diff --git a/.agents/skills/reverse-engineer-anything/SKILL.md b/.agents/skills/reverse-engineer-anything/SKILL.md index 07e1aa661..eaab0d44c 100644 --- a/.agents/skills/reverse-engineer-anything/SKILL.md +++ b/.agents/skills/reverse-engineer-anything/SKILL.md @@ -2,7 +2,7 @@ name: reverse-engineer-anything description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis. metadata: - version: "40" + version: "41" --- # REA @@ -61,12 +61,24 @@ explicit path or endpoint and do not need it. consult the NativeAOT workflow in `references/native-and-artifacts.md` for optional metadata recovery and its supported host/layout boundary. - User-owned browser page already open: `list_browser_targets`. -- Retained HAR/native mitmproxy capture: `inspect_web_network_capture`. Select +- Fiddler Everywhere traffic or a native `.saz` capture: read the + [Fiddler workflow](references/runtime-observation.md#fiddler-everywhere-traffic-debugging). + Inspect saved SAZ with `inspect_web_network_capture` and `format: "saz"`; + connect Everywhere's separate MCP server for live traffic. +- Retained HAR/SAZ/native mitmproxy/aioquic qlog capture: `inspect_web_network_capture`. Select original record ordinals when useful; inspect producer fields and byte/number sidecars without fetching recorded URLs or claiming live attribution. See [historical captures](https://github.com/morluto/rea/blob/main/docs/guides/web/web-network-captures.md) for the exact upstream - profile and credential exclusions. + profile and credential exclusions. Qlog support starts with aioquic 1.5.0 + JSON 0.3; stream coverage and endpoint loss declarations do not recover bodies + or establish network loss. Prefer detail summary, then kind qlog trace/stream + pages; select one trace, stream ID and direction for contribution/range pages. + Facts retain all-recorded-events-before-selection scope. Other qlog layouts + and PCAP correlation are unsupported. - User-owned Electron runtime already open: `list_electron_targets`. +- Packet-field discovery: `inspect_packet_fields` searches installed protocols + and field names/types before choosing fields for `inspect_packet_capture`. + Query/page the relevant records; registrations do not establish observed traffic. - Recorded packet captures: `inspect_packet_capture` with selected TShark fields, display filters and decode-as rules. Requires Linux, util-linux prlimit and `REA_TSHARK_COMMAND`; see [capture guide](https://github.com/morluto/rea/blob/main/docs/guides/data/packet-captures.md). @@ -74,6 +86,15 @@ explicit path or endpoint and do not need it. frames; use `match_offset` / `match_limit` for later pages, or explicit null limit for complete matching output. Preserve the source digest across pages. This does not perform live capture. + For address/DNS/SNI/protocol summaries use `inspect_pcap_capture` with MCP + detail summary, then retained kind pcap pages. Requires Wireshark 4.x tshark + and capinfos, with Linux prlimit or Windows Job Objects; see + [packet summaries](https://github.com/morluto/rea/blob/main/docs/guides/data/pcap-analysis.md). + Select an exact DNS question for address pages; page exhaustion does not prove + network completeness. This reads recordings and does not acquire traffic. +- Decoder discovery: `inspect_signal_decoders` searches installed decoder IDs + or selected decoder help, including channels and options. Query and page the + relevant details before choosing settings; this does not scan hardware. - Recorded logic/signal traces: `decode_signal_recording` with explicit decoder, channel and protocol settings. On Linux with util-linux prlimit, supply sigrok-cli 0.7.2 through `REA_SIGROK_COMMAND`; see [recording guide](https://github.com/morluto/rea/blob/main/docs/guides/signals/signal-recordings.md). diff --git a/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md b/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md index b024521d3..c98618964 100644 --- a/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md +++ b/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md @@ -83,6 +83,14 @@ names, the native API record, and value-flow summaries. Pseudocode offsets and l code units; use the returned `next_offset` for continuation. Provider limitations and unavailable facts remain explicit; the complete parent Evidence is retained. +`inspect_macho` on a large framework returns megabytes of imports and exports. +Select `detail: "summary"` for slice identity, UUID and per-collection counts, +then page rows with `view: {kind: "macho", facet: "exports", offset: 0, limit: 64}` +and `normalized_result.parent_evidence_id`. Facets are entrypoints, +architectures, build_metadata, load_commands, dependencies, imports, exports, +segments and provenance. `source_exhaustive: false` means unreturned symbols +may exist. + To see which functions or Objective-C methods a Mach-O actually calls in one run, use `observe_native_calls` with explicit breakpoints and a bounded `duration_ms`/`max_events`. It launches a new process under LLDB, so the target @@ -111,6 +119,8 @@ loaded bytes, file mappings, relocations and the entry against the immutable snapshot. Keep `mismatch` and `unsupported` explicit. Verified import covers the reported static image, not runtime DOS or PC-98 hardware behavior. +For Ghidra decompilation, `procedure_pseudo_code` also accepts `procedure: "file-offset:0x..."`; CLI `rea decompile --file-offset=0x... --provider ghidra` resolves the source byte offset internally. An unresolved 0x-prefixed numeric procedure selector also falls back to a unique file mapping. Existing symbols and analysis addresses win; multiple mappings fail as ambiguous. Preserve the returned file-offset and address locations and raw selection observations. ELF virtual addresses are distinct from file offsets; never assume an arbitrary offset plus image base is an analysis address. + Use `read_bytes` for initialized analysis memory and `address_to_file_offset` to anchor one observed address to original file bytes. Loader fixups can change a word; a source offset does not imply byte equality. Complete function body ranges @@ -194,8 +204,9 @@ every executable in the bundle. It also lists missing or weak loads and earlier `architecture`. System paths stay undetermined because the dyld shared cache provides them. -Use `extract_artifact` when materialized files are needed. It takes no arguments -and materializes all regular files into a fresh temporary directory chosen by +Use `extract_artifact` when materialized files are needed. It extracts the active +target and accepts optional `integrity_policy`; see the [MCP contracts](https://github.com/morluto/rea/blob/main/docs/reference/mcp-contracts.md). +It materializes all regular files into a fresh temporary directory chosen by REA. Symlinks and encrypted entries are inventory facts, not extractable files. The result reports the materialized directory; callers do not choose the destination. No separate permission grant is needed. diff --git a/.agents/skills/reverse-engineer-anything/references/runtime-observation.md b/.agents/skills/reverse-engineer-anything/references/runtime-observation.md index 3e16a3e19..60bb88633 100644 --- a/.agents/skills/reverse-engineer-anything/references/runtime-observation.md +++ b/.agents/skills/reverse-engineer-anything/references/runtime-observation.md @@ -26,3 +26,18 @@ passive browser/Electron Evidence exist. Prefer captured-source digest identity; report path/digest disagreement as a mismatch and preserve ambiguity. Explicit path mappings are inference inputs and never broaden filesystem or CDP authority. A bundle observed at runtime does not prove every contained module executed. + +## Fiddler Everywhere traffic debugging + +For large saved captures, request `detail: "summary"`, then page retained Evidence +with `inspect_analysis_view` and `view: {kind: "capture", detail: "preview", offset: 0, limit: 20}`. +Select complete record pages only for needed headers, metadata or payloads; views +read the historical parent without repeating capture decoding. + +Inspect native `.saz` snapshots with `inspect_web_network_capture` and +`format: "saz"`; encrypted archives are unsupported. For live +traffic analysis, connect Everywhere's separate MCP server and use its +advertised session tools with an explicit `sessionsSource` (`LiveTraffic` or +`AgentCalls`). Preserve existing sessions and filters when inspecting a +recorded run. See the [capture and MCP guide](https://github.com/morluto/rea/blob/main/docs/guides/web/web-network-captures.md) +for the workflow and Telerik's public setup and traffic-debugging skills. diff --git a/.gitattributes b/.gitattributes index 1774c0113..b8247b27f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,6 @@ # Windows command fixtures retain their native line endings. *.cmd text eol=crlf + +# Preserve whitespace in original upstream licensing texts. +licenses/npm-runtime-notices.txt whitespace=-blank-at-eol diff --git a/.github/actions/portable-build-cache/action.yml b/.github/actions/portable-build-cache/action.yml index ad127ce3d..cee775ec5 100644 --- a/.github/actions/portable-build-cache/action.yml +++ b/.github/actions/portable-build-cache/action.yml @@ -1,14 +1,24 @@ name: Portable build cache -description: Reuse Turbo build outputs without serializing verification jobs. +description: Restore portable Turbo build outputs from the current run or cross-run cache. inputs: save: description: Save newly built outputs after the job succeeds. default: "false" + build_cache_artifact: + description: Reuse portable Turbo outputs uploaded by the current workflow run. + default: "" runs: using: composite steps: + - name: Download portable build outputs from this workflow run + if: inputs.build_cache_artifact != '' + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.build_cache_artifact }} + path: .turbo/cache/ - name: Resolve portable build task hashes id: plan + if: inputs.build_cache_artifact == '' shell: bash env: BUILD_CACHE_PREFIX: rea-portable-build-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.npmrc', '.nvmrc', 'package-lock.json') }} @@ -28,14 +38,14 @@ runs: console.log(`prefix=${process.env.BUILD_CACHE_PREFIX}-`); ' >> "$GITHUB_OUTPUT" - name: Restore portable build outputs - if: inputs.save != 'true' + if: inputs.build_cache_artifact == '' && inputs.save != 'true' uses: actions/cache/restore@v4 with: path: .turbo/cache/ key: ${{ steps.plan.outputs.key }} restore-keys: ${{ steps.plan.outputs.prefix }} - name: Restore and save portable build outputs - if: inputs.save == 'true' + if: inputs.build_cache_artifact == '' && inputs.save == 'true' uses: actions/cache@v4 with: path: .turbo/cache/ diff --git a/.github/workflows/ci-full-pr.yml b/.github/workflows/ci-full-pr.yml new file mode 100644 index 000000000..8f76a2ea2 --- /dev/null +++ b/.github/workflows/ci-full-pr.yml @@ -0,0 +1,18 @@ +name: Full PR qualification + +on: + pull_request: + branches: [main, "release/*"] + types: [labeled] + +permissions: + contents: read + actions: read + +jobs: + qualification: + name: Qualify labeled PR revision + if: github.event.label.name == 'ci:full' + uses: ./.github/workflows/ci.yml + with: + source_sha: ${{ github.sha }} diff --git a/.github/workflows/ci-timings.yml b/.github/workflows/ci-timings.yml new file mode 100644 index 000000000..30fa19464 --- /dev/null +++ b/.github/workflows/ci-timings.yml @@ -0,0 +1,46 @@ +name: CI timings + +on: + schedule: + - cron: "17 * * * *" + workflow_dispatch: + +concurrency: + group: ci-timings-${{ github.repository }} + cancel-in-progress: false + +permissions: + contents: read + actions: read + +jobs: + report: + name: Collect recent completed workflow attempts + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + # Consume only API data and execute batch code from the trusted default branch. + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + - uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + - name: Record queue, execution, and matched step timing + continue-on-error: true + env: + GH_TOKEN: ${{ github.token }} + CI_REPOSITORY: ${{ github.repository }} + run: node scripts/ci/job-timings-batch.mjs + - name: Upload CI timing artifacts + if: always() && hashFiles('.cache/ci-job-timings/*') != '' + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: ci-job-timings-batch + path: .cache/ci-job-timings/ + include-hidden-files: true + if-no-files-found: error + overwrite: true + retention-days: 14 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 082623684..ab930e32d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,42 +5,44 @@ on: branches: [main] pull_request: branches: [main, "release/*"] + schedule: + - cron: "23 0-2,4-23 * * *" + - cron: "23 3 * * *" workflow_dispatch: + workflow_call: + inputs: + source_sha: + description: Exact qualification source; must match the caller revision. + required: true + type: string permissions: contents: read concurrency: - group: ci-${{ github.event.pull_request.number || github.ref }} - # The latest main push verifies the full tree, including earlier changes. - # Publication uses its own release workflow and concurrency group. - cancel-in-progress: true + # Complete qualification finishes even while main receives more pushes. + # Main feedback also finishes, coalescing newer pushes to one pending run. + # Scheduled/manual main runs coalesce to one active and the latest pending; + # release and label-triggered qualification use exact-revision groups. + group: ci-${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || inputs.source_sha != '' || contains(github.event.pull_request.labels.*.name, 'ci:full')) && 'qualification' || 'feedback' }}-${{ inputs.source_sha || github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' && inputs.source_sha == '' && !contains(github.event.pull_request.labels.*.name, 'ci:full') }} env: HUSKY: "0" jobs: - pr-title: - name: Conventional PR title - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - name: Validate title for Release Please - env: - PR_TITLE: ${{ github.event.pull_request.title }} - run: >- - node -e 'const title = process.env.PR_TITLE ?? ""; - const conventional = /^(?:feat|fix|docs|refactor|perf|test|build|ci|chore|revert)(?:\([a-z0-9._/-]+\))?!?: .+/u; - if (!conventional.test(title)) { - console.error("PR title must use Conventional Commits, for example: feat: add historical source import"); - process.exit(1); - }' - changes: name: Classify changes runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + actions: read outputs: + tier: ${{ steps.plan.outputs.tier }} + qualification_run_id: ${{ steps.qualification.outputs.run_id }} code: ${{ steps.plan.outputs.code }} + sqlite: ${{ steps.plan.outputs.sqlite }} runtime: ${{ steps.plan.outputs.runtime }} package: ${{ steps.plan.outputs.package }} apple: ${{ steps.plan.outputs.apple }} @@ -59,26 +61,58 @@ jobs: nativeaot: ${{ steps.plan.outputs.nativeaot }} website: ${{ steps.plan.outputs.website }} matrix: ${{ steps.plan.outputs.matrix }} + test_selection: ${{ steps.plan.outputs.test_selection }} steps: - uses: actions/checkout@v4 with: + ref: ${{ inputs.source_sha || github.sha }} fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version-file: .nvmrc + - name: Bind qualification to the caller revision + if: inputs.source_sha != '' + env: + SOURCE_SHA: ${{ inputs.source_sha }} + run: | + test "${SOURCE_SHA}" = "${GITHUB_SHA}" + test "${SOURCE_SHA}" = "$(git rev-parse HEAD)" + - name: Find a verified ancestor for push selection + id: baseline + if: github.event_name == 'push' && inputs.source_sha == '' + env: + GH_TOKEN: ${{ github.token }} + HEAD_SHA: ${{ github.sha }} + CI_REPOSITORY: ${{ github.repository }} + CI_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: node scripts/ci/baseline.mjs + - name: Admit scheduled full qualification + id: qualification + if: github.event_name == 'schedule' && inputs.source_sha == '' + env: + GH_TOKEN: ${{ github.token }} + HEAD_SHA: ${{ github.sha }} + CI_REPOSITORY: ${{ github.repository }} + CI_REPOSITORY_ID: ${{ github.repository_id }} + CI_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + CI_FORCE_FULL: ${{ github.event.schedule == '23 3 * * *' }} + run: node scripts/ci/qualification.mjs - name: Select verification lanes id: plan env: - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - CI_FULL: ${{ contains(github.event.pull_request.labels.*.name, 'ci:full') }} + BASE_SHA: ${{ steps.baseline.outputs.base || github.event.pull_request.base.sha }} + BASELINE_REASON: ${{ steps.baseline.outputs.reason }} + HEAD_SHA: ${{ inputs.source_sha || github.event.pull_request.head.sha || github.sha }} + CI_FULL: ${{ inputs.source_sha != '' || contains(github.event.pull_request.labels.*.name, 'ci:full') }} + CI_SKIP_FULL: ${{ steps.qualification.outputs.run_full == 'false' }} run: node scripts/ci/plan.mjs static: name: Static checks needs: changes - if: ${{ !cancelled() }} + if: ${{ !cancelled() && needs.changes.outputs.tier != 'reused' }} runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Require successful change classification env: @@ -90,6 +124,9 @@ jobs: node-version-file: .nvmrc cache: npm - run: npm ci + - name: Validate workflow syntax and expressions + if: needs.changes.outputs.workflows == 'true' + run: go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 -shellcheck= -pyflakes= - if: needs.changes.outputs.code == 'true' run: npm run check:ci - if: needs.changes.outputs.code == 'true' @@ -114,6 +151,7 @@ jobs: needs: [changes, build] if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -129,7 +167,14 @@ jobs: with: name: rea-test-runtime path: . - - run: npm run test:ci:shard:run -- --shard=${{ matrix.shard }} + - name: Run complete portable suite with coverage + if: needs.changes.outputs.tier == 'full' + run: npm run test:ci:shard:run -- --shard=${{ matrix.shard }} + env: + REA_CI_TEST_HISTORY: .cache/ci-test-history/test-results.json + - name: Run complete portable suite for fast feedback + if: needs.changes.outputs.tier == 'fast' + run: npm run test:run -- --reporter=default --reporter=blob --shard=${{ matrix.shard }} env: REA_CI_TEST_HISTORY: .cache/ci-test-history/test-results.json - uses: actions/upload-artifact@v4 @@ -145,8 +190,20 @@ jobs: build: name: Build package needs: changes - if: needs.changes.outputs.code == 'true' + # Reusable provider workflows consume this run's portable build artifact, + # even when a workflow-only edit selects the lane without portable tests. + if: >- + needs.changes.outputs.code == 'true' || + needs.changes.outputs.browser == 'true' || + needs.changes.outputs.binary_layout == 'true' || + needs.changes.outputs.evm == 'true' || + needs.changes.outputs.javascript_recovery == 'true' || + needs.changes.outputs.recorded_crash == 'true' || + needs.changes.outputs.web_network == 'true' || + needs.changes.outputs.web_runtime == 'true' || + needs.changes.outputs.web_source_map == 'true' runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read actions: read @@ -160,21 +217,17 @@ jobs: - name: Reuse portable build outputs across runs uses: ./.github/actions/portable-build-cache with: - save: "true" + save: ${{ github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} - run: npm run test:prepare - - name: Find successful default-branch timing history + - name: Find available trusted full-suite timing history id: history continue-on-error: true env: GH_TOKEN: ${{ github.token }} CI_REPOSITORY: ${{ github.repository }} + CI_REPOSITORY_ID: ${{ github.repository_id }} CI_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - run: | - run_id="$(gh api --method GET \ - "repos/${CI_REPOSITORY}/actions/workflows/ci.yml/runs" \ - -f branch="${CI_DEFAULT_BRANCH}" -f event=push -f status=success -f per_page=1 \ - --jq '.workflow_runs[0].id // empty')" - echo "run-id=${run_id}" >> "${GITHUB_OUTPUT}" + run: node scripts/ci/test-history.mjs - name: Download previous timing report if: steps.history.outputs.run-id != '' continue-on-error: true @@ -210,15 +263,18 @@ jobs: retention-days: 7 sqlite-runtime: - needs: [changes, build] - if: needs.changes.outputs.code == 'true' + # Preserve all selected coverage, but admit expensive host/provider work + # only after static validation. Portable tests still provide early feedback. + needs: [changes, static, build] + if: needs.changes.outputs.sqlite == 'true' uses: ./.github/workflows/sqlite-runtime.yml test: - name: Test (coverage + timing) + name: Portable tests needs: [changes, test-shard] - if: ${{ !cancelled() }} + if: ${{ !cancelled() && needs.changes.outputs.tier != 'reused' }} runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Require successful change classification env: @@ -241,7 +297,7 @@ jobs: merge-multiple: true - name: Merge coverage, JUnit, and timing reports id: merge - if: needs.changes.outputs.code == 'true' && success() + if: needs.changes.outputs.code == 'true' && needs.changes.outputs.tier == 'full' && success() run: >- npm run test:ci:merge -- --coverage.reportsDirectory=coverage @@ -251,13 +307,28 @@ jobs: --reporter=default --reporter=junit --reporter=json + --reporter=./scripts/ci/test-timing-reporter.mjs + --outputFile.junit=test-results.xml + --outputFile.json=test-results.json + - name: Merge fast-suite JUnit and timing reports + id: merge-fast + if: needs.changes.outputs.code == 'true' && needs.changes.outputs.tier == 'fast' && success() + run: >- + npm exec -- vitest --merge-reports + --reporter=default + --reporter=junit + --reporter=json + --reporter=./scripts/ci/test-timing-reporter.mjs --outputFile.junit=test-results.xml --outputFile.json=test-results.json - name: Summarize slowest test files - if: needs.changes.outputs.code == 'true' && !cancelled() && hashFiles('test-results.json') != '' + if: needs.changes.outputs.code == 'true' && !cancelled() && hashFiles('test-timings.json') != '' env: SHARD_RESULT: ${{ needs.test-shard.result }} - MERGE_RESULT: ${{ steps.merge.outcome }} + MERGE_RESULT: ${{ needs.changes.outputs.tier == 'full' && steps.merge.outcome || steps.merge-fast.outcome }} + CI_VERIFY_TEST_INVENTORY: "true" + CI_TEST_SELECTION: ${{ needs.changes.outputs.test_selection }} + CI_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: node scripts/ci/test-report.mjs - uses: actions/upload-artifact@v4 if: needs.changes.outputs.code == 'true' && !cancelled() && hashFiles('test-results.json') != '' @@ -266,11 +337,14 @@ jobs: path: | test-results.xml test-results.json + test-timings.json coverage/ + .cache/ci-test-selection/report.json + include-hidden-files: true if-no-files-found: error retention-days: 30 - name: Publish successful timing history - if: needs.changes.outputs.code == 'true' && success() && needs.test-shard.result == 'success' + if: needs.changes.outputs.code == 'true' && needs.changes.outputs.tier == 'full' && success() && needs.test-shard.result == 'success' uses: actions/upload-artifact@v4 with: name: test-timings @@ -287,7 +361,7 @@ jobs: conformance-fixtures: name: Source-built conformance fixtures - needs: changes + needs: [changes, static] if: needs.changes.outputs.fixtures == 'true' runs-on: ubuntu-latest timeout-minutes: 10 @@ -298,7 +372,7 @@ jobs: windows-native-build: name: Build bundled Windows x64 native controls - needs: changes + needs: [changes, static] if: needs.changes.outputs.runtime == 'true' runs-on: ubuntu-latest timeout-minutes: 10 @@ -334,7 +408,7 @@ jobs: package-e2e: name: Native package baseline (${{ matrix.platform }} ${{ matrix.architecture }}) - needs: [changes, build, windows-native-build] + needs: [changes, static, build, windows-native-build] if: needs.changes.outputs.runtime == 'true' strategy: fail-fast: false @@ -373,6 +447,8 @@ jobs: name: windows-native-controls path: native/windows/build/ - run: npm run verify:windows-native:artifact + - name: Verify NativeAOT diagnostic applicability on this host + run: npm run test:focused -- tests/evaluation/package/nativeAotDiagnostics.test.ts - name: Resolve npm cache before verifier HOME isolation id: npm-cache run: | @@ -381,13 +457,24 @@ jobs: - run: npm run verify:package env: npm_config_cache: ${{ steps.npm-cache.outputs.path }} + REA_VERIFIED_PACKAGE_DIRECTORY: ${{ needs.changes.outputs.tier == 'full' && matrix.platform == 'linux' && matrix.architecture == 'x64' && '.cache/verified-package' || '' }} - name: Verify real Node Inspector discovery and observation timeout-minutes: 10 run: npm run verify:inspector + - name: Retain the exact qualified release package + if: needs.changes.outputs.tier == 'full' && matrix.platform == 'linux' && matrix.architecture == 'x64' + uses: actions/upload-artifact@v4 + with: + name: verified-release-package + path: .cache/verified-package/ + include-hidden-files: true + if-no-files-found: error + overwrite: true + retention-days: 7 apple-artifacts: name: Real Apple artifact CLI/MCP E2E - needs: [changes, build] + needs: [changes, static, build] if: needs.changes.outputs.apple == 'true' runs-on: macos-15 timeout-minutes: 15 @@ -435,7 +522,7 @@ jobs: reconstruction-readiness: name: Reconstruction readiness - needs: changes + needs: [changes, static] if: needs.changes.outputs.readiness == 'true' runs-on: ubuntu-latest timeout-minutes: 15 @@ -464,7 +551,7 @@ jobs: windows-curated: name: Windows capability and package lane - needs: [changes, build, windows-native-build] + needs: [changes, static, build, windows-native-build] if: needs.changes.outputs.package == 'true' runs-on: windows-latest timeout-minutes: 25 @@ -509,6 +596,7 @@ jobs: tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts tests/boundary/filesystem/setupUnavailableProvider.test.ts tests/boundary/filesystem/windowsNpxRegistration.test.ts + tests/acceptance/setup/homeDirectoryFallback.test.ts tests/boundary/filesystem/webScriptManifestPaths.test.ts tests/boundary/process/ProcessEvidence.host.test.ts tests/acceptance/webModuleCli.test.ts @@ -575,6 +663,7 @@ jobs: needs: changes if: needs.changes.outputs.docs == 'true' runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -596,73 +685,78 @@ jobs: skills/reverse-engineer-anything if-no-files-found: error - workflows: - name: Validate workflows - needs: changes - if: needs.changes.outputs.workflows == 'true' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Validate workflow syntax and expressions - run: go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 -shellcheck= -pyflakes= - browser: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.browser == 'true' uses: ./.github/workflows/real-browser.yml + with: + build_cache_artifact: rea-build-cache binary_layout: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.binary_layout == 'true' uses: ./.github/workflows/real-binary-layout.yml + with: + build_cache_artifact: rea-build-cache evm: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.evm == 'true' uses: ./.github/workflows/real-evm-interface.yml + with: + build_cache_artifact: rea-build-cache javascript_recovery: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.javascript_recovery == 'true' uses: ./.github/workflows/real-javascript-recovery.yml + with: + build_cache_artifact: rea-build-cache recorded_crash: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.recorded_crash == 'true' uses: ./.github/workflows/real-recorded-crash.yml + with: + build_cache_artifact: rea-build-cache web_network: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.web_network == 'true' uses: ./.github/workflows/real-web-network-captures.yml + with: + build_cache_artifact: rea-build-cache web_runtime: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.web_runtime == 'true' uses: ./.github/workflows/real-web-runtime.yml + with: + build_cache_artifact: rea-build-cache web_source_map: - needs: changes + needs: [changes, static, build] if: needs.changes.outputs.web_source_map == 'true' uses: ./.github/workflows/real-web-source-map.yml + with: + build_cache_artifact: rea-build-cache nativeaot: - needs: changes + needs: [changes, static] if: needs.changes.outputs.nativeaot == 'true' uses: ./.github/workflows/nativeaot-fixtures.yml website: - needs: changes + needs: [changes, static] if: needs.changes.outputs.website == 'true' uses: ./.github/workflows/website-check.yml required: name: CI required - if: ${{ !cancelled() }} + if: ${{ always() }} needs: [ changes, - pr-title, static, build, test-shard, @@ -675,7 +769,6 @@ jobs: reconstruction-readiness, windows-curated, docs, - workflows, browser, binary_layout, evm, @@ -688,12 +781,24 @@ jobs: website, ] runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: .nvmrc - name: Require every selected lane to pass + id: gate env: CI_JOBS: ${{ toJSON(needs) }} + CI_QUALIFICATION_DIRECTORY: .cache/ci-qualification run: node scripts/ci/required.mjs + - name: Upload full qualification receipt artifact + if: needs.changes.outputs.tier == 'full' && success() + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.gate.outputs.receipt_name }} + path: ${{ steps.gate.outputs.receipt_path }} + if-no-files-found: error + overwrite: true + retention-days: 7 diff --git a/.github/workflows/nativeaot-fixtures.yml b/.github/workflows/nativeaot-fixtures.yml index e819ca5fb..ce7dc1ea1 100644 --- a/.github/workflows/nativeaot-fixtures.yml +++ b/.github/workflows/nativeaot-fixtures.yml @@ -12,7 +12,8 @@ jobs: name: Build Windows x64 NativeAOT fixture # .NET 8.0.22's bundled linker discovery supports VS 2019/2022. runs-on: windows-2022 - timeout-minutes: 15 + # Two bounded restore attempts and one compile can each take five minutes. + timeout-minutes: 20 env: DOTNET_CLI_TELEMETRY_OPTOUT: "1" DOTNET_PROCESSOR_COUNT: "1" diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml new file mode 100644 index 000000000..abe98bb48 --- /dev/null +++ b/.github/workflows/pr-title.yml @@ -0,0 +1,29 @@ +name: PR title + +on: + pull_request: + branches: [main, "release/*"] + types: [opened, synchronize, reopened, edited] + +permissions: {} + +concurrency: + group: pr-title-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + pr-title: + name: Conventional PR title + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - name: Validate title for Release Please + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: >- + node -e 'const title = process.env.PR_TITLE ?? ""; + const conventional = /^(?:feat|fix|docs|refactor|perf|test|build|ci|chore|revert)(?:\([a-z0-9._/-]+\))?!?: .+/u; + if (!conventional.test(title)) { + console.error("PR title must use Conventional Commits, for example: feat: add historical source import"); + process.exit(1); + }' diff --git a/.github/workflows/real-binary-layout.yml b/.github/workflows/real-binary-layout.yml index e8c244de6..5cec952ce 100644 --- a/.github/workflows/real-binary-layout.yml +++ b/.github/workflows/real-binary-layout.yml @@ -8,14 +8,16 @@ on: type: boolean default: false workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" permissions: contents: read -concurrency: - group: real-binary-layout-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - env: NODE_OPTIONS: --max-old-space-size=768 HUSKY: "0" @@ -33,6 +35,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - name: Acquire exact upstream libraries in an isolated runner environment shell: bash run: | diff --git a/.github/workflows/real-browser.yml b/.github/workflows/real-browser.yml index 76ba2e4a6..912fdafb1 100644 --- a/.github/workflows/real-browser.yml +++ b/.github/workflows/real-browser.yml @@ -2,12 +2,14 @@ name: Real browser verification on: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" workflow_dispatch: -concurrency: - group: real-browser-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - env: HUSKY: "0" @@ -26,6 +28,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - run: npm run verify:browser env: REA_BROWSER_EXECUTABLE: /usr/bin/google-chrome diff --git a/.github/workflows/real-evm-interface.yml b/.github/workflows/real-evm-interface.yml index 9e4cddeb4..dfdd3970f 100644 --- a/.github/workflows/real-evm-interface.yml +++ b/.github/workflows/real-evm-interface.yml @@ -3,14 +3,16 @@ name: Real offline EVM interface on: workflow_dispatch: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" permissions: contents: read -concurrency: - group: real-evm-interface-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - env: NODE_OPTIONS: --max-old-space-size=768 HUSKY: "0" @@ -27,6 +29,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - name: Acquire unchanged fixture compiler in isolated runner storage shell: bash run: | diff --git a/.github/workflows/real-javascript-recovery.yml b/.github/workflows/real-javascript-recovery.yml index 4fee667d8..817dc4dc0 100644 --- a/.github/workflows/real-javascript-recovery.yml +++ b/.github/workflows/real-javascript-recovery.yml @@ -2,15 +2,17 @@ name: Real JavaScript recovery on: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" workflow_dispatch: permissions: contents: read -concurrency: - group: javascript-recovery-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - env: HUSKY: "0" NODE_OPTIONS: "--max-old-space-size=768" @@ -28,6 +30,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - name: Fetch pinned Wakaru release into the job workspace shell: bash run: | diff --git a/.github/workflows/real-packet-capture.yml b/.github/workflows/real-packet-capture.yml index 8faf9ba99..b5e9f9201 100644 --- a/.github/workflows/real-packet-capture.yml +++ b/.github/workflows/real-packet-capture.yml @@ -7,6 +7,13 @@ on: - "tests/boundary/cli/captureCleanup.test.ts" - "tests/boundary/mcp/packetCaptureMcp.test.ts" - "src/captures/**" + - "src/pcap/**" + - "src/domain/pcap/**" + - "src/domain/analysisView/pcapCaptureView.ts" + - "src/application/pcap/**" + - "src/contracts/pcap/**" + - "src/server/registerPcapTools.ts" + - "tests/boundary/pcap/**" - "src/domain/captures/**" - "src/application/captures/**" - "src/contracts/captures/**" @@ -44,7 +51,8 @@ jobs: - run: sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tshark util-linux python3 - run: npm ci - run: npm run build:cached - - run: npm run test:focused -- src/process/LinuxResourceLimits.test.ts tests/boundary/captures/captureProvider.test.ts tests/boundary/captures/captureDescriptorCleanup.test.ts tests/boundary/captures/resourceLimits.test.ts tests/boundary/captures/packetOutput.test.ts tests/boundary/mcp/packetCaptureMcp.test.ts tests/boundary/cli/captureCleanup.test.ts + - run: npm run test:focused -- tests/boundary/captures/fieldDiscovery.test.ts src/process/LinuxResourceLimits.test.ts tests/boundary/captures/captureProvider.test.ts tests/boundary/captures/captureDescriptorCleanup.test.ts tests/boundary/captures/resourceLimits.test.ts tests/boundary/captures/packetOutput.test.ts tests/boundary/mcp/packetCaptureMcp.test.ts tests/boundary/cli/captureCleanup.test.ts - run: node scripts/verify-packet-capture.mjs env: REA_TSHARK_COMMAND: /usr/bin/tshark + REA_CAPINFOS_COMMAND: /usr/bin/capinfos diff --git a/.github/workflows/real-recorded-crash.yml b/.github/workflows/real-recorded-crash.yml index d4410bb24..04467a608 100644 --- a/.github/workflows/real-recorded-crash.yml +++ b/.github/workflows/real-recorded-crash.yml @@ -3,14 +3,16 @@ name: Real recorded crash evidence on: workflow_dispatch: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" permissions: contents: read -concurrency: - group: real-recorded-crash-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - env: NODE_OPTIONS: --max-old-space-size=768 HUSKY: "0" @@ -30,6 +32,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - name: Install GDB on the disposable CI runner shell: bash run: | diff --git a/.github/workflows/real-signal-recording.yml b/.github/workflows/real-signal-recording.yml index 5ec413e72..cc902037e 100644 --- a/.github/workflows/real-signal-recording.yml +++ b/.github/workflows/real-signal-recording.yml @@ -44,7 +44,7 @@ jobs: - run: sudo apt-get update && sudo apt-get install -y sigrok-cli util-linux python3 - run: npm ci - run: npm run build:cached - - run: npm run test:focused -- src/process/LinuxResourceLimits.test.ts src/domain/signals/annotationTextWindow.test.ts tests/boundary/signals/recordingProvider.test.ts tests/boundary/signals/recordingDescriptorCleanup.test.ts tests/boundary/signals/resourceLimits.test.ts tests/boundary/mcp/signalRecordingMcp.test.ts tests/boundary/cli/signalCleanup.test.ts + - run: npm run test:focused -- tests/boundary/signals/decoderDiscovery.test.ts src/process/LinuxResourceLimits.test.ts src/domain/signals/annotationTextWindow.test.ts tests/boundary/signals/recordingProvider.test.ts tests/boundary/signals/recordingDescriptorCleanup.test.ts tests/boundary/signals/resourceLimits.test.ts tests/boundary/mcp/signalRecordingMcp.test.ts tests/boundary/cli/signalCleanup.test.ts - run: node scripts/verify-signal-recording.mjs env: REA_SIGROK_COMMAND: /usr/bin/sigrok-cli diff --git a/.github/workflows/real-web-network-captures.yml b/.github/workflows/real-web-network-captures.yml index b888674f7..d41bb37a5 100644 --- a/.github/workflows/real-web-network-captures.yml +++ b/.github/workflows/real-web-network-captures.yml @@ -3,14 +3,16 @@ name: Real historical web network captures on: workflow_dispatch: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" permissions: contents: read -concurrency: - group: real-web-network-captures-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - env: HUSKY: "0" NODE_OPTIONS: --max-old-space-size=768 @@ -29,6 +31,8 @@ jobs: run: npm install --global npm@11.16.0 - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - name: Acquire fixed upstream native profile in runner temporary storage shell: bash run: | diff --git a/.github/workflows/real-web-runtime.yml b/.github/workflows/real-web-runtime.yml index c600e895c..2575c55f9 100644 --- a/.github/workflows/real-web-runtime.yml +++ b/.github/workflows/real-web-runtime.yml @@ -1,12 +1,15 @@ name: Real website runtime attribution on: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" workflow_dispatch: permissions: contents: read -concurrency: - group: real-web-runtime-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: HUSKY: "0" jobs: @@ -21,6 +24,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - run: npm run verify:browser:runtime env: REA_BROWSER_EXECUTABLE: /usr/bin/google-chrome diff --git a/.github/workflows/real-web-source-map.yml b/.github/workflows/real-web-source-map.yml index 483b2f712..8e0869eb7 100644 --- a/.github/workflows/real-web-source-map.yml +++ b/.github/workflows/real-web-source-map.yml @@ -1,12 +1,15 @@ name: Real website source-map verification on: workflow_call: + inputs: + build_cache_artifact: + description: Portable build cache artifact from the calling CI run. + required: false + type: string + default: "" workflow_dispatch: permissions: contents: read -concurrency: - group: real-web-source-map-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: HUSKY: "0" jobs: @@ -21,6 +24,8 @@ jobs: cache: npm - run: npm ci - uses: ./.github/actions/portable-build-cache + with: + build_cache_artifact: ${{ inputs.build_cache_artifact }} - name: Install the pinned compiler into an isolated fixture directory run: npm install --prefix "$RUNNER_TEMP/rea-web-source-map-compiler" --no-audit --no-fund --package-lock=false esbuild@0.25.10 - run: npm run verify:browser:source-maps diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c60f32a2c..7cc798cfa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -290,13 +290,25 @@ jobs: if: inputs.phase == 'prepare' && steps.release.outputs.prs_created == 'true' run: npm run docs:check && git diff --exit-code - publish: - name: Publish to npm + qualification: + name: Qualify exact release revision needs: [merged-release, release-please] if: >- always() && !cancelled() && ((needs.merged-release.result == 'success' && needs.merged-release.outputs.release_created == 'true') || (needs.release-please.result == 'success' && inputs.phase == 'publish' && needs.release-please.outputs.release_created == 'true')) + permissions: + contents: read + actions: read + uses: ./.github/workflows/ci.yml + with: + source_sha: ${{ needs.merged-release.outputs.sha || needs.release-please.outputs.sha }} + + publish: + name: Publish to npm + needs: [merged-release, release-please, qualification] + if: >- + always() && !cancelled() && needs.qualification.result == 'success' runs-on: ubuntu-latest permissions: contents: read @@ -315,17 +327,20 @@ jobs: - run: npm ci - - name: Prepare Windows native build toolchain - run: sudo apt-get update && sudo apt-get install --no-install-recommends -y g++-mingw-w64-x86-64 + - name: Download the exact qualified package + uses: actions/download-artifact@v4 + with: + name: verified-release-package + path: .cache/verified-package/ - - name: Build and verify bundled Windows native controls - run: npm run build:windows-native && npm run verify:windows-native:artifact - - - name: Verify packaged release before publishing - run: npm run verify:package + - name: Verify qualified package provenance and digest + id: package + run: node scripts/ci/verified-package.mjs validate .cache/verified-package - name: Publish shell: bash + env: + VERIFIED_PACKAGE_TARBALL: ${{ steps.package.outputs.tarball }} run: | version="$(node --input-type=module -e 'import packageJson from "./package.json" with { type: "json" }; process.stdout.write(packageJson.version)')" published_version="$(npm view "rea-agents@${version}" version --json 2>/dev/null || true)" @@ -333,7 +348,7 @@ jobs: echo "rea-agents@${version} is already published; verifying the existing package." else tag="$(node scripts/release-npm-tag.mjs "${version}")" - npm publish --access public --tag "${tag}" + npm publish "${VERIFIED_PACKAGE_TARBALL}" --access public --tag "${tag}" fi - name: Verify published CLI from npm diff --git a/.github/workflows/website-check.yml b/.github/workflows/website-check.yml index 8931ba418..2a2c5406f 100644 --- a/.github/workflows/website-check.yml +++ b/.github/workflows/website-check.yml @@ -7,10 +7,6 @@ on: permissions: contents: read -concurrency: - group: website-check-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - jobs: check: name: Website checks diff --git a/.gitignore b/.gitignore index 90d431ec0..0d006e13f 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ coverage/ .vitest/ .vitest-reports/ test-results.xml +test-timings.json .turbo/ .cache/ docs/.vitepress/cache/ @@ -72,3 +73,5 @@ Thumbs.db # Complete static website output, including generated language editions. website/_site/ +# Temporary translation output prepared before replacing the complete site. +website/.i18n-*/ diff --git a/.jscpd.json b/.jscpd.json index c8e89d791..25608bfac 100644 --- a/.jscpd.json +++ b/.jscpd.json @@ -1,5 +1,5 @@ { - "threshold": 3.0, + "threshold": 3.5, "reporters": ["consoleFull"], "ignore": [ "node_modules/**", diff --git a/README.md b/README.md index c60e3b810..aed9d315b 100644 --- a/README.md +++ b/README.md @@ -150,29 +150,30 @@ CLI commands use the same workflows. REA requires Node.js 22.x (>=22.19), 24.x (>=24.11), or 26+, plus npm. Additional tools and host support depend on the target: -| Target | What REA returns | Requirements and guide | -| ---------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://rea.tools/guides/native/) | -| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/guides/native/binary-diagnostics.md) | -| Go binaries | Embedded compiler version, modules, replacements and build settings | Built-in static ELF/PE/thin Mach-O inspection; no Go installation required | -| WASM artifact | Validation, sections, exact import/export WAT forms and decoded WAT | Caller-supplied WABT 1.0.42; `inspect_wasm_artifact` | -| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/guides/evm/evm-bytecode.md) | -| SQLite databases | Tables, columns, indexes, views, triggers and selected ordinary-table rows | Local database/WAL snapshot; Node.js 24.x >=24.15 or 26+ with native SQLite limits | -| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools on Linux x64; optional GDB/pwndbg; [recorded crashes](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://rea.tools/guides/javascript/) | -| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://rea.tools/guides/browser/) | -| Saved network captures | Requests, responses, exposed payloads and source locations | HAR; mitmdump on Linux for native mitmproxy captures; [capture guide](docs/guides/web/web-network-captures.md) | -| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/guides/managed/managed-code-analysis.md) | -| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS/Windows x64; [Android guide](docs/guides/android/android-analysis.md) | -| Android devices | Devices, packages, processes, logs, dumps, screen captures, and APK/file transfers | Caller-supplied adb (emulator or hardware); [ADB guide](docs/guides/android/adb-device-analysis.md) | -| JEB projects | Engine-backed project units, artifact digests and type/method pseudo-code | A caller-started JEB client serving MCP, selected with REA_JEB_MCP_URL; [JEB guide](docs/providers/jeb-analysis.md) | -| Android resources | Decoded manifest, string tables, locales and version facts | Caller-supplied Apktool launcher; [resource guide](docs/guides/android/apktool-resource-analysis.md) | -| Flutter apps | Dart snapshot hash, per-ABI library digests and engine build provenance | None (static APK parsing); [Flutter guide](docs/guides/android/flutter-analysis.md) | -| Firmware | Regions, extraction results and native-analysis handoffs | Binwalk / Unblob on Linux; [firmware guide](docs/guides/firmware/firmware-analysis.md) | -| Recorded packets | Selected fields, repeated values, filters and decode-as rules | Linux: TShark 4.x + prlimit; [capture guide](docs/guides/data/packet-captures.md) | -| Recorded logic signals | Decoder annotations, sample ranges and diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [signal recordings](docs/guides/signals/signal-recordings.md) | +| Target | What REA returns | Requirements and guide | +| ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | +| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://rea.tools/guides/native/) | +| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/guides/native/binary-diagnostics.md) | +| Go binaries | Embedded compiler version, modules, replacements and build settings | Built-in static ELF/PE/thin Mach-O inspection; no Go installation required | +| WASM artifact | Validation, sections, exact import/export WAT forms and decoded WAT | Caller-supplied WABT 1.0.42; `inspect_wasm_artifact` | +| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier on Linux x64; [offline EVM guide](docs/guides/evm/evm-bytecode.md) | +| SQLite databases | Tables, columns, indexes, views, triggers and selected ordinary-table rows | Local database/WAL snapshot; Node.js 24.x >=24.15 or 26+ with native SQLite limits | +| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools on Linux x64; optional GDB/pwndbg; [recorded crashes](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://rea.tools/guides/javascript/) | +| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://rea.tools/guides/browser/) | +| Saved network captures | Requests, responses, exposed payloads and source locations | HAR or Fiddler Everywhere SAZ; mitmdump on Linux for native mitmproxy; [capture guide](docs/guides/web/web-network-captures.md) | +| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | None (static only); [managed-code guide](docs/guides/managed/managed-code-analysis.md) | +| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS/Windows x64; [Android guide](docs/guides/android/android-analysis.md) | +| Android devices | Devices, packages, processes, logs, dumps, screen captures, and APK/file transfers | Caller-supplied adb (emulator or hardware); [ADB guide](docs/guides/android/adb-device-analysis.md) | +| JEB projects | Engine-backed project units, artifact digests and type/method pseudo-code | A caller-started JEB client serving MCP, selected with REA_JEB_MCP_URL; [JEB guide](docs/providers/jeb-analysis.md) | +| Android resources | Decoded manifest, string tables, locales and version facts | Caller-supplied Apktool launcher; [resource guide](docs/guides/android/apktool-resource-analysis.md) | +| Flutter apps | Dart snapshot hash, per-ABI library digests and engine build provenance | None (static APK parsing); [Flutter guide](docs/guides/android/flutter-analysis.md) | +| Firmware | Regions, extraction results and native-analysis handoffs | Binwalk / Unblob on Linux; [firmware guide](docs/guides/firmware/firmware-analysis.md) | +| Recorded packets | Selected fields, repeated values, filters and decode-as rules | Linux: TShark 4.x + prlimit; [capture guide](docs/guides/data/packet-captures.md) | +| Packet summaries | Endpoints, DNS, TLS SNI, protocol distribution and HTTP requests | Caller-supplied tshark and capinfos (Linux-verified); [pcap guide](docs/guides/data/pcap-analysis.md) | +| Recorded logic signals | Decoder annotations, sample ranges and diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [signal recordings](docs/guides/signals/signal-recordings.md) | | Packages and resources | File inventories, digests, plists, Apple bundle anatomy and extracted resources | [Artifact and JavaScript guide](docs/guides/javascript/javascript-artifact-reconstruction.md), [Apple applications](docs/guides/apple/apple-application-analysis.md) | -| Process behavior | Terminal output, interactions, exit and filesystem observations, and run comparisons | Linux/macOS with a native PTY; [process capture](docs/guides/runtime/process-capture.md) | +| Process behavior | Terminal output, interactions, exit and filesystem observations, and run comparisons | Linux/macOS with a native PTY; [process capture](docs/guides/runtime/process-capture.md) | Static JavaScript and .NET inspection read the supplied files without running the application. Runtime capture runs or interacts with the selected target @@ -321,7 +322,7 @@ Report vulnerabilities through [SECURITY.md](SECURITY.md). ## Star history -🎉 **110,000 GitHub stars — thank you!** +🎉 **170,000 GitHub stars — thank you!** Thanks to everyone using REA, reporting bugs, requesting features, testing builds, and contributing fixes. diff --git a/README_ar.md b/README_ar.md index fca15e7d0..8037f142f 100644 --- a/README_ar.md +++ b/README_ar.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup يتطلب REA إصدار Node.js 22.x (>=22.19) أو 24.x (>=24.11) أو 26+، إضافة إلى npm. تعتمد الأدوات الإضافية والأنظمة المضيفة المدعومة على الهدف: -| الهدف | ما يعيده REA | المتطلبات والدليل | -| ------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA؛ [تحليل الشيفرة الأصلية](https://rea.tools/ar/guides/native/) | -| بنية ELF دون تشغيل | الأقسام والمقاطع والرموز ومعلومات إعادة التموضع الأصلية، وآليات الحماية المحتملة المستدلّ عليها بالفحص الثابت | pwntools يوفّره المستدعي على Linux x64؛ [تشخيص الملفات الثنائية](docs/guides/native/binary-diagnostics.md) | -| شيفرة EVM البايتية | محددات التوجيه، وإزاحات البايتات، والمعاملات المستنتجة، وقابلية تغيير الحالة | مدخل محلي يحمل بايتات خامًا أو تمثيلًا سداسيًا عشريًا على Linux x64؛ [دليل EVM دون تشغيل](docs/guides/evm/evm-bytecode.md) | -| أعطال Linux المسجّلة | سجلات note الخام، ومسجّلات المعالج/الإشارات لكل خيط مسجّل، وترشيحات اختيارية لخرائط الذاكرة | pwntools يوفّره المستدعي على Linux x64؛ GDB/pwndbg اختياريان؛ [الأعطال المسجّلة](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | الوحدات، وعمليات الاستيراد، وخرائط المصدر، والمسارات، وIPC، وعلاقات إضافات الشيفرة الأصلية | Node.js وnpm؛ [تحليل التطبيقات](https://rea.tools/ar/guides/javascript/) | -| المواقع | بنية الصفحة، والسكربتات، وملاحظات الشبكة، ولقطات الشاشة المطلوبة | متصفح من عائلة Chrome؛ [تحليل المتصفح](https://rea.tools/ar/guides/browser/) | -| تسجيلات الشبكة المحفوظة | الطلبات، والاستجابات، ومحتويات الحمولة المتاحة، ومواضعها في المصدر | HAR؛ وmitmdump على Linux لتسجيلات mitmproxy بصيغتها الأصلية؛ [دليل تسجيلات الشبكة](docs/guides/web/web-network-captures.md) | -| تجميعات .NET | البيانات الوصفية، وتعليمات CIL، واعتماديات الشيفرة الأصلية المعلنة، ومقارنات البناء | فحص ثابت؛ [دليل الشيفرة المُدارة](docs/guides/managed/managed-code-analysis.md) | -| حزم Android APK | تصريحات ملف manifest، والأصناف، والدوال الناتجة عن فك الترجمة، والمراجع | JADX دون واجهة رسومية وJDK كامل على Linux/macOS/Windows x64؛ [دليل Android](docs/guides/android/android-analysis.md) | -| أجهزة Android | الأجهزة والحزم والعمليات والسجلات والدامبات ولقطات الشاشة ونقل APK/الملفات | adb يوفّره المُستدعي (محاكي أو جهاز)؛ [دليل ADB](docs/guides/android/adb-device-analysis.md) | -| مشاريع JEB | وحدات المشروع من المحرك وبصمات المصنّفات والكود الزائف للأنواع/الدوال | عميل JEB يبدأه المُستدعي ويقدّم MCP، ويُختار عبر REA_JEB_MCP_URL؛ [دليل JEB](docs/providers/jeb-analysis.md) | -| موارد Android | البيان المفكوك الترميز وجداول السلاسل واللغات وحقائق الإصدار | مُشغّل Apktool يوفّره المُستدعي؛ [دليل الموارد](docs/guides/android/apktool-resource-analysis.md) | -| تطبيقات Flutter | بصمة لقطة Dart وهشوش المكتبات لكل ABI وأصل بناء المحرك | لا شيء (تحليل APK ساكن)؛ [دليل Flutter](docs/guides/android/flutter-analysis.md) | -| البرامج الثابتة | المناطق، ونتائج الاستخراج، وما يُمرّر إلى تحليل الشيفرة الأصلية | Binwalk / Unblob على Linux؛ [دليل البرامج الثابتة](docs/guides/firmware/firmware-analysis.md) | -| الحزم المسجلة | حقول مختارة وقيم متكررة ومرشحات وقواعد فك الترميز | Linux: TShark 4.x + prlimit; [دليل التقاط الحزم](docs/guides/data/packet-captures.md) | -| الإشارات المنطقية المسجلة | تعليقات مفكك الترميز ونطاقات العينات ومعلومات التشخيص | Linux: sigrok-cli 0.7.2 + prlimit; [دليل الإشارات](docs/guides/signals/signal-recordings.md) | +| الهدف | ما يعيده REA | المتطلبات والدليل | +| ------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| الملفات الثنائية للشيفرة الأصلية | شيفرة شبه برمجية، وتعليمات تجميع، وسلاسل نصية، ورموز، واستدعاءات، ومراجع | Hopper أو Ghidra أو IDA؛ [تحليل الشيفرة الأصلية](https://rea.tools/ar/guides/native/) | +| بنية ELF دون تشغيل | الأقسام والمقاطع والرموز ومعلومات إعادة التموضع الأصلية، وآليات الحماية المحتملة المستدلّ عليها بالفحص الثابت | pwntools يوفّره المستدعي على Linux x64؛ [تشخيص الملفات الثنائية](docs/guides/native/binary-diagnostics.md) | +| شيفرة EVM البايتية | محددات التوجيه، وإزاحات البايتات، والمعاملات المستنتجة، وقابلية تغيير الحالة | مدخل محلي يحمل بايتات خامًا أو تمثيلًا سداسيًا عشريًا على Linux x64؛ [دليل EVM دون تشغيل](docs/guides/evm/evm-bytecode.md) | +| أعطال Linux المسجّلة | سجلات note الخام، ومسجّلات المعالج/الإشارات لكل خيط مسجّل، وترشيحات اختيارية لخرائط الذاكرة | pwntools يوفّره المستدعي على Linux x64؛ GDB/pwndbg اختياريان؛ [الأعطال المسجّلة](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | الوحدات، وعمليات الاستيراد، وخرائط المصدر، والمسارات، وIPC، وعلاقات إضافات الشيفرة الأصلية | Node.js وnpm؛ [تحليل التطبيقات](https://rea.tools/ar/guides/javascript/) | +| المواقع | بنية الصفحة، والسكربتات، وملاحظات الشبكة، ولقطات الشاشة المطلوبة | متصفح من عائلة Chrome؛ [تحليل المتصفح](https://rea.tools/ar/guides/browser/) | +| تسجيلات الشبكة المحفوظة | الطلبات، والاستجابات، ومحتويات الحمولة المتاحة، ومواضعها في المصدر | HAR؛ وmitmdump على Linux لتسجيلات mitmproxy بصيغتها الأصلية؛ [دليل تسجيلات الشبكة](docs/guides/web/web-network-captures.md) | +| التقاط الحزم | نقاط النهاية وDNS وTLS SNI وتوزيع البروتوكولات وطلبات HTTP | tshark وcapinfos يوفّرهما المُستدعي؛ [دليل pcap](docs/guides/data/pcap-analysis.md) | +| تجميعات .NET | البيانات الوصفية، وتعليمات CIL، واعتماديات الشيفرة الأصلية المعلنة، ومقارنات البناء | فحص ثابت؛ [دليل الشيفرة المُدارة](docs/guides/managed/managed-code-analysis.md) | +| حزم Android APK | تصريحات ملف manifest، والأصناف، والدوال الناتجة عن فك الترجمة، والمراجع | JADX دون واجهة رسومية وJDK كامل على Linux/macOS/Windows x64؛ [دليل Android](docs/guides/android/android-analysis.md) | +| أجهزة Android | الأجهزة والحزم والعمليات والسجلات والدامبات ولقطات الشاشة ونقل APK/الملفات | adb يوفّره المُستدعي (محاكي أو جهاز)؛ [دليل ADB](docs/guides/android/adb-device-analysis.md) | +| مشاريع JEB | وحدات المشروع من المحرك وبصمات المصنّفات والكود الزائف للأنواع/الدوال | عميل JEB يبدأه المُستدعي ويقدّم MCP، ويُختار عبر REA_JEB_MCP_URL؛ [دليل JEB](docs/providers/jeb-analysis.md) | +| موارد Android | البيان المفكوك الترميز وجداول السلاسل واللغات وحقائق الإصدار | مُشغّل Apktool يوفّره المُستدعي؛ [دليل الموارد](docs/guides/android/apktool-resource-analysis.md) | +| تطبيقات Flutter | بصمة لقطة Dart وهشوش المكتبات لكل ABI وأصل بناء المحرك | لا شيء (تحليل APK ساكن)؛ [دليل Flutter](docs/guides/android/flutter-analysis.md) | +| البرامج الثابتة | المناطق، ونتائج الاستخراج، وما يُمرّر إلى تحليل الشيفرة الأصلية | Binwalk / Unblob على Linux؛ [دليل البرامج الثابتة](docs/guides/firmware/firmware-analysis.md) | +| الحزم المسجلة | حقول مختارة وقيم متكررة ومرشحات وقواعد فك الترميز | Linux: TShark 4.x + prlimit; [دليل التقاط الحزم](docs/guides/data/packet-captures.md) | +| الإشارات المنطقية المسجلة | تعليقات مفكك الترميز ونطاقات العينات ومعلومات التشخيص | Linux: sigrok-cli 0.7.2 + prlimit; [دليل الإشارات](docs/guides/signals/signal-recordings.md) | | الحزم والموارد | قوائم الملفات، والبصمات، وملفات plist، وبنية حزم Apple، والموارد المستخرجة | [دليل تحليل الملفات وJavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md)، [تطبيقات Apple](docs/guides/apple/apple-application-analysis.md) | -| سلوك العمليات | مخرجات الطرفية، والتفاعلات، وملاحظات الخروج ونظام الملفات، ومقارنات التشغيل | Linux/macOS مع PTY أصلي؛ [تسجيل سلوك العمليات](docs/guides/runtime/process-capture.md) | +| سلوك العمليات | مخرجات الطرفية، والتفاعلات، وملاحظات الخروج ونظام الملفات، ومقارنات التشغيل | Linux/macOS مع PTY أصلي؛ [تسجيل سلوك العمليات](docs/guides/runtime/process-capture.md) | يقرأ الفحص الثابت لـ JavaScript و.NET الملفات المقدّمة دون تشغيل التطبيق. يشغّل التسجيل أثناء التنفيذ الهدف المحدد أو يتفاعل معه بصلاحيات مستخدمك؛ ويشرح كل دليل للتسجيل أثناء التنفيذ آثاره. @@ -263,7 +264,7 @@ npx rea-agents@latest setup ## سجل النجوم -🎉 **110,000 نجمة على GitHub — شكرًا لكم!** +🎉 **170,000 نجمة على GitHub — شكرًا لكم!** شكرًا لكل من يستخدم REA، ويبلّغ عن الأخطاء، ويقترح ميزات، ويختبر إصدارات البناء، ويساهم بالإصلاحات. diff --git a/README_de.md b/README_de.md index 4c6517b84..0e362c363 100644 --- a/README_de.md +++ b/README_de.md @@ -130,26 +130,27 @@ Dein Agent ruft REA über MCP auf, um das Ziel zu untersuchen und relevanten Cod REA benötigt Node.js 22.x (>=22.19), 24.x (>=24.11) oder 26+ sowie npm. Zusätzliche Werkzeuge und unterstützte Hostsysteme hängen vom Ziel ab: -| Ziel | Was REA zurückgibt | Voraussetzungen und Anleitung | -| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra oder IDA; [native Analyse](https://rea.tools/de/guides/native/) | -| Offline-ELF-Struktur | Sektionen, Segmente, ursprüngliche Symbole/Relokationen und mögliche Schutzmaßnahmen aus statischer Analyse | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; [Binärdiagnostik](docs/guides/native/binary-diagnostics.md) | -| EVM-Bytecode | Dispatch-Selektoren, Byte-Offsets, abgeleitete Argumente und Veränderbarkeit des Zustands | Lokale Eingabe mit Rohbytes oder Hexdarstellung unter Linux x64; [Offline-EVM-Leitfaden](docs/guides/evm/evm-bytecode.md) | -| Aufgezeichnete Linux-Abstürze | Unverarbeitete Note-Einträge, Register/Signale aller aufgezeichneten Threads und optionale Zuordnungskandidaten | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; optional GDB/pwndbg; [aufgezeichnete Abstürze](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Module, Imports, Source Maps, Routen, IPC und Beziehungen zu nativen Add-ons | Node.js und npm; [Anwendungsanalyse](https://rea.tools/de/guides/javascript/) | -| Websites | Seitenstruktur, Skripte, Netzwerkbeobachtungen und angeforderte Screenshots | Ein Browser aus der Chrome-Familie; [Browseranalyse](https://rea.tools/de/guides/browser/) | -| Gespeicherte Netzwerkaufzeichnungen | Anfragen, Antworten, zugängliche Nutzdaten und Quellpositionen | HAR; mitmdump unter Linux für Aufzeichnungen im nativen mitmproxy-Format; [Leitfaden zu Netzwerkaufzeichnungen](docs/guides/web/web-network-captures.md) | -| .NET-Assemblies | Metadaten, CIL-Anweisungen, deklarierte native Abhängigkeiten und Build-Vergleiche | Statische Untersuchung; [Leitfaden für verwalteten Code](docs/guides/managed/managed-code-analysis.md) | -| Android-APKs | Manifest-Deklarationen, Klassen, dekompilierte Methoden und Verweise | JADX ohne grafische Oberfläche und ein vollständiges JDK unter Linux/macOS/Windows x64; [Android-Leitfaden](docs/guides/android/android-analysis.md) | -| Android-Geräte | Geräte, Pakete, Prozesse, Logs, Dumps, Bildschirmaufnahmen sowie APK- und Dateiübertragungen | Vom Aufrufer bereitgestelltes adb (Emulator oder Gerät); [ADB-Leitfaden](docs/guides/android/adb-device-analysis.md) | -| JEB-Projekte | Engine-gestützte Projekteinheiten, Artefakt-Prüfsummen und Pseudokode von Typen/Methoden | Ein vom Aufrufer gestarteter JEB-Client mit MCP, ausgewählt über REA_JEB_MCP_URL; [JEB-Leitfaden](docs/providers/jeb-analysis.md) | -| Android-Ressourcen | Dekodiertes Manifest, String-Tabellen, Sprachen und Versionsfakten | Vom Aufrufer bereitgestellter Apktool-Starter; [Ressourcen-Leitfaden](docs/guides/android/apktool-resource-analysis.md) | -| Flutter-Apps | Dart-Snapshot-Hash, Per-ABI-Bibliotheksprüfsummen und Engine-Build-Provenienz | Keine (statische APK-Analyse); [Flutter-Leitfaden](docs/guides/android/flutter-analysis.md) | -| Firmware | Bereiche, Extraktionsergebnisse und Übergaben an die native Analyse | Binwalk / Unblob unter Linux; [Firmware-Leitfaden](docs/guides/firmware/firmware-analysis.md) | -| Aufgezeichnete Pakete | Ausgewählte Felder, wiederholte Werte, Filter und Decode-as-Regeln | Linux: TShark 4.x + prlimit; [Mitschnitt-Anleitung](docs/guides/data/packet-captures.md) | -| Aufgezeichnete Logiksignale | Decoder-Anmerkungen, Sample-Bereiche und Diagnosen | Linux: sigrok-cli 0.7.2 + prlimit; [Signalaufzeichnungen](docs/guides/signals/signal-recordings.md) | -| Pakete und Ressourcen | Dateiinventare, Hashwerte, plists, Aufbau von Apple-Bundles und extrahierte Ressourcen | [Artefakt- und JavaScript-Leitfaden](docs/guides/javascript/javascript-artifact-reconstruction.md), [Apple-Anwendungen](docs/guides/apple/apple-application-analysis.md) | -| Prozessverhalten | Terminalausgabe, Interaktionen, Beobachtungen zu Prozessende und Dateisystem sowie Laufvergleiche | Linux/macOS mit nativer PTY; [Prozessaufzeichnung](docs/guides/runtime/process-capture.md) | +| Ziel | Was REA zurückgibt | Voraussetzungen und Anleitung | +| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| Native Binärdateien | Pseudocode, Assemblercode, Zeichenketten, Symbole, Aufrufe und Verweise | Hopper, Ghidra oder IDA; [native Analyse](https://rea.tools/de/guides/native/) | +| Offline-ELF-Struktur | Sektionen, Segmente, ursprüngliche Symbole/Relokationen und mögliche Schutzmaßnahmen aus statischer Analyse | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; [Binärdiagnostik](docs/guides/native/binary-diagnostics.md) | +| EVM-Bytecode | Dispatch-Selektoren, Byte-Offsets, abgeleitete Argumente und Veränderbarkeit des Zustands | Lokale Eingabe mit Rohbytes oder Hexdarstellung unter Linux x64; [Offline-EVM-Leitfaden](docs/guides/evm/evm-bytecode.md) | +| Aufgezeichnete Linux-Abstürze | Unverarbeitete Note-Einträge, Register/Signale aller aufgezeichneten Threads und optionale Zuordnungskandidaten | Vom Aufrufer bereitgestelltes pwntools unter Linux x64; optional GDB/pwndbg; [aufgezeichnete Abstürze](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Module, Imports, Source Maps, Routen, IPC und Beziehungen zu nativen Add-ons | Node.js und npm; [Anwendungsanalyse](https://rea.tools/de/guides/javascript/) | +| Websites | Seitenstruktur, Skripte, Netzwerkbeobachtungen und angeforderte Screenshots | Ein Browser aus der Chrome-Familie; [Browseranalyse](https://rea.tools/de/guides/browser/) | +| Gespeicherte Netzwerkaufzeichnungen | Anfragen, Antworten, zugängliche Nutzdaten und Quellpositionen | HAR; mitmdump unter Linux für Aufzeichnungen im nativen mitmproxy-Format; [Leitfaden zu Netzwerkaufzeichnungen](docs/guides/web/web-network-captures.md) | +| Paketerfassungen | Endpunkte, DNS, TLS SNI, Protokollverteilung und HTTP-Anfragen | Vom Aufrufer bereitgestellte tshark- und capinfos-Binaries; [pcap-Leitfaden](docs/guides/data/pcap-analysis.md) | +| .NET-Assemblies | Metadaten, CIL-Anweisungen, deklarierte native Abhängigkeiten und Build-Vergleiche | Statische Untersuchung; [Leitfaden für verwalteten Code](docs/guides/managed/managed-code-analysis.md) | +| Android-APKs | Manifest-Deklarationen, Klassen, dekompilierte Methoden und Verweise | JADX ohne grafische Oberfläche und ein vollständiges JDK unter Linux/macOS/Windows x64; [Android-Leitfaden](docs/guides/android/android-analysis.md) | +| Android-Geräte | Geräte, Pakete, Prozesse, Logs, Dumps, Bildschirmaufnahmen sowie APK- und Dateiübertragungen | Vom Aufrufer bereitgestelltes adb (Emulator oder Gerät); [ADB-Leitfaden](docs/guides/android/adb-device-analysis.md) | +| JEB-Projekte | Engine-gestützte Projekteinheiten, Artefakt-Prüfsummen und Pseudokode von Typen/Methoden | Ein vom Aufrufer gestarteter JEB-Client mit MCP, ausgewählt über REA_JEB_MCP_URL; [JEB-Leitfaden](docs/providers/jeb-analysis.md) | +| Android-Ressourcen | Dekodiertes Manifest, String-Tabellen, Sprachen und Versionsfakten | Vom Aufrufer bereitgestellter Apktool-Starter; [Ressourcen-Leitfaden](docs/guides/android/apktool-resource-analysis.md) | +| Flutter-Apps | Dart-Snapshot-Hash, Per-ABI-Bibliotheksprüfsummen und Engine-Build-Provenienz | Keine (statische APK-Analyse); [Flutter-Leitfaden](docs/guides/android/flutter-analysis.md) | +| Firmware | Bereiche, Extraktionsergebnisse und Übergaben an die native Analyse | Binwalk / Unblob unter Linux; [Firmware-Leitfaden](docs/guides/firmware/firmware-analysis.md) | +| Aufgezeichnete Pakete | Ausgewählte Felder, wiederholte Werte, Filter und Decode-as-Regeln | Linux: TShark 4.x + prlimit; [Mitschnitt-Anleitung](docs/guides/data/packet-captures.md) | +| Aufgezeichnete Logiksignale | Decoder-Anmerkungen, Sample-Bereiche und Diagnosen | Linux: sigrok-cli 0.7.2 + prlimit; [Signalaufzeichnungen](docs/guides/signals/signal-recordings.md) | +| Pakete und Ressourcen | Dateiinventare, Hashwerte, plists, Aufbau von Apple-Bundles und extrahierte Ressourcen | [Artefakt- und JavaScript-Leitfaden](docs/guides/javascript/javascript-artifact-reconstruction.md), [Apple-Anwendungen](docs/guides/apple/apple-application-analysis.md) | +| Prozessverhalten | Terminalausgabe, Interaktionen, Beobachtungen zu Prozessende und Dateisystem sowie Laufvergleiche | Linux/macOS mit nativer PTY; [Prozessaufzeichnung](docs/guides/runtime/process-capture.md) | Statische JavaScript- und .NET-Untersuchungen lesen die bereitgestellten Dateien, ohne die Anwendung auszuführen. Laufzeitaufzeichnungen führen das gewählte Ziel mit deinen Benutzerrechten aus oder interagieren damit; die jeweiligen Anleitungen beschreiben die Auswirkungen. @@ -261,7 +262,7 @@ Melde Sicherheitslücken gemäß [SECURITY.md](SECURITY.md). ## Sternverlauf -🎉 **110.000 GitHub-Sterne – vielen Dank!** +🎉 **170.000 GitHub-Sterne – vielen Dank!** Danke an alle, die REA nutzen, Fehler melden, Funktionswünsche äußern, Builds testen und Fehlerbehebungen beitragen. diff --git a/README_es.md b/README_es.md index 623d4a66a..09a413695 100644 --- a/README_es.md +++ b/README_es.md @@ -130,26 +130,27 @@ Tu agente llama a REA mediante MCP para inspeccionar el objetivo y seguir el có REA requiere Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, además de npm. Las herramientas adicionales y los sistemas anfitriones compatibles dependen del objetivo: -| Objetivo | Qué devuelve REA | Requisitos y guía | -| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra o IDA; [análisis nativo](https://rea.tools/es/guides/native/) | -| Estructura ELF sin ejecutar | Secciones, segmentos, símbolos/reubicaciones originales y posibles medidas de mitigación detectadas mediante análisis estático | pwntools proporcionado por quien llama, en Linux x64; [diagnóstico de binarios](docs/guides/native/binary-diagnostics.md) | -| Bytecode EVM | Selectores de despacho, desplazamientos en bytes, argumentos inferidos y mutabilidad | Entrada local con bytes sin procesar o representación hexadecimal, en Linux x64; [guía de EVM sin ejecutar](docs/guides/evm/evm-bytecode.md) | -| Fallos de Linux registrados | Registros note sin procesar, registros/señales de cada hilo registrado y posibles correspondencias de memoria opcionales | pwntools proporcionado por quien llama, en Linux x64; GDB/pwndbg opcionales; [fallos registrados](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Módulos, importaciones, mapas de código fuente, rutas, IPC y relaciones con complementos nativos | Node.js y npm; [análisis de aplicaciones](https://rea.tools/es/guides/javascript/) | -| Sitios web | Estructura de la página, scripts, observaciones de red y capturas de pantalla solicitadas | Un navegador de la familia Chrome; [análisis del navegador](https://rea.tools/es/guides/browser/) | -| Capturas de red guardadas | Solicitudes, respuestas, contenido accesible de las cargas útiles y ubicaciones de origen | HAR; mitmdump en Linux para capturas en formato nativo de mitmproxy; [guía de capturas](docs/guides/web/web-network-captures.md) | -| Ensamblados .NET | Metadatos, instrucciones CIL, dependencias nativas declaradas y comparaciones de compilaciones | Inspección estática; [guía de código administrado](docs/guides/managed/managed-code-analysis.md) | -| APK de Android | Declaraciones del manifiesto, clases, métodos descompilados y referencias | JADX sin interfaz gráfica y un JDK completo en Linux/macOS/Windows x64; [guía de Android](docs/guides/android/android-analysis.md) | -| Dispositivos Android | Dispositivos, paquetes, procesos, registros, volcados, capturas de pantalla y transferencias de APK/archivos | adb suministrado por el autor de la llamada (emulador o dispositivo); [guía de ADB](docs/guides/android/adb-device-analysis.md) | -| Proyectos JEB | Unidades de proyecto del motor, resúmenes de artefactos y pseudocódigo de tipos/métodos | Un cliente JEB iniciado por el autor de la llamada que sirve MCP, seleccionado con REA_JEB_MCP_URL; [guía de JEB](docs/providers/jeb-analysis.md) | -| Recursos de Android | Manifiesto decodificado, tablas de cadenas, idiomas y datos de versión | Lanzador de Apktool suministrado por el autor de la llamada; [guía de recursos](docs/guides/android/apktool-resource-analysis.md) | -| Aplicaciones Flutter | Hash de snapshot de Dart, resúmenes de bibliotecas por ABI y procedencia de compilación del motor | Ninguna (análisis APK estático); [guía de Flutter](docs/guides/android/flutter-analysis.md) | -| Firmware | Regiones, resultados de extracción y derivaciones al análisis nativo | Binwalk / Unblob en Linux; [guía de firmware](docs/guides/firmware/firmware-analysis.md) | -| Paquetes grabados | Campos seleccionados, valores repetidos, filtros y reglas de decodificación | Linux: TShark 4.x + prlimit; [guía de capturas](docs/guides/data/packet-captures.md) | -| Señales lógicas grabadas | Anotaciones del decodificador, rangos de muestras y diagnósticos | Linux: sigrok-cli 0.7.2 + prlimit; [guía de señales](docs/guides/signals/signal-recordings.md) | +| Objetivo | Qué devuelve REA | Requisitos y guía | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | +| Binarios nativos | Pseudocódigo, ensamblador, cadenas, símbolos, llamadas y referencias | Hopper, Ghidra o IDA; [análisis nativo](https://rea.tools/es/guides/native/) | +| Estructura ELF sin ejecutar | Secciones, segmentos, símbolos/reubicaciones originales y posibles medidas de mitigación detectadas mediante análisis estático | pwntools proporcionado por quien llama, en Linux x64; [diagnóstico de binarios](docs/guides/native/binary-diagnostics.md) | +| Bytecode EVM | Selectores de despacho, desplazamientos en bytes, argumentos inferidos y mutabilidad | Entrada local con bytes sin procesar o representación hexadecimal, en Linux x64; [guía de EVM sin ejecutar](docs/guides/evm/evm-bytecode.md) | +| Fallos de Linux registrados | Registros note sin procesar, registros/señales de cada hilo registrado y posibles correspondencias de memoria opcionales | pwntools proporcionado por quien llama, en Linux x64; GDB/pwndbg opcionales; [fallos registrados](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Módulos, importaciones, mapas de código fuente, rutas, IPC y relaciones con complementos nativos | Node.js y npm; [análisis de aplicaciones](https://rea.tools/es/guides/javascript/) | +| Sitios web | Estructura de la página, scripts, observaciones de red y capturas de pantalla solicitadas | Un navegador de la familia Chrome; [análisis del navegador](https://rea.tools/es/guides/browser/) | +| Capturas de red guardadas | Solicitudes, respuestas, contenido accesible de las cargas útiles y ubicaciones de origen | HAR; mitmdump en Linux para capturas en formato nativo de mitmproxy; [guía de capturas](docs/guides/web/web-network-captures.md) | +| Capturas de paquetes | Endpoints, DNS, TLS SNI, distribución de protocolos y solicitudes HTTP | tshark y capinfos suministrados por el autor de la llamada; [guía pcap](docs/guides/data/pcap-analysis.md) | +| Ensamblados .NET | Metadatos, instrucciones CIL, dependencias nativas declaradas y comparaciones de compilaciones | Inspección estática; [guía de código administrado](docs/guides/managed/managed-code-analysis.md) | +| APK de Android | Declaraciones del manifiesto, clases, métodos descompilados y referencias | JADX sin interfaz gráfica y un JDK completo en Linux/macOS/Windows x64; [guía de Android](docs/guides/android/android-analysis.md) | +| Dispositivos Android | Dispositivos, paquetes, procesos, registros, volcados, capturas de pantalla y transferencias de APK/archivos | adb suministrado por el autor de la llamada (emulador o dispositivo); [guía de ADB](docs/guides/android/adb-device-analysis.md) | +| Proyectos JEB | Unidades de proyecto del motor, resúmenes de artefactos y pseudocódigo de tipos/métodos | Un cliente JEB iniciado por el autor de la llamada que sirve MCP, seleccionado con REA_JEB_MCP_URL; [guía de JEB](docs/providers/jeb-analysis.md) | +| Recursos de Android | Manifiesto decodificado, tablas de cadenas, idiomas y datos de versión | Lanzador de Apktool suministrado por el autor de la llamada; [guía de recursos](docs/guides/android/apktool-resource-analysis.md) | +| Aplicaciones Flutter | Hash de snapshot de Dart, resúmenes de bibliotecas por ABI y procedencia de compilación del motor | Ninguna (análisis APK estático); [guía de Flutter](docs/guides/android/flutter-analysis.md) | +| Firmware | Regiones, resultados de extracción y derivaciones al análisis nativo | Binwalk / Unblob en Linux; [guía de firmware](docs/guides/firmware/firmware-analysis.md) | +| Paquetes grabados | Campos seleccionados, valores repetidos, filtros y reglas de decodificación | Linux: TShark 4.x + prlimit; [guía de capturas](docs/guides/data/packet-captures.md) | +| Señales lógicas grabadas | Anotaciones del decodificador, rangos de muestras y diagnósticos | Linux: sigrok-cli 0.7.2 + prlimit; [guía de señales](docs/guides/signals/signal-recordings.md) | | Paquetes y recursos | Inventarios de archivos, resúmenes criptográficos, plists, estructura de paquetes de Apple y recursos extraídos | [Guía de artefactos y JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [aplicaciones de Apple](docs/guides/apple/apple-application-analysis.md) | -| Comportamiento de procesos | Salida de la terminal, interacciones, observaciones de salida y del sistema de archivos, y comparaciones entre ejecuciones | Linux/macOS con una PTY nativa; [captura de procesos](docs/guides/runtime/process-capture.md) | +| Comportamiento de procesos | Salida de la terminal, interacciones, observaciones de salida y del sistema de archivos, y comparaciones entre ejecuciones | Linux/macOS con una PTY nativa; [captura de procesos](docs/guides/runtime/process-capture.md) | La inspección estática de JavaScript y .NET lee los archivos suministrados sin ejecutar la aplicación. La captura en ejecución inicia el objetivo seleccionado o interactúa con él con los permisos de tu usuario; cada guía describe sus efectos. @@ -261,7 +262,7 @@ Informa de vulnerabilidades siguiendo [SECURITY.md](SECURITY.md). ## Historial de estrellas -🎉 **110.000 estrellas en GitHub: ¡gracias!** +🎉 **170.000 estrellas en GitHub: ¡gracias!** Gracias a quienes usan REA, informan de errores, solicitan funciones, prueban compilaciones y contribuyen con correcciones. diff --git a/README_fa.md b/README_fa.md index 9044983c1..87626915c 100644 --- a/README_fa.md +++ b/README_fa.md @@ -122,26 +122,27 @@ npx rea-agents@latest setup REA به Node.js 22.x (>=22.19)، 24.x (>=24.11) یا 26+، به‌همراه npm نیاز دارد. ابزارهای اضافی و پشتیبانی سیستم میزبان به نوع هدف بستگی دارند: -| هدف | خروجی REA | پیش‌نیازها و راهنما | -| ---------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| باینری‌های بومی | شبه‌کد، اسمبلی، رشته‌ها، نمادها، فراخوانی‌ها و ارجاعات | Hopper، Ghidra یا IDA؛ [تحلیل بومی](https://rea.tools/fa/guides/native/) | -| ساختار ELF آفلاین | بخش‌ها، سگمنت‌ها، نمادها و relocationهای اصلی و گزینه‌های احتمالی کاهش آسیب‌پذیری ایستا | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ [تشخیص باینری](docs/guides/native/binary-diagnostics.md) | -| بایت‌کد EVM | selectorهای dispatch، offsetهای بایتی، آرگومان‌های استنباط‌شده و قابلیت تغییر وضعیت | دادهٔ خام/hex محلی روی Linux x64؛ [راهنمای EVM آفلاین](docs/guides/evm/evm-bytecode.md) | -| کرش‌های ثبت‌شدهٔ لینوکس | یادداشت‌های خام، رجیسترها/سیگنال‌های تمام threadهای ثبت‌شده و گزینه‌های احتمالی نگاشت | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ GDB/pwndbg اختیاری؛ [کرش‌های ثبت‌شده](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | ماژول‌ها، importها، source mapها، مسیرها، IPC و ارتباط افزونه‌های بومی | Node.js و npm؛ [تحلیل برنامه](https://rea.tools/fa/guides/javascript/) | -| وب‌سایت‌ها | ساختار صفحه، اسکریپت‌ها، مشاهدات شبکه و اسکرین‌شات‌های درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](https://rea.tools/fa/guides/browser/) | -| داده‌های ضبط‌شدهٔ شبکه | درخواست‌ها، پاسخ‌ها، payloadهای آشکارشده و مکان آن‌ها در منبع | HAR؛ ابزار mitmdump در لینوکس برای ضبط‌های بومی mitmproxy؛ [راهنمای ضبط شبکه](docs/guides/web/web-network-captures.md) | -| اسمبلی‌های .NET | فراداده، دستورالعمل‌های CIL، وابستگی‌های بومی اعلام‌شده و مقایسهٔ buildها | بررسی ایستا؛ [راهنمای کد مدیریت‌شده](docs/guides/managed/managed-code-analysis.md) | -| فایل‌های APK اندروید | تعاریف Manifest، کلاس‌ها، متدهای دیکامپایل‌شده و ارجاعات | JADX بدون رابط گرافیکی و JDK کامل در Linux/macOS/Windows x64؛ [راهنمای اندروید](docs/guides/android/android-analysis.md) | -| دستگاه‌های اندروید | دستگاه‌ها، بسته‌ها، فرایندها، لاگ‌ها، دامپ‌ها، اسکرین‌شات‌ها و انتقال APK/فایل | adb تأمین‌شده توسط فراخوان‌کننده (شبیه‌ساز یا دستگاه)؛ [راهنمای ADB](docs/guides/android/adb-device-analysis.md) | -| پروژه‌های JEB | واحدهای پروژه از موتور، هش‌های مصنوع و شبه‌کدِ نوع/متد | یک کلاینت JEB که توسط فراخوان‌کننده اجرا شده و MCP ارائه می‌دهد و با REA_JEB_MCP_URL انتخاب می‌شود؛ [راهنمای JEB](docs/providers/jeb-analysis.md) | -| منابع اندروید | مانیفست رمزگشایی‌شده، جداول رشته‌ها، زبان‌ها و اطلاعات نسخه | راه‌انداز Apktool تأمین‌شده توسط فراخوان‌کننده؛ [راهنمای منابع](docs/guides/android/apktool-resource-analysis.md) | -| برنامه‌های فلاتر | هش اسنپ‌شات دارت، هش کتابخانه‌ها به تفکیک ABI و اصالت بیلد موتور | هیچ (تحلیل ایستا APK)؛ [راهنمای فلاتر](docs/guides/android/flutter-analysis.md) | -| Firmware | ناحیه‌ها، نتایج استخراج و تحویل به ابزارهای تحلیل بومی | Binwalk / Unblob در لینوکس؛ [راهنمای Firmware](docs/guides/firmware/firmware-analysis.md) | -| بسته‌های ضبط‌شده | فیلدهای منتخب، مقادیر تکراری، فیلترها و قواعد رمزگشایی | Linux: TShark 4.x + prlimit; [راهنمای ضبط بسته](docs/guides/data/packet-captures.md) | -| سیگنال‌های منطقی ضبط‌شده | توضیحات رمزگشا، بازه‌های نمونه و اطلاعات عیب‌یابی | Linux: sigrok-cli 0.7.2 + prlimit; [راهنمای سیگنال‌ها](docs/guides/signals/signal-recordings.md) | -| بسته‌ها و منابع | فهرست فایل‌ها، digestها، فایل‌های plist، ساختار bundle اپل و منابع استخراج‌شده | [راهنمای آرتیفکت و JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md)، [برنامه‌های اپل](docs/guides/apple/apple-application-analysis.md) | -| رفتار فرایند | خروجی ترمینال، تعاملات، وضعیت خروج، مشاهدات سیستم فایل و مقایسهٔ اجراها | Linux/macOS با PTY بومی؛ [ضبط فرایند](docs/guides/runtime/process-capture.md) | +| هدف | خروجی REA | پیش‌نیازها و راهنما | +| ---------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| باینری‌های بومی | شبه‌کد، اسمبلی، رشته‌ها، نمادها، فراخوانی‌ها و ارجاعات | Hopper، Ghidra یا IDA؛ [تحلیل بومی](https://rea.tools/fa/guides/native/) | +| ساختار ELF آفلاین | بخش‌ها، سگمنت‌ها، نمادها و relocationهای اصلی و گزینه‌های احتمالی کاهش آسیب‌پذیری ایستا | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ [تشخیص باینری](docs/guides/native/binary-diagnostics.md) | +| بایت‌کد EVM | selectorهای dispatch، offsetهای بایتی، آرگومان‌های استنباط‌شده و قابلیت تغییر وضعیت | دادهٔ خام/hex محلی روی Linux x64؛ [راهنمای EVM آفلاین](docs/guides/evm/evm-bytecode.md) | +| کرش‌های ثبت‌شدهٔ لینوکس | یادداشت‌های خام، رجیسترها/سیگنال‌های تمام threadهای ثبت‌شده و گزینه‌های احتمالی نگاشت | pwntools تأمین‌شده توسط فراخواننده روی Linux x64؛ GDB/pwndbg اختیاری؛ [کرش‌های ثبت‌شده](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | ماژول‌ها، importها، source mapها، مسیرها، IPC و ارتباط افزونه‌های بومی | Node.js و npm؛ [تحلیل برنامه](https://rea.tools/fa/guides/javascript/) | +| وب‌سایت‌ها | ساختار صفحه، اسکریپت‌ها، مشاهدات شبکه و اسکرین‌شات‌های درخواستی | مرورگر مبتنی بر Chrome؛ [تحلیل مرورگر](https://rea.tools/fa/guides/browser/) | +| داده‌های ضبط‌شدهٔ شبکه | درخواست‌ها، پاسخ‌ها، payloadهای آشکارشده و مکان آن‌ها در منبع | HAR؛ ابزار mitmdump در لینوکس برای ضبط‌های بومی mitmproxy؛ [راهنمای ضبط شبکه](docs/guides/web/web-network-captures.md) | +| اسمبلی‌های .NET | فراداده، دستورالعمل‌های CIL، وابستگی‌های بومی اعلام‌شده و مقایسهٔ buildها | بررسی ایستا؛ [راهنمای کد مدیریت‌شده](docs/guides/managed/managed-code-analysis.md) | +| فایل‌های APK اندروید | تعاریف Manifest، کلاس‌ها، متدهای دیکامپایل‌شده و ارجاعات | JADX بدون رابط گرافیکی و JDK کامل در Linux/macOS/Windows x64؛ [راهنمای اندروید](docs/guides/android/android-analysis.md) | +| دستگاه‌های اندروید | دستگاه‌ها، بسته‌ها، فرایندها، لاگ‌ها، دامپ‌ها، اسکرین‌شات‌ها و انتقال APK/فایل | adb تأمین‌شده توسط فراخوان‌کننده (شبیه‌ساز یا دستگاه)؛ [راهنمای ADB](docs/guides/android/adb-device-analysis.md) | +| پروژه‌های JEB | واحدهای پروژه از موتور، هش‌های مصنوع و شبه‌کدِ نوع/متد | یک کلاینت JEB که توسط فراخوان‌کننده اجرا شده و MCP ارائه می‌دهد و با REA_JEB_MCP_URL انتخاب می‌شود؛ [راهنمای JEB](docs/providers/jeb-analysis.md) | +| منابع اندروید | مانیفست رمزگشایی‌شده، جداول رشته‌ها، زبان‌ها و اطلاعات نسخه | راه‌انداز Apktool تأمین‌شده توسط فراخوان‌کننده؛ [راهنمای منابع](docs/guides/android/apktool-resource-analysis.md) | +| برنامه‌های فلاتر | هش اسنپ‌شات دارت، هش کتابخانه‌ها به تفکیک ABI و اصالت بیلد موتور | هیچ (تحلیل ایستا APK)؛ [راهنمای فلاتر](docs/guides/android/flutter-analysis.md) | +| Firmware | ناحیه‌ها، نتایج استخراج و تحویل به ابزارهای تحلیل بومی | Binwalk / Unblob در لینوکس؛ [راهنمای Firmware](docs/guides/firmware/firmware-analysis.md) | +| بسته‌های ضبط‌شده | فیلدهای منتخب، مقادیر تکراری، فیلترها و قواعد رمزگشایی | Linux: TShark 4.x + prlimit; [راهنمای ضبط بسته](docs/guides/data/packet-captures.md) | +| ضبط بسته‌ها | نقاط پایانی، DNS، TLS SNI، توزیع پروتکل و درخواست‌های HTTP | tshark و capinfos تأمین‌شده توسط فراخوان‌کننده؛ [راهنمای pcap](docs/guides/data/pcap-analysis.md) | +| سیگنال‌های منطقی ضبط‌شده | توضیحات رمزگشا، بازه‌های نمونه و اطلاعات عیب‌یابی | Linux: sigrok-cli 0.7.2 + prlimit; [راهنمای سیگنال‌ها](docs/guides/signals/signal-recordings.md) | +| بسته‌ها و منابع | فهرست فایل‌ها، digestها، فایل‌های plist، ساختار bundle اپل و منابع استخراج‌شده | [راهنمای آرتیفکت و JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md)، [برنامه‌های اپل](docs/guides/apple/apple-application-analysis.md) | +| رفتار فرایند | خروجی ترمینال، تعاملات، وضعیت خروج، مشاهدات سیستم فایل و مقایسهٔ اجراها | Linux/macOS با PTY بومی؛ [ضبط فرایند](docs/guides/runtime/process-capture.md) | بررسی ایستای JavaScript و .NET فایل‌های ارائه‌شده را بدون اجرای برنامه می‌خواند. ضبط زمان اجرا، هدف انتخاب‌شده را با مجوزهای کاربری شما اجرا می‌کند یا با آن تعامل دارد؛ آثار این عملیات در راهنمای مربوط به هر نوع ضبط توضیح داده شده‌اند. @@ -246,7 +247,7 @@ npx rea-agents@latest setup ## تاریخچهٔ ستاره‌ها -🎉 **۱۱۰٬۰۰۰ ستارهٔ GitHub — سپاسگزاریم!** +🎉 **۱۷۰٬۰۰۰ ستارهٔ GitHub — سپاسگزاریم!** از همهٔ کسانی که از REA استفاده می‌کنند، خطاها را گزارش می‌دهند، قابلیت‌های جدید پیشنهاد می‌کنند، buildها را آزمایش می‌کنند و در بهبود پروژه مشارکت دارند سپاسگزاریم. diff --git a/README_fr.md b/README_fr.md index 58de4463e..2b9fa3838 100644 --- a/README_fr.md +++ b/README_fr.md @@ -133,27 +133,28 @@ Votre agent appelle REA via MCP pour inspecter la cible et suivre le code pertin REA nécessite Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, ainsi que npm. Les outils supplémentaires et les hôtes pris en charge dépendent de la cible : -| Cible | Ce que REA renvoie | Prérequis et guide | -| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra ou IDA ; [analyse native](https://rea.tools/fr/guides/native/) | -| Structure ELF hors ligne | Sections, segments, symboles et relocations d'origine, et protections statiques candidates | pwntools fourni par l'utilisateur sous Linux x64 ; [diagnostics binaires](docs/guides/native/binary-diagnostics.md) | -| Artefact WASM | Validation, sections, formes WAT exactes d'import/export et WAT décodé | WABT 1.0.42 fourni par l'utilisateur ; `inspect_wasm_artifact` | -| Bytecode EVM | Sélecteurs de dispatch, offsets en octets, arguments inférés et mutabilité | Fichier local brut ou hexadécimal sous Linux x64 ; [guide EVM hors ligne](docs/guides/evm/evm-bytecode.md) | -| Crashs Linux enregistrés | Notes brutes, registres et signaux de chaque thread enregistré, et correspondances de mappings facultatives | pwntools fourni par l'utilisateur sous Linux x64 ; GDB/pwndbg en option ; [crashs enregistrés](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Modules, imports, source maps, routes, IPC et relations avec les modules natifs | Node.js et npm ; [analyse d'applications](https://rea.tools/fr/guides/javascript/) | -| Sites web | Structure des pages, scripts, observations réseau et captures d'écran demandées | Un navigateur de la famille Chrome ; [analyse du navigateur](https://rea.tools/fr/guides/browser/) | -| Captures réseau enregistrées | Requêtes, réponses, payloads exposés et emplacements dans le code source | HAR ; mitmdump sous Linux pour les captures mitmproxy natives ; [guide des captures](docs/guides/web/web-network-captures.md) | -| Assemblys .NET | Métadonnées, instructions CIL, dépendances natives déclarées et comparaisons de builds | Inspection statique ; [guide du code managé](docs/guides/managed/managed-code-analysis.md) | -| APK Android | Déclarations du manifeste, classes, méthodes décompilées et références | JADX headless et un JDK complet sous Linux/macOS/Windows x64 ; [guide Android](docs/guides/android/android-analysis.md) | -| Appareils Android | Appareils, paquets, processus, journaux, dumps, captures d'écran et transferts d'APK/fichiers | adb fourni par l'appelant (émulateur ou appareil) ; [guide ADB](docs/guides/android/adb-device-analysis.md) | -| Projets JEB | Unités de projet fournies par le moteur, condensés d'artefacts et pseudo-code de types/méthodes | Un client JEB démarré par l'appelant servant MCP, sélectionné via REA_JEB_MCP_URL ; [guide JEB](docs/providers/jeb-analysis.md) | -| Ressources Android | Manifeste décodé, tables de chaînes, langues et faits de version | Lanceur Apktool fourni par l'appelant ; [guide des ressources](docs/guides/android/apktool-resource-analysis.md) | -| Applications Flutter | Empreinte de snapshot Dart, condensés de bibliothèques par ABI et provenance de build du moteur | Aucune (analyse APK statique) ; [guide Flutter](docs/guides/android/flutter-analysis.md) | -| Firmware | Régions, résultats d'extraction et passage de relais vers l'analyse native | Binwalk / Unblob sous Linux ; [guide firmware](docs/guides/firmware/firmware-analysis.md) | -| Paquets enregistrés | Champs sélectionnés, valeurs répétées, filtres et règles de décodage | Linux: TShark 4.x + prlimit; [guide des captures](docs/guides/data/packet-captures.md) | -| Signaux logiques enregistrés | Annotations du décodeur, plages d’échantillons et diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [guide des signaux](docs/guides/signals/signal-recordings.md) | +| Cible | Ce que REA renvoie | Prérequis et guide | +| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| Binaires natifs | Pseudo-code, assembleur, chaînes, symboles, appels et références | Hopper, Ghidra ou IDA ; [analyse native](https://rea.tools/fr/guides/native/) | +| Structure ELF hors ligne | Sections, segments, symboles et relocations d'origine, et protections statiques candidates | pwntools fourni par l'utilisateur sous Linux x64 ; [diagnostics binaires](docs/guides/native/binary-diagnostics.md) | +| Artefact WASM | Validation, sections, formes WAT exactes d'import/export et WAT décodé | WABT 1.0.42 fourni par l'utilisateur ; `inspect_wasm_artifact` | +| Bytecode EVM | Sélecteurs de dispatch, offsets en octets, arguments inférés et mutabilité | Fichier local brut ou hexadécimal sous Linux x64 ; [guide EVM hors ligne](docs/guides/evm/evm-bytecode.md) | +| Crashs Linux enregistrés | Notes brutes, registres et signaux de chaque thread enregistré, et correspondances de mappings facultatives | pwntools fourni par l'utilisateur sous Linux x64 ; GDB/pwndbg en option ; [crashs enregistrés](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Modules, imports, source maps, routes, IPC et relations avec les modules natifs | Node.js et npm ; [analyse d'applications](https://rea.tools/fr/guides/javascript/) | +| Sites web | Structure des pages, scripts, observations réseau et captures d'écran demandées | Un navigateur de la famille Chrome ; [analyse du navigateur](https://rea.tools/fr/guides/browser/) | +| Captures réseau enregistrées | Requêtes, réponses, payloads exposés et emplacements dans le code source | HAR ; mitmdump sous Linux pour les captures mitmproxy natives ; [guide des captures](docs/guides/web/web-network-captures.md) | +| Captures de paquets | Points de terminaison, DNS, TLS SNI, distribution des protocoles et requêtes HTTP | tshark et capinfos fournis par l'appelant ; [guide pcap](docs/guides/data/pcap-analysis.md) | +| Assemblys .NET | Métadonnées, instructions CIL, dépendances natives déclarées et comparaisons de builds | Inspection statique ; [guide du code managé](docs/guides/managed/managed-code-analysis.md) | +| APK Android | Déclarations du manifeste, classes, méthodes décompilées et références | JADX headless et un JDK complet sous Linux/macOS/Windows x64 ; [guide Android](docs/guides/android/android-analysis.md) | +| Appareils Android | Appareils, paquets, processus, journaux, dumps, captures d'écran et transferts d'APK/fichiers | adb fourni par l'appelant (émulateur ou appareil) ; [guide ADB](docs/guides/android/adb-device-analysis.md) | +| Projets JEB | Unités de projet fournies par le moteur, condensés d'artefacts et pseudo-code de types/méthodes | Un client JEB démarré par l'appelant servant MCP, sélectionné via REA_JEB_MCP_URL ; [guide JEB](docs/providers/jeb-analysis.md) | +| Ressources Android | Manifeste décodé, tables de chaînes, langues et faits de version | Lanceur Apktool fourni par l'appelant ; [guide des ressources](docs/guides/android/apktool-resource-analysis.md) | +| Applications Flutter | Empreinte de snapshot Dart, condensés de bibliothèques par ABI et provenance de build du moteur | Aucune (analyse APK statique) ; [guide Flutter](docs/guides/android/flutter-analysis.md) | +| Firmware | Régions, résultats d'extraction et passage de relais vers l'analyse native | Binwalk / Unblob sous Linux ; [guide firmware](docs/guides/firmware/firmware-analysis.md) | +| Paquets enregistrés | Champs sélectionnés, valeurs répétées, filtres et règles de décodage | Linux: TShark 4.x + prlimit; [guide des captures](docs/guides/data/packet-captures.md) | +| Signaux logiques enregistrés | Annotations du décodeur, plages d’échantillons et diagnostics | Linux: sigrok-cli 0.7.2 + prlimit; [guide des signaux](docs/guides/signals/signal-recordings.md) | | Paquets et ressources | Inventaires de fichiers, empreintes, plists, anatomie des bundles Apple et ressources extraites | [Guide artefacts et JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [applications Apple](docs/guides/apple/apple-application-analysis.md) | -| Comportement des processus | Sortie du terminal, interactions, code de sortie, observations du système de fichiers et comparaisons | Linux/macOS avec un PTY natif ; [capture de processus](docs/guides/runtime/process-capture.md) | +| Comportement des processus | Sortie du terminal, interactions, code de sortie, observations du système de fichiers et comparaisons | Linux/macOS avec un PTY natif ; [capture de processus](docs/guides/runtime/process-capture.md) | L'inspection statique JavaScript et .NET lit les fichiers fournis sans exécuter l'application. La capture à l'exécution lance la cible choisie ou interagit avec elle avec vos permissions utilisateur ; chaque guide d'exécution décrit ses effets. @@ -265,7 +266,7 @@ Signalez les vulnérabilités via [SECURITY.md](SECURITY.md). ## Historique des étoiles -🎉 **110 000 étoiles GitHub — merci !** +🎉 **170 000 étoiles GitHub — merci !** Merci à toutes les personnes qui utilisent REA, signalent des bugs, proposent des fonctionnalités, testent les builds et contribuent des correctifs. diff --git a/README_id.md b/README_id.md index 5105c3728..b292acacf 100644 --- a/README_id.md +++ b/README_id.md @@ -136,27 +136,28 @@ REA memerlukan Node.js 22.x (>=22.19), 24.x (>=24.11), atau 26+, beserta npm. Alat tambahan dan dukungan sistem host bergantung pada target yang dianalisis: -| Target | Hasil yang diberikan REA | Persyaratan dan panduan | -| -------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, atau IDA; [analisis native](https://rea.tools/id/guides/native/) | -| Tata letak ELF offline | Bagian, segmen, simbol/relokasi asli, dan kandidat mitigasi statis | pwntools yang disediakan pemanggil pada Linux x64; [diagnostik biner](docs/guides/native/binary-diagnostics.md) | -| Artefak WASM | Validasi, bagian, bentuk WAT import/ekspor yang tepat, dan WAT yang didekode | WABT 1.0.42 yang disediakan pemanggil; `inspect_wasm_artifact` | -| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal; [panduan EVM offline](docs/guides/evm/evm-bytecode.md) | -| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil; GDB/pwndbg opsional; [crash yang direkam](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](https://rea.tools/id/guides/javascript/) | -| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](https://rea.tools/id/guides/browser/) | -| Rekaman jaringan tersimpan | Permintaan, respons, payload yang terekspos, dan lokasi sumber | HAR; mitmdump di Linux untuk rekaman native mitmproxy; [panduan rekaman](docs/guides/web/web-network-captures.md) | -| Assembly .NET | Metadata, instruksi CIL, dependensi native yang dideklarasikan, dan perbandingan build | Tidak ada (hanya analisis statis); [panduan kode terkelola](docs/guides/managed/managed-code-analysis.md) | -| APK Android | Deklarasi manifest, kelas, metode hasil dekompilasi, dan referensi | JADX mode headless dan JDK lengkap di Linux/macOS/Windows x64; [panduan Android](docs/guides/android/android-analysis.md) | -| Perangkat Android | Perangkat, paket, proses, log, dump, tangkapan layar, serta transfer APK/berkas | adb buatan pemanggil (emulator atau perangkat); [panduan ADB](docs/guides/android/adb-device-analysis.md) | -| Proyek JEB | Unit proyek bertenaga mesin, hash artefak, dan pseudokode tipe/metode | Klien JEB yang dijalankan pemanggil dan menyajikan MCP, dipilih dengan REA_JEB_MCP_URL; [panduan JEB](docs/providers/jeb-analysis.md) | -| Resource Android | Manifest terdekode, tabel string, lokal, dan fakta versi | Peluncur Apktool buatan pemanggil; [panduan resource](docs/guides/android/apktool-resource-analysis.md) | -| Aplikasi Flutter | Hash snapshot Dart, hash pustaka per ABI, dan asal build engine | Tidak ada (parsing APK statis); [panduan Flutter](docs/guides/android/flutter-analysis.md) | -| Firmware | Wilayah, hasil ekstraksi, dan pengalihan ke analisis native | Binwalk / Unblob di Linux; [panduan firmware](docs/guides/firmware/firmware-analysis.md) | -| Paket rekaman | Kolom terpilih, nilai berulang, filter, dan aturan decode-as | Linux: TShark 4.x + prlimit; [panduan tangkapan](docs/guides/data/packet-captures.md) | -| Sinyal logika terekam | Anotasi dekoder, rentang sampel, dan diagnostik | Linux: sigrok-cli 0.7.2 + prlimit; [panduan sinyal](docs/guides/signals/signal-recordings.md) | +| Target | Hasil yang diberikan REA | Persyaratan dan panduan | +| -------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| Biner native | Pseudocode, assembly, string, simbol, pemanggilan, dan referensi | Hopper, Ghidra, atau IDA; [analisis native](https://rea.tools/id/guides/native/) | +| Tata letak ELF offline | Bagian, segmen, simbol/relokasi asli, dan kandidat mitigasi statis | pwntools yang disediakan pemanggil pada Linux x64; [diagnostik biner](docs/guides/native/binary-diagnostics.md) | +| Artefak WASM | Validasi, bagian, bentuk WAT import/ekspor yang tepat, dan WAT yang didekode | WABT 1.0.42 yang disediakan pemanggil; `inspect_wasm_artifact` | +| Bytecode EVM | Selector dispatch, offset byte, argumen yang disimpulkan, dan sifat mutabilitas | Pembawa data raw/hex lokal; [panduan EVM offline](docs/guides/evm/evm-bytecode.md) | +| Crash Linux yang direkam | Catatan mentah, register/sinyal setiap thread yang direkam, dan kandidat pemetaan opsional | pwntools yang disediakan pemanggil; GDB/pwndbg opsional; [crash yang direkam](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Modul, impor, source map, rute, IPC, dan hubungan add-on native | Node.js dan npm; [analisis aplikasi](https://rea.tools/id/guides/javascript/) | +| Situs web | Struktur halaman, skrip, pengamatan jaringan, dan tangkapan layar yang diminta | Peramban berbasis Chrome; [analisis peramban](https://rea.tools/id/guides/browser/) | +| Rekaman jaringan tersimpan | Permintaan, respons, payload yang terekspos, dan lokasi sumber | HAR; mitmdump di Linux untuk rekaman native mitmproxy; [panduan rekaman](docs/guides/web/web-network-captures.md) | +| Capturan paket | Endpoint, DNS, TLS SNI, distribusi protokol, dan permintaan HTTP | tshark dan capinfos buatan pemanggil; [panduan pcap](docs/guides/data/pcap-analysis.md) | +| Assembly .NET | Metadata, instruksi CIL, dependensi native yang dideklarasikan, dan perbandingan build | Tidak ada (hanya analisis statis); [panduan kode terkelola](docs/guides/managed/managed-code-analysis.md) | +| APK Android | Deklarasi manifest, kelas, metode hasil dekompilasi, dan referensi | JADX mode headless dan JDK lengkap di Linux/macOS/Windows x64; [panduan Android](docs/guides/android/android-analysis.md) | +| Perangkat Android | Perangkat, paket, proses, log, dump, tangkapan layar, serta transfer APK/berkas | adb buatan pemanggil (emulator atau perangkat); [panduan ADB](docs/guides/android/adb-device-analysis.md) | +| Proyek JEB | Unit proyek bertenaga mesin, hash artefak, dan pseudokode tipe/metode | Klien JEB yang dijalankan pemanggil dan menyajikan MCP, dipilih dengan REA_JEB_MCP_URL; [panduan JEB](docs/providers/jeb-analysis.md) | +| Resource Android | Manifest terdekode, tabel string, lokal, dan fakta versi | Peluncur Apktool buatan pemanggil; [panduan resource](docs/guides/android/apktool-resource-analysis.md) | +| Aplikasi Flutter | Hash snapshot Dart, hash pustaka per ABI, dan asal build engine | Tidak ada (parsing APK statis); [panduan Flutter](docs/guides/android/flutter-analysis.md) | +| Firmware | Wilayah, hasil ekstraksi, dan pengalihan ke analisis native | Binwalk / Unblob di Linux; [panduan firmware](docs/guides/firmware/firmware-analysis.md) | +| Paket rekaman | Kolom terpilih, nilai berulang, filter, dan aturan decode-as | Linux: TShark 4.x + prlimit; [panduan tangkapan](docs/guides/data/packet-captures.md) | +| Sinyal logika terekam | Anotasi dekoder, rentang sampel, dan diagnostik | Linux: sigrok-cli 0.7.2 + prlimit; [panduan sinyal](docs/guides/signals/signal-recordings.md) | | Paket dan sumber daya | Inventaris berkas, digest, plist, struktur paket Apple, dan sumber daya yang diekstrak | [Panduan artefak dan JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [aplikasi Apple](docs/guides/apple/apple-application-analysis.md) | -| Perilaku proses | Keluaran terminal, interaksi, pengamatan proses keluar dan sistem berkas, serta perbandingan eksekusi | Linux/macOS dengan PTY native; [perekaman proses](docs/guides/runtime/process-capture.md) | +| Perilaku proses | Keluaran terminal, interaksi, pengamatan proses keluar dan sistem berkas, serta perbandingan eksekusi | Linux/macOS dengan PTY native; [perekaman proses](docs/guides/runtime/process-capture.md) | Pemeriksaan JavaScript dan .NET statis membaca berkas yang disediakan tanpa menjalankan aplikasinya. Perekaman runtime menjalankan atau berinteraksi dengan target yang dipilih menggunakan izin pengguna Anda. Setiap panduan runtime menjelaskan dampaknya. @@ -286,7 +287,7 @@ Laporkan kerentanan melalui [SECURITY.md](SECURITY.md). ## Riwayat Bintang -🎉 **110.000 bintang GitHub, terima kasih!** +🎉 **170.000 bintang GitHub, terima kasih!** Terima kasih kepada semua orang yang menggunakan REA, melaporkan bug, meminta fitur, menguji build, dan berkontribusi dalam perbaikan. diff --git a/README_it.md b/README_it.md index ee1547b15..2ec355d94 100644 --- a/README_it.md +++ b/README_it.md @@ -133,27 +133,28 @@ Il tuo agente chiama REA tramite MCP per ispezionare il bersaglio e tracciare il REA richiede Node.js 22.x (>=22.19), 24.x (>=24.11) o 26+, oltre a npm. Strumenti aggiuntivi e supporto host dipendono dal bersaglio: -| Obiettivo | Cosa restituisce REA | Requisiti e guida | -| ---------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra o IDA; [analisi nativa](https://rea.tools/it/guides/native/) | -| Layout ELF offline | Sezioni, segmenti, simboli/relocazioni originali e candidati mitigazioni statiche | pwntools fornito dal chiamante su Linux x64; [diagnostica binaria](docs/guides/native/binary-diagnostics.md) | -| Artefatto WASM | Convalida, sezioni, forme WAT di import/export esatte e WAT decodificato | WABT 1.0.42 fornito dal chiamante; `inspect_wasm_artifact` | -| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale; [guida EVM offline](docs/guides/evm/evm-bytecode.md) | -| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante; GDB/pwndbg opzionale; [crash registrati](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](https://rea.tools/it/guides/javascript/) | -| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](https://rea.tools/it/guides/browser/) | -| Acquisizioni di rete salvate | Richieste, risposte, payload esposti e posizioni sorgente | HAR; mitmdump su Linux per acquisizioni mitmproxy native; [guida alle acquisizioni](docs/guides/web/web-network-captures.md) | -| Assembly .NET | Metadati, istruzioni CIL, dipendenze native dichiarate e confronti di build | Nessuno (solo statico); [guida managed-code](docs/guides/managed/managed-code-analysis.md) | -| APK Android | Dichiarazioni manifest, classi, metodi decompilati e riferimenti | JADX headless e un JDK completo su Linux/macOS/Windows x64; [guida Android](docs/guides/android/android-analysis.md) | -| Dispositivi Android | Dispositivi, pacchetti, processi, log, dump, screenshot e trasferimenti APK/file | adb fornito dal chiamante (emulatore o hardware); [guida ADB](docs/guides/android/adb-device-analysis.md) | -| Progetti JEB | Unità di progetto dal motore, digest degli artifact e pseudocodice di tipi/metodi | Client JEB avviato dal chiamante via MCP, selezionato con REA_JEB_MCP_URL; [guida JEB](docs/providers/jeb-analysis.md) | -| Risorse Android | Manifest decodificato, tabelle stringhe, lingue e dati di versione | Launcher Apktool fornito dal chiamante; [guida alle risorse](docs/guides/android/apktool-resource-analysis.md) | -| App Flutter | Hash dello snapshot Dart, digest delle librerie per ABI e provenienza della build del motore | Nessuno (analisi APK statica); [guida Flutter](docs/guides/android/flutter-analysis.md) | -| Firmware | Regioni, risultati di estrazione e passaggi all'analisi nativa | Binwalk / Unblob su Linux; [guida firmware](docs/guides/firmware/firmware-analysis.md) | -| Pacchetti registrati | Campi selezionati, valori ripetuti, filtri e regole di decodifica | Linux: TShark 4.x + prlimit; [guida alle catture](docs/guides/data/packet-captures.md) | -| Segnali logici registrati | Annotazioni del decoder, intervalli di campioni e diagnostica | Linux: sigrok-cli 0.7.2 + prlimit; [guida ai segnali](docs/guides/signals/signal-recordings.md) | +| Obiettivo | Cosa restituisce REA | Requisiti e guida | +| ---------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| Binari nativi | Pseudocodice, assembly, stringhe, simboli, chiamate e riferimenti | Hopper, Ghidra o IDA; [analisi nativa](https://rea.tools/it/guides/native/) | +| Layout ELF offline | Sezioni, segmenti, simboli/relocazioni originali e candidati mitigazioni statiche | pwntools fornito dal chiamante su Linux x64; [diagnostica binaria](docs/guides/native/binary-diagnostics.md) | +| Artefatto WASM | Convalida, sezioni, forme WAT di import/export esatte e WAT decodificato | WABT 1.0.42 fornito dal chiamante; `inspect_wasm_artifact` | +| Bytecode EVM | Selettori di dispatch, offset dei byte, argomenti inferiti e mutabilità | Carrier raw/hex locale; [guida EVM offline](docs/guides/evm/evm-bytecode.md) | +| Crash Linux registrati | Note grezze, registri/segnai di ogni thread registrato e candidati mapping opzionali | pwntools fornito dal chiamante; GDB/pwndbg opzionale; [crash registrati](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Moduli, import, source map, route, IPC e relazioni con add-on nativi | Node.js e npm; [analisi delle applicazioni](https://rea.tools/it/guides/javascript/) | +| Siti web | Struttura della pagina, script, osservazioni di rete e screenshot richiesti | Un browser della famiglia Chrome; [analisi browser](https://rea.tools/it/guides/browser/) | +| Acquisizioni di rete salvate | Richieste, risposte, payload esposti e posizioni sorgente | HAR; mitmdump su Linux per acquisizioni mitmproxy native; [guida alle acquisizioni](docs/guides/web/web-network-captures.md) | +| Captured di pacchetti | Endpoint, DNS, TLS SNI, distribuzione dei protocolli e richieste HTTP | tshark e capinfos forniti dal chiamante; [guida pcap](docs/guides/data/pcap-analysis.md) | +| Assembly .NET | Metadati, istruzioni CIL, dipendenze native dichiarate e confronti di build | Nessuno (solo statico); [guida managed-code](docs/guides/managed/managed-code-analysis.md) | +| APK Android | Dichiarazioni manifest, classi, metodi decompilati e riferimenti | JADX headless e un JDK completo su Linux/macOS/Windows x64; [guida Android](docs/guides/android/android-analysis.md) | +| Dispositivi Android | Dispositivi, pacchetti, processi, log, dump, screenshot e trasferimenti APK/file | adb fornito dal chiamante (emulatore o hardware); [guida ADB](docs/guides/android/adb-device-analysis.md) | +| Progetti JEB | Unità di progetto dal motore, digest degli artifact e pseudocodice di tipi/metodi | Client JEB avviato dal chiamante via MCP, selezionato con REA_JEB_MCP_URL; [guida JEB](docs/providers/jeb-analysis.md) | +| Risorse Android | Manifest decodificato, tabelle stringhe, lingue e dati di versione | Launcher Apktool fornito dal chiamante; [guida alle risorse](docs/guides/android/apktool-resource-analysis.md) | +| App Flutter | Hash dello snapshot Dart, digest delle librerie per ABI e provenienza della build del motore | Nessuno (analisi APK statica); [guida Flutter](docs/guides/android/flutter-analysis.md) | +| Firmware | Regioni, risultati di estrazione e passaggi all'analisi nativa | Binwalk / Unblob su Linux; [guida firmware](docs/guides/firmware/firmware-analysis.md) | +| Pacchetti registrati | Campi selezionati, valori ripetuti, filtri e regole di decodifica | Linux: TShark 4.x + prlimit; [guida alle catture](docs/guides/data/packet-captures.md) | +| Segnali logici registrati | Annotazioni del decoder, intervalli di campioni e diagnostica | Linux: sigrok-cli 0.7.2 + prlimit; [guida ai segnali](docs/guides/signals/signal-recordings.md) | | Pacchetti e risorse | Inventari file, digest, plist, anatomia dei bundle Apple e risorse estratte | [Guida artifact e JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [Applicazioni Apple](docs/guides/apple/apple-application-analysis.md) | -| Comportamento dei processi | Output del terminale, interazioni, osservazioni su uscita e filesystem ed confronti di esecuzione | Linux/macOS con un PTY nativo; [cattura dei processi](docs/guides/runtime/process-capture.md) | +| Comportamento dei processi | Output del terminale, interazioni, osservazioni su uscita e filesystem ed confronti di esecuzione | Linux/macOS con un PTY nativo; [cattura dei processi](docs/guides/runtime/process-capture.md) | L'ispezione statica di JavaScript e .NET legge i file forniti senza eseguire l'applicazione. La cattura a runtime esegue o interagisce con il bersaglio selezionato usando i tuoi permessi utente; ogni guida runtime descrive i suoi effetti. @@ -265,7 +266,7 @@ Segnala vulnerabilità tramite [SECURITY.md](SECURITY.md). ## Cronologia delle stelle -🎉 **110.000 stelle su GitHub — grazie!** +🎉 **170.000 stelle su GitHub — grazie!** Grazie a tutti coloro che usano REA, segnalano bug, propongono funzionalità, testano le build e contribuiscono con correzioni. diff --git a/README_ja.md b/README_ja.md index 839ddaf4d..87ed1433d 100644 --- a/README_ja.md +++ b/README_ja.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup REA には Node.js 22.x(>=22.19)、24.x(>=24.11)、または 26+ と npm が必要です。追加のツールや対応ホストは、対象によって異なります。 -| 対象 | REA が返すもの | 要件とガイド | -| -------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、または IDA;[ネイティブ分析](https://rea.tools/ja/guides/native/) | -| オフライン ELF レイアウト | セクション、セグメント、元のシンボル/再配置情報、静的解析によるセキュリティ対策の候補 | Linux x64 で利用者が用意する pwntools;[バイナリ診断](docs/guides/native/binary-diagnostics.md) | -| EVM バイトコード | ディスパッチセレクター、バイトオフセット、推定された引数と状態変更の可否 | Linux x64 上のローカルの生バイト/16 進数の入力ファイル;[オフライン EVM ガイド](docs/guides/evm/evm-bytecode.md) | -| 記録済みの Linux クラッシュ | 生の note レコード、記録された全スレッドのレジスター/シグナル、任意のマッピング候補 | Linux x64 で利用者が用意する pwntools;GDB/pwndbg は任意;[記録済みクラッシュ](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | モジュール、インポート、ソースマップ、ルート、IPC、ネイティブアドオンの関係 | Node.js と npm;[アプリケーション分析](https://rea.tools/ja/guides/javascript/) | -| ウェブサイト | ページ構造、スクリプト、ネットワークの観測結果、依頼されたスクリーンショット | Chrome 系ブラウザー;[ブラウザー分析](https://rea.tools/ja/guides/browser/) | -| 保存済みのネットワークキャプチャ | リクエスト、レスポンス、取得可能なペイロード、ソース内の位置 | HAR;mitmproxy ネイティブ形式のキャプチャには Linux 上の mitmdump;[キャプチャガイド](docs/guides/web/web-network-captures.md) | -| .NET アセンブリ | メタデータ、CIL 命令、宣言されたネイティブ依存関係、ビルドの比較 | 静的な検査;[マネージドコードのガイド](docs/guides/managed/managed-code-analysis.md) | -| Android APK | マニフェストの宣言、クラス、逆コンパイルされたメソッド、参照 | Linux/macOS/Windows x64 上のヘッドレス JADX と完全な JDK;[Android ガイド](docs/guides/android/android-analysis.md) | -| Android デバイス | デバイス、パッケージ、プロセス、ログ、ダンプ、スクリーンキャプチャ、APK/ファイル転送 | 呼び出し側が用意した adb(エミュレーターまたは実機);[ADB ガイド](docs/guides/android/adb-device-analysis.md) | -| JEBプロジェクト | エンジンによるプロジェクトユニット、アーティファクトのダイジェスト、型/メソッドの擬似コード | 呼び出し側が起動し MCP を提供する JEB クライアント(REA_JEB_MCP_URL で選択);[JEB ガイド](docs/providers/jeb-analysis.md) | -| Android リソース | デコードされたマニフェスト、文字列テーブル、ロケール、バージョン情報 | 呼び出し側が用意した Apktool ランチャー;[リソースガイド](docs/guides/android/apktool-resource-analysis.md) | -| Flutter アプリ | Dart スナップショットハッシュ、ABI ごとのライブラリダイジェスト、エンジンビルドの来歴 | 不要(静的 APK 解析);[Flutter ガイド](docs/guides/android/flutter-analysis.md) | -| ファームウェア | 領域、抽出結果、ネイティブ分析への引き継ぎ | Linux 上の Binwalk / Unblob;[ファームウェアガイド](docs/guides/firmware/firmware-analysis.md) | -| 記録済みパケット | 選択フィールド、繰り返し値、フィルター、デコード指定 | Linux: TShark 4.x + prlimit; [キャプチャガイド](docs/guides/data/packet-captures.md) | -| 記録済みロジック信号 | デコーダ注釈、サンプル範囲、診断情報 | Linux: sigrok-cli 0.7.2 + prlimit; [信号記録ガイド](docs/guides/signals/signal-recordings.md) | +| 対象 | REA が返すもの | 要件とガイド | +| -------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| ネイティブバイナリ | 疑似コード、アセンブリ、文字列、シンボル、呼び出し、参照 | Hopper、Ghidra、または IDA;[ネイティブ分析](https://rea.tools/ja/guides/native/) | +| オフライン ELF レイアウト | セクション、セグメント、元のシンボル/再配置情報、静的解析によるセキュリティ対策の候補 | Linux x64 で利用者が用意する pwntools;[バイナリ診断](docs/guides/native/binary-diagnostics.md) | +| EVM バイトコード | ディスパッチセレクター、バイトオフセット、推定された引数と状態変更の可否 | Linux x64 上のローカルの生バイト/16 進数の入力ファイル;[オフライン EVM ガイド](docs/guides/evm/evm-bytecode.md) | +| 記録済みの Linux クラッシュ | 生の note レコード、記録された全スレッドのレジスター/シグナル、任意のマッピング候補 | Linux x64 で利用者が用意する pwntools;GDB/pwndbg は任意;[記録済みクラッシュ](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | モジュール、インポート、ソースマップ、ルート、IPC、ネイティブアドオンの関係 | Node.js と npm;[アプリケーション分析](https://rea.tools/ja/guides/javascript/) | +| ウェブサイト | ページ構造、スクリプト、ネットワークの観測結果、依頼されたスクリーンショット | Chrome 系ブラウザー;[ブラウザー分析](https://rea.tools/ja/guides/browser/) | +| 保存済みのネットワークキャプチャ | リクエスト、レスポンス、取得可能なペイロード、ソース内の位置 | HAR;mitmproxy ネイティブ形式のキャプチャには Linux 上の mitmdump;[キャプチャガイド](docs/guides/web/web-network-captures.md) | +| パケットキャプチャ | エンドポイント、DNS、TLS SNI、プロトコル分布、HTTPリクエスト | 呼び出し側が用意した tshark と capinfos;[pcapガイド](docs/guides/data/pcap-analysis.md) | +| .NET アセンブリ | メタデータ、CIL 命令、宣言されたネイティブ依存関係、ビルドの比較 | 静的な検査;[マネージドコードのガイド](docs/guides/managed/managed-code-analysis.md) | +| Android APK | マニフェストの宣言、クラス、逆コンパイルされたメソッド、参照 | Linux/macOS/Windows x64 上のヘッドレス JADX と完全な JDK;[Android ガイド](docs/guides/android/android-analysis.md) | +| Android デバイス | デバイス、パッケージ、プロセス、ログ、ダンプ、スクリーンキャプチャ、APK/ファイル転送 | 呼び出し側が用意した adb(エミュレーターまたは実機);[ADB ガイド](docs/guides/android/adb-device-analysis.md) | +| JEBプロジェクト | エンジンによるプロジェクトユニット、アーティファクトのダイジェスト、型/メソッドの擬似コード | 呼び出し側が起動し MCP を提供する JEB クライアント(REA_JEB_MCP_URL で選択);[JEB ガイド](docs/providers/jeb-analysis.md) | +| Android リソース | デコードされたマニフェスト、文字列テーブル、ロケール、バージョン情報 | 呼び出し側が用意した Apktool ランチャー;[リソースガイド](docs/guides/android/apktool-resource-analysis.md) | +| Flutter アプリ | Dart スナップショットハッシュ、ABI ごとのライブラリダイジェスト、エンジンビルドの来歴 | 不要(静的 APK 解析);[Flutter ガイド](docs/guides/android/flutter-analysis.md) | +| ファームウェア | 領域、抽出結果、ネイティブ分析への引き継ぎ | Linux 上の Binwalk / Unblob;[ファームウェアガイド](docs/guides/firmware/firmware-analysis.md) | +| 記録済みパケット | 選択フィールド、繰り返し値、フィルター、デコード指定 | Linux: TShark 4.x + prlimit; [キャプチャガイド](docs/guides/data/packet-captures.md) | +| 記録済みロジック信号 | デコーダ注釈、サンプル範囲、診断情報 | Linux: sigrok-cli 0.7.2 + prlimit; [信号記録ガイド](docs/guides/signals/signal-recordings.md) | | パッケージとリソース | ファイル一覧、ダイジェスト、plist、Apple バンドルの構造、抽出されたリソース | [アーティファクトと JavaScript のガイド](docs/guides/javascript/javascript-artifact-reconstruction.md)、[Apple アプリケーション](docs/guides/apple/apple-application-analysis.md) | -| プロセスの動作 | ターミナル出力、対話、終了とファイルシステムの観測結果、実行の比較 | ネイティブ PTY を備えた Linux/macOS;[プロセスキャプチャ](docs/guides/runtime/process-capture.md) | +| プロセスの動作 | ターミナル出力、対話、終了とファイルシステムの観測結果、実行の比較 | ネイティブ PTY を備えた Linux/macOS;[プロセスキャプチャ](docs/guides/runtime/process-capture.md) | 静的な JavaScript と .NET の検査は、指定されたファイルを読み取り、アプリケーションを実行しません。実行時キャプチャは、あなたのユーザー権限で対象を実行したり、対象とやり取りしたりします。それぞれの実行時ガイドに、どのような操作が行われるかを記載しています。 @@ -263,7 +264,7 @@ npx rea-agents@latest setup ## スター履歴 -🎉 **GitHub スター 110,000 件、ありがとうございます!** +🎉 **GitHub スター 170,000 件、ありがとうございます!** REA の利用、バグ報告、機能の要望、ビルドのテスト、修正への貢献に感謝します。 diff --git a/README_ko.md b/README_ko.md index 3aad440d8..0ab40d1ba 100644 --- a/README_ko.md +++ b/README_ko.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup REA에는 Node.js 22.x(>=22.19), 24.x(>=24.11) 또는 26+와 npm이 필요합니다. 추가 도구와 호스트 지원은 대상에 따라 다릅니다. -| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 | -| --------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](https://rea.tools/ko/guides/native/) | -| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](docs/guides/native/binary-diagnostics.md) | -| EVM 바이트코드 | 디스패치 선택자, 바이트 오프셋, 추론한 인자와 상태 변경 가능 여부 | Linux x64의 로컬 원시 바이트/16진수 입력 파일; [오프라인 EVM 가이드](docs/guides/evm/evm-bytecode.md) | -| 기록된 Linux 크래시 | 원시 note 레코드, 기록된 모든 스레드의 레지스터/시그널, 선택적 매핑 후보 | Linux x64에서 호출자가 제공하는 pwntools; GDB/pwndbg는 선택 사항; [기록된 크래시](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; [애플리케이션 분석](https://rea.tools/ko/guides/javascript/) | -| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](https://rea.tools/ko/guides/browser/) | -| 저장된 네트워크 캡처 | 요청, 응답, 접근 가능한 페이로드, 소스 위치 | HAR; mitmproxy 네이티브 캡처에는 Linux의 mitmdump; [캡처 가이드](docs/guides/web/web-network-captures.md) | -| .NET 어셈블리 | 메타데이터, CIL 명령, 선언된 네이티브 의존성, 빌드 비교 | 정적 검사; [관리 코드 가이드](docs/guides/managed/managed-code-analysis.md) | -| Android APK | 매니페스트 선언, 클래스, 디컴파일된 메서드, 참조 | Linux/macOS/Windows x64의 헤드리스 JADX와 전체 JDK; [Android 가이드](docs/guides/android/android-analysis.md) | -| Android 기기 | 기기, 패키지, 프로세스, 로그, 덤프, 화면 캡처, APK/파일 전송 | 호출자 제공 adb(에뮬레이터 또는 실제 기기); [ADB 가이드](docs/guides/android/adb-device-analysis.md) | -| JEB 프로젝트 | 엔진 기반 프로젝트 유닛, 아티팩트 해시, 타입/메서드 의사코드 | 호출자가 시작하고 MCP를 제공하는 JEB 클라이언트(REA_JEB_MCP_URL로 선택); [JEB 가이드](docs/providers/jeb-analysis.md) | -| Android 리소스 | 디코딩된 매니페스트, 문자열 테이블, 로캘, 버전 정보 | 호출자 제공 Apktool 런처; [리소스 가이드](docs/guides/android/apktool-resource-analysis.md) | -| Flutter 앱 | Dart 스냅샷 해시, ABI별 라이브러리 해시, 엔진 빌드 출처 | 없음 (정적 APK 파싱); [Flutter 가이드](docs/guides/android/flutter-analysis.md) | -| 펌웨어 | 영역, 추출 결과, 네이티브 분석으로 전달할 정보 | Linux의 Binwalk / Unblob; [펌웨어 가이드](docs/guides/firmware/firmware-analysis.md) | -| 기록된 패킷 | 선택 필드, 반복 값, 필터 및 디코딩 규칙 | Linux: TShark 4.x + prlimit; [캡처 가이드](docs/guides/data/packet-captures.md) | -| 기록된 논리 신호 | 디코더 주석, 샘플 범위, 진단 정보 | Linux: sigrok-cli 0.7.2 + prlimit; [신호 기록 가이드](docs/guides/signals/signal-recordings.md) | +| 대상 | REA가 반환하는 내용 | 요구 사항 및 가이드 | +| --------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| 네이티브 바이너리 | 의사 코드, 어셈블리, 문자열, 심볼, 호출, 참조 | Hopper, Ghidra 또는 IDA; [네이티브 분석](https://rea.tools/ko/guides/native/) | +| 오프라인 ELF 레이아웃 | 섹션, 세그먼트, 원본 심볼/재배치 정보, 정적 분석으로 얻은 보안 완화 기법 후보 | Linux x64에서 호출자가 제공하는 pwntools; [바이너리 진단](docs/guides/native/binary-diagnostics.md) | +| EVM 바이트코드 | 디스패치 선택자, 바이트 오프셋, 추론한 인자와 상태 변경 가능 여부 | Linux x64의 로컬 원시 바이트/16진수 입력 파일; [오프라인 EVM 가이드](docs/guides/evm/evm-bytecode.md) | +| 기록된 Linux 크래시 | 원시 note 레코드, 기록된 모든 스레드의 레지스터/시그널, 선택적 매핑 후보 | Linux x64에서 호출자가 제공하는 pwntools; GDB/pwndbg는 선택 사항; [기록된 크래시](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | 모듈, 임포트, 소스 맵, 라우트, IPC, 네이티브 애드온 관계 | Node.js와 npm; [애플리케이션 분석](https://rea.tools/ko/guides/javascript/) | +| 웹사이트 | 페이지 구조, 스크립트, 네트워크 관찰 결과, 요청한 스크린샷 | Chrome 계열 브라우저; [브라우저 분석](https://rea.tools/ko/guides/browser/) | +| 저장된 네트워크 캡처 | 요청, 응답, 접근 가능한 페이로드, 소스 위치 | HAR; mitmproxy 네이티브 캡처에는 Linux의 mitmdump; [캡처 가이드](docs/guides/web/web-network-captures.md) | +| 패킷 캡처 | 엔드포인트, DNS, TLS SNI, 프로토콜 분포, HTTP 요청 | 호출자 제공 tshark 및 capinfos; [pcap 가이드](docs/guides/data/pcap-analysis.md) | +| .NET 어셈블리 | 메타데이터, CIL 명령, 선언된 네이티브 의존성, 빌드 비교 | 정적 검사; [관리 코드 가이드](docs/guides/managed/managed-code-analysis.md) | +| Android APK | 매니페스트 선언, 클래스, 디컴파일된 메서드, 참조 | Linux/macOS/Windows x64의 헤드리스 JADX와 전체 JDK; [Android 가이드](docs/guides/android/android-analysis.md) | +| Android 기기 | 기기, 패키지, 프로세스, 로그, 덤프, 화면 캡처, APK/파일 전송 | 호출자 제공 adb(에뮬레이터 또는 실제 기기); [ADB 가이드](docs/guides/android/adb-device-analysis.md) | +| JEB 프로젝트 | 엔진 기반 프로젝트 유닛, 아티팩트 해시, 타입/메서드 의사코드 | 호출자가 시작하고 MCP를 제공하는 JEB 클라이언트(REA_JEB_MCP_URL로 선택); [JEB 가이드](docs/providers/jeb-analysis.md) | +| Android 리소스 | 디코딩된 매니페스트, 문자열 테이블, 로캘, 버전 정보 | 호출자 제공 Apktool 런처; [리소스 가이드](docs/guides/android/apktool-resource-analysis.md) | +| Flutter 앱 | Dart 스냅샷 해시, ABI별 라이브러리 해시, 엔진 빌드 출처 | 없음 (정적 APK 파싱); [Flutter 가이드](docs/guides/android/flutter-analysis.md) | +| 펌웨어 | 영역, 추출 결과, 네이티브 분석으로 전달할 정보 | Linux의 Binwalk / Unblob; [펌웨어 가이드](docs/guides/firmware/firmware-analysis.md) | +| 기록된 패킷 | 선택 필드, 반복 값, 필터 및 디코딩 규칙 | Linux: TShark 4.x + prlimit; [캡처 가이드](docs/guides/data/packet-captures.md) | +| 기록된 논리 신호 | 디코더 주석, 샘플 범위, 진단 정보 | Linux: sigrok-cli 0.7.2 + prlimit; [신호 기록 가이드](docs/guides/signals/signal-recordings.md) | | 패키지 및 리소스 | 파일 목록, 다이제스트, plist, Apple 번들 구조, 추출한 리소스 | [아티팩트 및 JavaScript 가이드](docs/guides/javascript/javascript-artifact-reconstruction.md), [Apple 애플리케이션](docs/guides/apple/apple-application-analysis.md) | -| 프로세스 동작 | 터미널 출력, 상호작용, 종료 및 파일 시스템 관찰 결과, 실행 비교 | 네이티브 PTY를 지원하는 Linux/macOS; [프로세스 캡처](docs/guides/runtime/process-capture.md) | +| 프로세스 동작 | 터미널 출력, 상호작용, 종료 및 파일 시스템 관찰 결과, 실행 비교 | 네이티브 PTY를 지원하는 Linux/macOS; [프로세스 캡처](docs/guides/runtime/process-capture.md) | 정적 JavaScript 및 .NET 검사는 제공된 파일을 읽으며 애플리케이션을 실행하지 않습니다. 런타임 캡처는 사용자의 권한으로 선택한 대상을 실행하거나 대상과 상호작용합니다. 각 런타임 가이드에서 그 영향을 설명합니다. @@ -263,7 +264,7 @@ npx rea-agents@latest setup ## 스타 기록 -🎉 **GitHub 스타 110,000개, 감사합니다!** +🎉 **GitHub 스타 170,000개, 감사합니다!** REA를 사용하고, 버그를 보고하고, 기능을 요청하고, 빌드를 테스트하고, 수정에 기여해 주신 모든 분께 감사드립니다. diff --git a/README_pl.md b/README_pl.md index fdc07a59f..4092c6aff 100644 --- a/README_pl.md +++ b/README_pl.md @@ -130,26 +130,27 @@ Twój agent wywołuje REA przez MCP, aby analizować cel i śledzić istotny kod REA wymaga Node.js 22.x (>=22.19), 24.x (>=24.11) lub 26+ oraz npm. Dodatkowe narzędzia i obsługiwane platformy zależą od celu analizy: -| Cel | Co zwraca REA | Wymagania i przewodnik | -| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra lub IDA; [analiza kodu natywnego](https://rea.tools/pl/guides/native/) | -| Układ pliku ELF w trybie offline | Sekcje, segmenty, oryginalne symbole/relokacje i potencjalne mechanizmy zabezpieczeń wskazane przez analizę statyczną | pwntools dostarczone przez użytkownika w systemie Linux x64; [diagnostyka plików binarnych](docs/guides/native/binary-diagnostics.md) | -| Kod bajtowy EVM | Selektory wywołań, przesunięcia bajtowe, wywnioskowane argumenty i mutowalność | Lokalny plik z surowymi bajtami lub zapisem szesnastkowym w systemie Linux x64; [przewodnik EVM offline](docs/guides/evm/evm-bytecode.md) | -| Zarejestrowane awarie systemu Linux | Surowe rekordy note, rejestry/sygnały każdego zarejestrowanego wątku i opcjonalni kandydaci na mapowania | pwntools dostarczone przez użytkownika w systemie Linux x64; opcjonalnie GDB/pwndbg; [zarejestrowane awarie](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Moduły, importy, mapy źródeł, trasy, IPC i powiązania z natywnymi dodatkami | Node.js i npm; [analiza aplikacji](https://rea.tools/pl/guides/javascript/) | -| Strony internetowe | Struktura strony, skrypty, obserwacje sieciowe i zamówione zrzuty ekranu | Przeglądarka z rodziny Chrome; [analiza w przeglądarce](https://rea.tools/pl/guides/browser/) | -| Zapisane przechwycenia ruchu sieciowego | Żądania, odpowiedzi, dostępne dane przesyłane i lokalizacje źródłowe | HAR; mitmdump w systemie Linux dla natywnych przechwyceń mitmproxy; [przewodnik przechwytywania](docs/guides/web/web-network-captures.md) | -| Zestawy .NET | Metadane, instrukcje CIL, zadeklarowane zależności natywne i porównania kompilacji | Analiza statyczna; [przewodnik kodu zarządzanego](docs/guides/managed/managed-code-analysis.md) | -| Pakiety APK dla Androida | Deklaracje manifestu, klasy, zdekompilowane metody i odwołania | JADX bez interfejsu graficznego i pełny JDK w systemach Linux/macOS/Windows x64; [przewodnik Androida](docs/guides/android/android-analysis.md) | -| Urządzenia z Androidem | Urządzenia, pakiety, procesy, logi, zrzuty, zrzuty ekranu oraz transfery APK/plików | adb dostarczony przez wywołującego (emulator lub urządzenie); [przewodnik ADB](docs/guides/android/adb-device-analysis.md) | -| Projekty JEB | Jednostki projektu obsługiwane przez silnik, skróty artefaktów i pseudokod typów/metod | Uruchomiony przez wywołującego klient JEB udostępniający MCP, wybrany przez REA_JEB_MCP_URL; [przewodnik JEB](docs/providers/jeb-analysis.md) | -| Zasoby Androida | Zdekodowany manifest, tablice ciągów, języki i informacje o wersji | Należący do wywołującego launcher Apktool; [przewodnik zasobów](docs/guides/android/apktool-resource-analysis.md) | -| Aplikacje Flutter | Hash migawki Dart, sumy bibliotek per ABI i pochodzenie kompilacji silnika | Brak (statyczna analiza APK); [przewodnik Flutter](docs/guides/android/flutter-analysis.md) | -| Oprogramowanie układowe | Regiony, wyniki wyodrębniania i przekazanie do analizy kodu natywnego | Binwalk / Unblob w systemie Linux; [przewodnik oprogramowania układowego](docs/guides/firmware/firmware-analysis.md) | -| Zapisane pakiety | Wybrane pola, powtarzane wartości, filtry i reguły dekodowania | Linux: TShark 4.x + prlimit; [przewodnik po przechwyconych pakietach](docs/guides/data/packet-captures.md) | -| Zapisane sygnały logiczne | Adnotacje dekodera, zakresy próbek i diagnostyka | Linux: sigrok-cli 0.7.2 + prlimit; [przewodnik po sygnałach](docs/guides/signals/signal-recordings.md) | +| Cel | Co zwraca REA | Wymagania i przewodnik | +| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| Natywne pliki binarne | Pseudokod, kod asemblera, ciągi znaków, symbole, wywołania i odwołania | Hopper, Ghidra lub IDA; [analiza kodu natywnego](https://rea.tools/pl/guides/native/) | +| Układ pliku ELF w trybie offline | Sekcje, segmenty, oryginalne symbole/relokacje i potencjalne mechanizmy zabezpieczeń wskazane przez analizę statyczną | pwntools dostarczone przez użytkownika w systemie Linux x64; [diagnostyka plików binarnych](docs/guides/native/binary-diagnostics.md) | +| Kod bajtowy EVM | Selektory wywołań, przesunięcia bajtowe, wywnioskowane argumenty i mutowalność | Lokalny plik z surowymi bajtami lub zapisem szesnastkowym w systemie Linux x64; [przewodnik EVM offline](docs/guides/evm/evm-bytecode.md) | +| Zarejestrowane awarie systemu Linux | Surowe rekordy note, rejestry/sygnały każdego zarejestrowanego wątku i opcjonalni kandydaci na mapowania | pwntools dostarczone przez użytkownika w systemie Linux x64; opcjonalnie GDB/pwndbg; [zarejestrowane awarie](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Moduły, importy, mapy źródeł, trasy, IPC i powiązania z natywnymi dodatkami | Node.js i npm; [analiza aplikacji](https://rea.tools/pl/guides/javascript/) | +| Strony internetowe | Struktura strony, skrypty, obserwacje sieciowe i zamówione zrzuty ekranu | Przeglądarka z rodziny Chrome; [analiza w przeglądarce](https://rea.tools/pl/guides/browser/) | +| Zapisane przechwycenia ruchu sieciowego | Żądania, odpowiedzi, dostępne dane przesyłane i lokalizacje źródłowe | HAR; mitmdump w systemie Linux dla natywnych przechwyceń mitmproxy; [przewodnik przechwytywania](docs/guides/web/web-network-captures.md) | +| Przechwytywanie pakietów | Punkty końcowe, DNS, TLS SNI, dystrybucja protokołów i żądania HTTP | Dostarczone przez wywołującego tshark i capinfos; [przewodnik pcap](docs/guides/data/pcap-analysis.md) | +| Zestawy .NET | Metadane, instrukcje CIL, zadeklarowane zależności natywne i porównania kompilacji | Analiza statyczna; [przewodnik kodu zarządzanego](docs/guides/managed/managed-code-analysis.md) | +| Pakiety APK dla Androida | Deklaracje manifestu, klasy, zdekompilowane metody i odwołania | JADX bez interfejsu graficznego i pełny JDK w systemach Linux/macOS/Windows x64; [przewodnik Androida](docs/guides/android/android-analysis.md) | +| Urządzenia z Androidem | Urządzenia, pakiety, procesy, logi, zrzuty, zrzuty ekranu oraz transfery APK/plików | adb dostarczony przez wywołującego (emulator lub urządzenie); [przewodnik ADB](docs/guides/android/adb-device-analysis.md) | +| Projekty JEB | Jednostki projektu obsługiwane przez silnik, skróty artefaktów i pseudokod typów/metod | Uruchomiony przez wywołującego klient JEB udostępniający MCP, wybrany przez REA_JEB_MCP_URL; [przewodnik JEB](docs/providers/jeb-analysis.md) | +| Zasoby Androida | Zdekodowany manifest, tablice ciągów, języki i informacje o wersji | Należący do wywołującego launcher Apktool; [przewodnik zasobów](docs/guides/android/apktool-resource-analysis.md) | +| Aplikacje Flutter | Hash migawki Dart, sumy bibliotek per ABI i pochodzenie kompilacji silnika | Brak (statyczna analiza APK); [przewodnik Flutter](docs/guides/android/flutter-analysis.md) | +| Oprogramowanie układowe | Regiony, wyniki wyodrębniania i przekazanie do analizy kodu natywnego | Binwalk / Unblob w systemie Linux; [przewodnik oprogramowania układowego](docs/guides/firmware/firmware-analysis.md) | +| Zapisane pakiety | Wybrane pola, powtarzane wartości, filtry i reguły dekodowania | Linux: TShark 4.x + prlimit; [przewodnik po przechwyconych pakietach](docs/guides/data/packet-captures.md) | +| Zapisane sygnały logiczne | Adnotacje dekodera, zakresy próbek i diagnostyka | Linux: sigrok-cli 0.7.2 + prlimit; [przewodnik po sygnałach](docs/guides/signals/signal-recordings.md) | | Pakiety i zasoby | Spisy plików, skróty, pliki plist, struktura pakietów Apple i wyodrębnione zasoby | [Przewodnik artefaktów i JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [aplikacje Apple](docs/guides/apple/apple-application-analysis.md) | -| Zachowanie procesów | Wyjście terminala, interakcje, obserwacje zakończenia i systemu plików oraz porównania uruchomień | Linux/macOS z natywnym PTY; [przechwytywanie procesów](docs/guides/runtime/process-capture.md) | +| Zachowanie procesów | Wyjście terminala, interakcje, obserwacje zakończenia i systemu plików oraz porównania uruchomień | Linux/macOS z natywnym PTY; [przechwytywanie procesów](docs/guides/runtime/process-capture.md) | Statyczna analiza JavaScript i .NET odczytuje dostarczone pliki bez uruchamiania aplikacji. Przechwytywanie w czasie wykonywania uruchamia wybrany cel lub wchodzi z nim w interakcje z uprawnieniami Twojego użytkownika; skutki opisano w odpowiednich przewodnikach. @@ -261,7 +262,7 @@ Zgłaszaj podatności zgodnie z [SECURITY.md](SECURITY.md). ## Historia gwiazdek -🎉 **110 000 gwiazdek na GitHubie — dziękujemy!** +🎉 **170 000 gwiazdek na GitHubie — dziękujemy!** Dziękujemy wszystkim, którzy używają REA, zgłaszają błędy, proponują nowe funkcje, testują kompilacje i przesyłają poprawki. diff --git a/README_pt-BR.md b/README_pt-BR.md index 4e3d4e72f..2b1d88700 100644 --- a/README_pt-BR.md +++ b/README_pt-BR.md @@ -130,26 +130,27 @@ Seu agente chama o REA por MCP para inspecionar o alvo e rastrear o código rele O REA requer Node.js 22.x (>=22.19), 24.x (>=24.11) ou 26+, além do npm. As ferramentas adicionais e os sistemas anfitriões compatíveis dependem do alvo: -| Alvo | O que o REA retorna | Requisitos e guia | -| --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra ou IDA; [análise nativa](https://rea.tools/pt-BR/guides/native/) | -| Estrutura ELF sem execução | Seções, segmentos, símbolos/relocações originais e possíveis mecanismos de mitigação identificados por análise estática | pwntools fornecido pelo chamador no Linux x64; [diagnóstico de binários](docs/guides/native/binary-diagnostics.md) | -| Bytecode EVM | Seletores de despacho, offsets de bytes, argumentos inferidos e mutabilidade | Entrada local com bytes brutos ou representação hexadecimal no Linux x64; [guia de EVM sem execução](docs/guides/evm/evm-bytecode.md) | -| Falhas do Linux registradas | Registros note brutos, registradores/sinais de cada thread registrada e candidatos opcionais a mapeamentos | pwntools fornecido pelo chamador no Linux x64; GDB/pwndbg opcionais; [falhas registradas](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Módulos, importações, source maps, rotas, IPC e relações com complementos nativos | Node.js e npm; [análise de aplicativos](https://rea.tools/pt-BR/guides/javascript/) | -| Sites | Estrutura da página, scripts, observações de rede e capturas de tela solicitadas | Um navegador da família Chrome; [análise do navegador](https://rea.tools/pt-BR/guides/browser/) | -| Capturas de rede salvas | Requisições, respostas, payloads acessíveis e localizações de origem | HAR; mitmdump no Linux para capturas no formato nativo do mitmproxy; [guia de capturas](docs/guides/web/web-network-captures.md) | -| Assemblies .NET | Metadados, instruções CIL, dependências nativas declaradas e comparações de builds | Inspeção estática; [guia de código gerenciado](docs/guides/managed/managed-code-analysis.md) | -| APKs Android | Declarações do manifesto, classes, métodos descompilados e referências | JADX sem interface gráfica e um JDK completo no Linux/macOS/Windows x64; [guia de Android](docs/guides/android/android-analysis.md) | -| Dispositivos Android | Dispositivos, pacotes, processos, logs, despejos, capturas de tela e transferências de APK/arquivos | adb fornecido pelo chamador (emulador ou aparelho); [guia de ADB](docs/guides/android/adb-device-analysis.md) | -| Projetos JEB | Unidades de projeto do motor, hashes de artefatos e pseudocódigo de tipos/métodos | Um cliente JEB iniciado pelo chamador servindo MCP, selecionado com REA_JEB_MCP_URL; [guia de JEB](docs/providers/jeb-analysis.md) | -| Recursos do Android | Manifesto decodificado, tabelas de strings, idiomas e fatos de versão | Lançador do Apktool fornecido pelo chamador; [guia de recursos](docs/guides/android/apktool-resource-analysis.md) | -| Aplicativos Flutter | Hash de snapshot Dart, hashes de bibliotecas por ABI e procedência de build do motor | Nenhuma (análise estática de APK); [guia Flutter](docs/guides/android/flutter-analysis.md) | -| Firmware | Regiões, resultados de extração e encaminhamentos à análise nativa | Binwalk / Unblob no Linux; [guia de firmware](docs/guides/firmware/firmware-analysis.md) | -| Pacotes gravados | Campos selecionados, valores repetidos, filtros e regras de decodificação | Linux: TShark 4.x + prlimit; [guia de capturas](docs/guides/data/packet-captures.md) | -| Sinais lógicos gravados | Anotações do decodificador, intervalos de amostras e diagnósticos | Linux: sigrok-cli 0.7.2 + prlimit; [guia de sinais](docs/guides/signals/signal-recordings.md) | +| Alvo | O que o REA retorna | Requisitos e guia | +| --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| Binários nativos | Pseudocódigo, assembly, strings, símbolos, chamadas e referências | Hopper, Ghidra ou IDA; [análise nativa](https://rea.tools/pt-BR/guides/native/) | +| Estrutura ELF sem execução | Seções, segmentos, símbolos/relocações originais e possíveis mecanismos de mitigação identificados por análise estática | pwntools fornecido pelo chamador no Linux x64; [diagnóstico de binários](docs/guides/native/binary-diagnostics.md) | +| Bytecode EVM | Seletores de despacho, offsets de bytes, argumentos inferidos e mutabilidade | Entrada local com bytes brutos ou representação hexadecimal no Linux x64; [guia de EVM sem execução](docs/guides/evm/evm-bytecode.md) | +| Falhas do Linux registradas | Registros note brutos, registradores/sinais de cada thread registrada e candidatos opcionais a mapeamentos | pwntools fornecido pelo chamador no Linux x64; GDB/pwndbg opcionais; [falhas registradas](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Módulos, importações, source maps, rotas, IPC e relações com complementos nativos | Node.js e npm; [análise de aplicativos](https://rea.tools/pt-BR/guides/javascript/) | +| Sites | Estrutura da página, scripts, observações de rede e capturas de tela solicitadas | Um navegador da família Chrome; [análise do navegador](https://rea.tools/pt-BR/guides/browser/) | +| Capturas de rede salvas | Requisições, respostas, payloads acessíveis e localizações de origem | HAR; mitmdump no Linux para capturas no formato nativo do mitmproxy; [guia de capturas](docs/guides/web/web-network-captures.md) | +| Capturas de pacotes | Endpoints, DNS, TLS SNI, distribuição de protocolos e requisições HTTP | tshark e capinfos fornecidos pelo chamador; [guia pcap](docs/guides/data/pcap-analysis.md) | +| Assemblies .NET | Metadados, instruções CIL, dependências nativas declaradas e comparações de builds | Inspeção estática; [guia de código gerenciado](docs/guides/managed/managed-code-analysis.md) | +| APKs Android | Declarações do manifesto, classes, métodos descompilados e referências | JADX sem interface gráfica e um JDK completo no Linux/macOS/Windows x64; [guia de Android](docs/guides/android/android-analysis.md) | +| Dispositivos Android | Dispositivos, pacotes, processos, logs, despejos, capturas de tela e transferências de APK/arquivos | adb fornecido pelo chamador (emulador ou aparelho); [guia de ADB](docs/guides/android/adb-device-analysis.md) | +| Projetos JEB | Unidades de projeto do motor, hashes de artefatos e pseudocódigo de tipos/métodos | Um cliente JEB iniciado pelo chamador servindo MCP, selecionado com REA_JEB_MCP_URL; [guia de JEB](docs/providers/jeb-analysis.md) | +| Recursos do Android | Manifesto decodificado, tabelas de strings, idiomas e fatos de versão | Lançador do Apktool fornecido pelo chamador; [guia de recursos](docs/guides/android/apktool-resource-analysis.md) | +| Aplicativos Flutter | Hash de snapshot Dart, hashes de bibliotecas por ABI e procedência de build do motor | Nenhuma (análise estática de APK); [guia Flutter](docs/guides/android/flutter-analysis.md) | +| Firmware | Regiões, resultados de extração e encaminhamentos à análise nativa | Binwalk / Unblob no Linux; [guia de firmware](docs/guides/firmware/firmware-analysis.md) | +| Pacotes gravados | Campos selecionados, valores repetidos, filtros e regras de decodificação | Linux: TShark 4.x + prlimit; [guia de capturas](docs/guides/data/packet-captures.md) | +| Sinais lógicos gravados | Anotações do decodificador, intervalos de amostras e diagnósticos | Linux: sigrok-cli 0.7.2 + prlimit; [guia de sinais](docs/guides/signals/signal-recordings.md) | | Pacotes e recursos | Inventários de arquivos, digests, plists, estrutura de bundles Apple e recursos extraídos | [Guia de artefatos e JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [aplicativos Apple](docs/guides/apple/apple-application-analysis.md) | -| Comportamento de processos | Saída do terminal, interações, observações de encerramento e do sistema de arquivos, e comparações entre execuções | Linux/macOS com PTY nativo; [captura de processos](docs/guides/runtime/process-capture.md) | +| Comportamento de processos | Saída do terminal, interações, observações de encerramento e do sistema de arquivos, e comparações entre execuções | Linux/macOS com PTY nativo; [captura de processos](docs/guides/runtime/process-capture.md) | A inspeção estática de JavaScript e .NET lê os arquivos fornecidos sem executar o aplicativo. A captura em execução inicia o alvo selecionado ou interage com ele usando as permissões do seu usuário; cada guia descreve seus efeitos. @@ -261,7 +262,7 @@ Relate vulnerabilidades conforme [SECURITY.md](SECURITY.md). ## Histórico de estrelas -🎉 **110.000 estrelas no GitHub — muito obrigado!** +🎉 **170.000 estrelas no GitHub — muito obrigado!** Obrigado a todos que usam o REA, relatam bugs, sugerem funcionalidades, testam builds e contribuem com correções. diff --git a/README_ru.md b/README_ru.md index 6f1681d26..efd9d3e11 100644 --- a/README_ru.md +++ b/README_ru.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup REA требует Node.js 22.x (>=22.19), 24.x (>=24.11) или 26+, а также npm. Дополнительные инструменты и поддерживаемые системы зависят от цели: -| Цель | Что возвращает REA | Требования и руководство | -| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](https://rea.tools/ru/guides/native/) | -| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](docs/guides/native/binary-diagnostics.md) | -| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](docs/guides/evm/evm-bytecode.md) | -| Записанные сбои Linux | Необработанные записи note, регистры/сигналы каждого записанного потока и необязательные кандидаты сопоставления с памятью | pwntools, предоставленный вызывающей стороной, в Linux x64; необязательные GDB/pwndbg; [записанные сбои](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](https://rea.tools/ru/guides/javascript/) | -| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](https://rea.tools/ru/guides/browser/) | -| Сохранённые сетевые захваты | Запросы, ответы, доступные полезные данные и позиции в источнике | HAR; mitmdump в Linux для захватов в собственном формате mitmproxy; [руководство по сетевым захватам](docs/guides/web/web-network-captures.md) | -| Сборки .NET | Метаданные, инструкции CIL, объявленные нативные зависимости и сравнения сборок | Статическое исследование; [руководство по управляемому коду](docs/guides/managed/managed-code-analysis.md) | -| Android APK | Объявления манифеста, классы, декомпилированные методы и ссылки | JADX без графического интерфейса и полный JDK в Linux/macOS/Windows x64; [руководство по Android](docs/guides/android/android-analysis.md) | -| Устройства Android | Устройства, пакеты, процессы, журналы, дампы, снимки экрана и передача APK/файлов | adb, предоставленный вызывающей стороной (эмулятор или устройство); [руководство по ADB](docs/guides/android/adb-device-analysis.md) | -| Проекты JEB | Единицы проекта от движка, дайджесты артефактов и псевдокод типов/методов | Запущенный вызывающей стороной клиент JEB с интерфейсом MCP, выбирается через REA_JEB_MCP_URL; [руководство по JEB](docs/providers/jeb-analysis.md) | -| Ресурсы Android | Декодированный манифест, таблицы строк, языки и сведения о версии | Запуск Apktool, предоставленный вызывающей стороной; [руководство по ресурсам](docs/guides/android/apktool-resource-analysis.md) | -| Приложения Flutter | Хеш снапшота Dart, дайджесты библиотек по ABI и происхождение сборки движка | Не требуется (статический разбор APK); [руководство по Flutter](docs/guides/android/flutter-analysis.md) | -| Прошивки | Области, результаты извлечения и передача в нативный анализ | Binwalk / Unblob в Linux; [руководство по прошивкам](docs/guides/firmware/firmware-analysis.md) | -| Записанные пакеты | Выбранные поля, повторяющиеся значения, фильтры и правила декодирования | Linux: TShark 4.x + prlimit; [руководство по захватам](docs/guides/data/packet-captures.md) | -| Записанные логические сигналы | Аннотации декодера, диапазоны отсчётов и диагностика | Linux: sigrok-cli 0.7.2 + prlimit; [руководство по сигналам](docs/guides/signals/signal-recordings.md) | +| Цель | Что возвращает REA | Требования и руководство | +| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| Нативные бинарные файлы | Псевдокод, ассемблер, строки, символы, вызовы и ссылки | Hopper, Ghidra или IDA; [нативный анализ](https://rea.tools/ru/guides/native/) | +| Структура ELF без запуска | Секции, сегменты, исходные символы/релокации и возможные механизмы защиты по данным статического анализа | pwntools, предоставленный вызывающей стороной, в Linux x64; [диагностика бинарных файлов](docs/guides/native/binary-diagnostics.md) | +| Байт-код EVM | Селекторы диспетчеризации, смещения байтов, предполагаемые аргументы и изменяемость состояния | Локальные необработанные байты или шестнадцатеричное представление в Linux x64; [руководство по EVM без запуска](docs/guides/evm/evm-bytecode.md) | +| Записанные сбои Linux | Необработанные записи note, регистры/сигналы каждого записанного потока и необязательные кандидаты сопоставления с памятью | pwntools, предоставленный вызывающей стороной, в Linux x64; необязательные GDB/pwndbg; [записанные сбои](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Модули, импорты, карты исходного кода, маршруты, IPC и связи с нативными дополнениями | Node.js и npm; [анализ приложений](https://rea.tools/ru/guides/javascript/) | +| Сайты | Структура страницы, скрипты, наблюдения за сетью и запрошенные снимки экрана | Браузер семейства Chrome; [анализ браузера](https://rea.tools/ru/guides/browser/) | +| Сохранённые сетевые захваты | Запросы, ответы, доступные полезные данные и позиции в источнике | HAR; mitmdump в Linux для захватов в собственном формате mitmproxy; [руководство по сетевым захватам](docs/guides/web/web-network-captures.md) | +| Сборки .NET | Метаданные, инструкции CIL, объявленные нативные зависимости и сравнения сборок | Статическое исследование; [руководство по управляемому коду](docs/guides/managed/managed-code-analysis.md) | +| Android APK | Объявления манифеста, классы, декомпилированные методы и ссылки | JADX без графического интерфейса и полный JDK в Linux/macOS/Windows x64; [руководство по Android](docs/guides/android/android-analysis.md) | +| Устройства Android | Устройства, пакеты, процессы, журналы, дампы, снимки экрана и передача APK/файлов | adb, предоставленный вызывающей стороной (эмулятор или устройство); [руководство по ADB](docs/guides/android/adb-device-analysis.md) | +| Проекты JEB | Единицы проекта от движка, дайджесты артефактов и псевдокод типов/методов | Запущенный вызывающей стороной клиент JEB с интерфейсом MCP, выбирается через REA_JEB_MCP_URL; [руководство по JEB](docs/providers/jeb-analysis.md) | +| Ресурсы Android | Декодированный манифест, таблицы строк, языки и сведения о версии | Запуск Apktool, предоставленный вызывающей стороной; [руководство по ресурсам](docs/guides/android/apktool-resource-analysis.md) | +| Приложения Flutter | Хеш снапшота Dart, дайджесты библиотек по ABI и происхождение сборки движка | Не требуется (статический разбор APK); [руководство по Flutter](docs/guides/android/flutter-analysis.md) | +| Прошивки | Области, результаты извлечения и передача в нативный анализ | Binwalk / Unblob в Linux; [руководство по прошивкам](docs/guides/firmware/firmware-analysis.md) | +| Записанные пакеты | Выбранные поля, повторяющиеся значения, фильтры и правила декодирования | Linux: TShark 4.x + prlimit; [руководство по захватам](docs/guides/data/packet-captures.md) | +| Захват пакетов | Конечные точки, DNS, TLS SNI, распределение протоколов и HTTP-запросы | Предоставленные вызывающей стороной tshark и capinfos; [руководство по pcap](docs/guides/data/pcap-analysis.md) | +| Записанные логические сигналы | Аннотации декодера, диапазоны отсчётов и диагностика | Linux: sigrok-cli 0.7.2 + prlimit; [руководство по сигналам](docs/guides/signals/signal-recordings.md) | | Пакеты и ресурсы | Списки файлов, хеши, plist, структура пакетов Apple и извлечённые ресурсы | [Руководство по артефактам и JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [приложения Apple](docs/guides/apple/apple-application-analysis.md) | -| Поведение процессов | Вывод терминала, взаимодействия, наблюдения за завершением и файловой системой, сравнения запусков | Linux/macOS с нативным PTY; [захват процессов](docs/guides/runtime/process-capture.md) | +| Поведение процессов | Вывод терминала, взаимодействия, наблюдения за завершением и файловой системой, сравнения запусков | Linux/macOS с нативным PTY; [захват процессов](docs/guides/runtime/process-capture.md) | Статическое исследование JavaScript и .NET читает предоставленные файлы, не запуская приложение. Захват во время выполнения запускает выбранную цель или взаимодействует с ней с правами вашего пользователя; соответствующие руководства описывают последствия. @@ -261,7 +262,7 @@ npx rea-agents@latest setup ## История звёзд -🎉 **110 000 звёзд на GitHub — спасибо!** +🎉 **170 000 звёзд на GitHub — спасибо!** Спасибо всем, кто использует REA, сообщает об ошибках, предлагает новые функции, тестирует сборки и помогает с исправлениями. diff --git a/README_th.md b/README_th.md index 4a7322566..57d70511d 100644 --- a/README_th.md +++ b/README_th.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup REA ต้องใช้ Node.js 22.x (>=22.19), 24.x (>=24.11) หรือ 26+ และ npm เครื่องมือเพิ่มเติมและแพลตฟอร์มที่รองรับขึ้นอยู่กับเป้าหมาย: -| เป้าหมาย | สิ่งที่ REA ส่งกลับ | ข้อกำหนดและคู่มือ | -| ---------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra หรือ IDA; [การวิเคราะห์เนทีฟ](https://rea.tools/th/guides/native/) | -| โครงสร้าง ELF แบบออฟไลน์ | เซกชัน เซกเมนต์ สัญลักษณ์/รีโลเคชันต้นฉบับ และตัวเลือกกลไกป้องกันที่พบจากการวิเคราะห์แบบสถิต | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; [การวินิจฉัยไบนารี](docs/guides/native/binary-diagnostics.md) | -| ไบต์โค้ด EVM | ตัวเลือกฟังก์ชันสำหรับการเรียก ออฟเซ็ตไบต์ อาร์กิวเมนต์และความสามารถในการเปลี่ยนสถานะที่อนุมานได้ | ไฟล์บนเครื่องที่มีไบต์ดิบหรือข้อมูลเลขฐานสิบหกบน Linux x64; [คู่มือ EVM แบบออฟไลน์](docs/guides/evm/evm-bytecode.md) | -| ข้อมูลการแครชของ Linux ที่บันทึกไว้ | ระเบียน note ดิบ รีจิสเตอร์/สัญญาณของทุกเธรดที่บันทึกไว้ และตัวเลือกการแมปเพิ่มเติม | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; เลือกใช้ GDB/pwndbg เพิ่มเติมได้; [การแครชที่บันทึกไว้](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | โมดูล การนำเข้า ซอร์สแมป เส้นทาง IPC และความสัมพันธ์กับส่วนเสริมเนทีฟ | Node.js และ npm; [การวิเคราะห์แอปพลิเคชัน](https://rea.tools/th/guides/javascript/) | -| เว็บไซต์ | โครงสร้างหน้า สคริปต์ ข้อมูลเครือข่ายที่สังเกตได้ และภาพหน้าจอที่ร้องขอ | เบราว์เซอร์ในตระกูล Chrome; [การวิเคราะห์ผ่านเบราว์เซอร์](https://rea.tools/th/guides/browser/) | -| ข้อมูลเครือข่ายที่บันทึกไว้ | คำขอ คำตอบ เพย์โหลดที่ปรากฏ และตำแหน่งต้นทาง | HAR; mitmdump บน Linux สำหรับข้อมูลที่บันทึกในรูปแบบเนทีฟของ mitmproxy; [คู่มือการบันทึกข้อมูล](docs/guides/web/web-network-captures.md) | -| แอสเซมบลี .NET | เมทาดาทา คำสั่ง CIL การพึ่งพาเนทีฟที่ประกาศไว้ และการเปรียบเทียบผลการบิลด์ | การตรวจสอบแบบสถิต; [คู่มือโค้ดแบบจัดการ](docs/guides/managed/managed-code-analysis.md) | -| APK ของ Android | การประกาศใน manifest คลาส เมธอดที่ดีคอมไพล์ และการอ้างอิง | JADX แบบไม่มี GUI และ JDK แบบเต็มบน Linux/macOS/Windows x64; [คู่มือ Android](docs/guides/android/android-analysis.md) | -| อุปกรณ์ Android | อุปกรณ์ แพ็กเกจ โพรเซส บันทึก ดัมพ์ ภาพหน้าจอ และการถ่ายโอน APK/ไฟล์ | adb ที่ผู้เรียกจัดเตรียม (โปรแกรมจำลองหรืออุปกรณ์จริง); [คู่มือ ADB](docs/guides/android/adb-device-analysis.md) | -| โปรเจกต์ JEB | หน่วยโปรเจกต์จากเอนจิน, แฮชของอาร์ติแฟกต์ และซูโดโค้ดของไทป์/เมท็อด | ไคลเอนต์ JEB ที่ผู้เรียกเริ่มและให้บริการ MCP เลือกด้วย REA_JEB_MCP_URL; [คู่มือ JEB](docs/providers/jeb-analysis.md) | -| ทรัพยากร Android | ไฟล์ manifest ที่ถอดรหัสแล้ว ตารางสตริง ภาษา และข้อมูลเวอร์ชัน | ตัวเรียก Apktool ที่ผู้เรียกจัดเตรียม; [คู่มือทรัพยากร](docs/guides/android/apktool-resource-analysis.md) | -| แอป Flutter | แฮชสแนปชอต Dart, แฮชไลบรารีราย ABI และที่มาของบิลด์เอนจิน | ไม่ต้อง (วิเคราะห์ APK แบบ static); [คู่มือ Flutter](docs/guides/android/flutter-analysis.md) | -| เฟิร์มแวร์ | พื้นที่ข้อมูล ผลการแตกไฟล์ และการส่งต่อไปวิเคราะห์เนทีฟ | Binwalk / Unblob บน Linux; [คู่มือเฟิร์มแวร์](docs/guides/firmware/firmware-analysis.md) | -| แพ็กเก็ตที่บันทึกไว้ | ฟิลด์ที่เลือก ค่าซ้ำ ตัวกรอง และกฎการถอดรหัส | Linux: TShark 4.x + prlimit; [คู่มือไฟล์แคปเจอร์](docs/guides/data/packet-captures.md) | -| สัญญาณลอจิกที่บันทึกไว้ | คำอธิบายจากตัวถอดรหัส ช่วงตัวอย่าง และข้อมูลวินิจฉัย | Linux: sigrok-cli 0.7.2 + prlimit; [คู่มือสัญญาณ](docs/guides/signals/signal-recordings.md) | +| เป้าหมาย | สิ่งที่ REA ส่งกลับ | ข้อกำหนดและคู่มือ | +| ---------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| ไบนารีเนทีฟ | โค้ดเทียม แอสเซมบลี สตริง สัญลักษณ์ การเรียก และการอ้างอิง | Hopper, Ghidra หรือ IDA; [การวิเคราะห์เนทีฟ](https://rea.tools/th/guides/native/) | +| โครงสร้าง ELF แบบออฟไลน์ | เซกชัน เซกเมนต์ สัญลักษณ์/รีโลเคชันต้นฉบับ และตัวเลือกกลไกป้องกันที่พบจากการวิเคราะห์แบบสถิต | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; [การวินิจฉัยไบนารี](docs/guides/native/binary-diagnostics.md) | +| ไบต์โค้ด EVM | ตัวเลือกฟังก์ชันสำหรับการเรียก ออฟเซ็ตไบต์ อาร์กิวเมนต์และความสามารถในการเปลี่ยนสถานะที่อนุมานได้ | ไฟล์บนเครื่องที่มีไบต์ดิบหรือข้อมูลเลขฐานสิบหกบน Linux x64; [คู่มือ EVM แบบออฟไลน์](docs/guides/evm/evm-bytecode.md) | +| ข้อมูลการแครชของ Linux ที่บันทึกไว้ | ระเบียน note ดิบ รีจิสเตอร์/สัญญาณของทุกเธรดที่บันทึกไว้ และตัวเลือกการแมปเพิ่มเติม | pwntools ที่ผู้ใช้จัดเตรียมบน Linux x64; เลือกใช้ GDB/pwndbg เพิ่มเติมได้; [การแครชที่บันทึกไว้](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | โมดูล การนำเข้า ซอร์สแมป เส้นทาง IPC และความสัมพันธ์กับส่วนเสริมเนทีฟ | Node.js และ npm; [การวิเคราะห์แอปพลิเคชัน](https://rea.tools/th/guides/javascript/) | +| เว็บไซต์ | โครงสร้างหน้า สคริปต์ ข้อมูลเครือข่ายที่สังเกตได้ และภาพหน้าจอที่ร้องขอ | เบราว์เซอร์ในตระกูล Chrome; [การวิเคราะห์ผ่านเบราว์เซอร์](https://rea.tools/th/guides/browser/) | +| ข้อมูลเครือข่ายที่บันทึกไว้ | คำขอ คำตอบ เพย์โหลดที่ปรากฏ และตำแหน่งต้นทาง | HAR; mitmdump บน Linux สำหรับข้อมูลที่บันทึกในรูปแบบเนทีฟของ mitmproxy; [คู่มือการบันทึกข้อมูล](docs/guides/web/web-network-captures.md) | +| การจับแพ็กเก็ต | จุดเชื่อมต่อ, DNS, TLS SNI, การกระจายโปรโตคอล และคำขอ HTTP | tshark และ capinfos ที่ผู้เรียกจัดเตรียม; [คู่มือ pcap](docs/guides/data/pcap-analysis.md) | +| แอสเซมบลี .NET | เมทาดาทา คำสั่ง CIL การพึ่งพาเนทีฟที่ประกาศไว้ และการเปรียบเทียบผลการบิลด์ | การตรวจสอบแบบสถิต; [คู่มือโค้ดแบบจัดการ](docs/guides/managed/managed-code-analysis.md) | +| APK ของ Android | การประกาศใน manifest คลาส เมธอดที่ดีคอมไพล์ และการอ้างอิง | JADX แบบไม่มี GUI และ JDK แบบเต็มบน Linux/macOS/Windows x64; [คู่มือ Android](docs/guides/android/android-analysis.md) | +| อุปกรณ์ Android | อุปกรณ์ แพ็กเกจ โพรเซส บันทึก ดัมพ์ ภาพหน้าจอ และการถ่ายโอน APK/ไฟล์ | adb ที่ผู้เรียกจัดเตรียม (โปรแกรมจำลองหรืออุปกรณ์จริง); [คู่มือ ADB](docs/guides/android/adb-device-analysis.md) | +| โปรเจกต์ JEB | หน่วยโปรเจกต์จากเอนจิน, แฮชของอาร์ติแฟกต์ และซูโดโค้ดของไทป์/เมท็อด | ไคลเอนต์ JEB ที่ผู้เรียกเริ่มและให้บริการ MCP เลือกด้วย REA_JEB_MCP_URL; [คู่มือ JEB](docs/providers/jeb-analysis.md) | +| ทรัพยากร Android | ไฟล์ manifest ที่ถอดรหัสแล้ว ตารางสตริง ภาษา และข้อมูลเวอร์ชัน | ตัวเรียก Apktool ที่ผู้เรียกจัดเตรียม; [คู่มือทรัพยากร](docs/guides/android/apktool-resource-analysis.md) | +| แอป Flutter | แฮชสแนปชอต Dart, แฮชไลบรารีราย ABI และที่มาของบิลด์เอนจิน | ไม่ต้อง (วิเคราะห์ APK แบบ static); [คู่มือ Flutter](docs/guides/android/flutter-analysis.md) | +| เฟิร์มแวร์ | พื้นที่ข้อมูล ผลการแตกไฟล์ และการส่งต่อไปวิเคราะห์เนทีฟ | Binwalk / Unblob บน Linux; [คู่มือเฟิร์มแวร์](docs/guides/firmware/firmware-analysis.md) | +| แพ็กเก็ตที่บันทึกไว้ | ฟิลด์ที่เลือก ค่าซ้ำ ตัวกรอง และกฎการถอดรหัส | Linux: TShark 4.x + prlimit; [คู่มือไฟล์แคปเจอร์](docs/guides/data/packet-captures.md) | +| สัญญาณลอจิกที่บันทึกไว้ | คำอธิบายจากตัวถอดรหัส ช่วงตัวอย่าง และข้อมูลวินิจฉัย | Linux: sigrok-cli 0.7.2 + prlimit; [คู่มือสัญญาณ](docs/guides/signals/signal-recordings.md) | | แพ็กเกจและทรัพยากร | รายการไฟล์ ค่าแฮช plist โครงสร้างบันเดิลของ Apple และทรัพยากรที่แตกออกมา | [คู่มืออาร์ติแฟกต์และ JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [แอปพลิเคชัน Apple](docs/guides/apple/apple-application-analysis.md) | -| พฤติกรรมของโปรเซส | เอาต์พุตเทอร์มินัล การโต้ตอบ ข้อมูลการสิ้นสุดและระบบไฟล์ที่สังเกตได้ และการเปรียบเทียบการรัน | Linux/macOS ที่มี PTY เนทีฟ; [การบันทึกโปรเซส](docs/guides/runtime/process-capture.md) | +| พฤติกรรมของโปรเซส | เอาต์พุตเทอร์มินัล การโต้ตอบ ข้อมูลการสิ้นสุดและระบบไฟล์ที่สังเกตได้ และการเปรียบเทียบการรัน | Linux/macOS ที่มี PTY เนทีฟ; [การบันทึกโปรเซส](docs/guides/runtime/process-capture.md) | การตรวจสอบ JavaScript และ .NET แบบสถิตอ่านไฟล์ที่ให้มาโดยไม่รันแอปพลิเคชัน การบันทึกขณะทำงานจะรันหรือโต้ตอบกับเป้าหมายที่เลือกโดยใช้สิทธิ์ของผู้ใช้คุณ คู่มือการทำงานแต่ละฉบับอธิบายผลที่เกิดขึ้นไว้ @@ -261,7 +262,7 @@ npx rea-agents@latest setup ## ประวัติดาว -🎉 **110,000 ดาวบน GitHub — ขอบคุณทุกคน!** +🎉 **170,000 ดาวบน GitHub — ขอบคุณทุกคน!** ขอบคุณทุกคนที่ใช้ REA รายงานบั๊ก เสนอฟีเจอร์ ทดสอบบิลด์ และช่วยแก้ไข diff --git a/README_tr.md b/README_tr.md index 0c7d97d10..bf5e6f9d3 100644 --- a/README_tr.md +++ b/README_tr.md @@ -130,26 +130,27 @@ Ajanınız, hedefi incelemek ve ilgili kodu izlemek için MCP üzerinden REA'yı REA; Node.js 22.x (>=22.19), 24.x (>=24.11) veya 26+ ve npm gerektirir. Ek araçlar ve desteklenen ana bilgisayar sistemleri hedefe bağlıdır: -| Hedef | REA'nın döndürdükleri | Gereksinimler ve rehber | -| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra veya IDA; [yerel kod analizi](https://rea.tools/tr/guides/native/) | -| Çevrimdışı ELF yapısı | Bölümler, segmentler, özgün semboller/yeniden konumlandırmalar ve statik analizden olası güvenlik önlemleri | Linux x64 üzerinde çağıranın sağladığı pwntools; [ikili dosya tanılama](docs/guides/native/binary-diagnostics.md) | -| EVM bayt kodu | Yönlendirme seçicileri, bayt ofsetleri, çıkarımla belirlenen argümanlar ve durum değiştirilebilirliği | Linux x64 üzerinde yerel ham bayt/onaltılık girdi; [çevrimdışı EVM rehberi](docs/guides/evm/evm-bytecode.md) | -| Kaydedilmiş Linux çökmeleri | Ham note kayıtları, kaydedilen her iş parçacığının yazmaçları/sinyalleri ve isteğe bağlı eşleme adayları | Linux x64 üzerinde çağıranın sağladığı pwntools; isteğe bağlı GDB/pwndbg; [kaydedilmiş çökmeler](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Modüller, içe aktarmalar, kaynak haritaları, rotalar, IPC ve yerel eklenti ilişkileri | Node.js ve npm; [uygulama analizi](https://rea.tools/tr/guides/javascript/) | -| Web siteleri | Sayfa yapısı, betikler, ağ gözlemleri ve istenen ekran görüntüleri | Chrome ailesinden bir tarayıcı; [tarayıcı analizi](https://rea.tools/tr/guides/browser/) | -| Kaydedilmiş ağ yakalamaları | İstekler, yanıtlar, erişilebilir yük içerikleri ve kaynak konumları | HAR; mitmproxy'nin kendi biçimindeki yakalamalar için Linux üzerinde mitmdump; [ağ yakalama rehberi](docs/guides/web/web-network-captures.md) | -| .NET derlemeleri | Meta veriler, CIL talimatları, bildirilmiş yerel bağımlılıklar ve derleme karşılaştırmaları | Statik inceleme; [yönetilen kod rehberi](docs/guides/managed/managed-code-analysis.md) | -| Android APK'leri | Manifest bildirimleri, sınıflar, tersine derlenmiş metotlar ve referanslar | Linux/macOS/Windows x64 üzerinde arayüzsüz JADX ve tam bir JDK; [Android rehberi](docs/guides/android/android-analysis.md) | -| Android cihazları | Cihazlar, paketler, süreçler, günlükler, dökümler, ekran görüntüleri ve APK/dosya aktarımları | Çağıranın sağladığı adb (emülatör veya cihaz); [ADB rehberi](docs/guides/android/adb-device-analysis.md) | -| JEB projeleri | Motor destekli proje birimleri, artefakt özetleri ve tür/metot sözdekodu | Çağıranın başlattığı, MCP sunan bir JEB istemcisi, REA_JEB_MCP_URL ile seçilir; [JEB rehberi](docs/providers/jeb-analysis.md) | -| Android kaynakları | Çözülmüş manifest, dize tabloları, diller ve sürüm bilgileri | Çağıranın sağladığı Apktool başlatıcısı; [kaynak rehberi](docs/guides/android/apktool-resource-analysis.md) | -| Flutter uygulamaları | Dart anlık görüntü karması, ABI başına kitaplık özetleri ve motor derleme kökeni | Yok (statik APK çözümleme); [Flutter rehberi](docs/guides/android/flutter-analysis.md) | -| Donanım yazılımı | Bölgeler, çıkarma sonuçları ve yerel kod analizine devirler | Linux üzerinde Binwalk / Unblob; [donanım yazılımı rehberi](docs/guides/firmware/firmware-analysis.md) | -| Kaydedilmiş paketler | Seçilen alanlar, yinelenen değerler, filtreler ve çözümleme kuralları | Linux: TShark 4.x + prlimit; [yakalama kılavuzu](docs/guides/data/packet-captures.md) | -| Kaydedilmiş mantık sinyalleri | Kod çözücü açıklamaları, örnek aralıkları ve tanılama | Linux: sigrok-cli 0.7.2 + prlimit; [sinyal kılavuzu](docs/guides/signals/signal-recordings.md) | +| Hedef | REA'nın döndürdükleri | Gereksinimler ve rehber | +| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| Yerel makine kodu içeren ikili dosyalar | Sözde kod, assembly kodu, dizeler, semboller, çağrılar ve referanslar | Hopper, Ghidra veya IDA; [yerel kod analizi](https://rea.tools/tr/guides/native/) | +| Çevrimdışı ELF yapısı | Bölümler, segmentler, özgün semboller/yeniden konumlandırmalar ve statik analizden olası güvenlik önlemleri | Linux x64 üzerinde çağıranın sağladığı pwntools; [ikili dosya tanılama](docs/guides/native/binary-diagnostics.md) | +| EVM bayt kodu | Yönlendirme seçicileri, bayt ofsetleri, çıkarımla belirlenen argümanlar ve durum değiştirilebilirliği | Linux x64 üzerinde yerel ham bayt/onaltılık girdi; [çevrimdışı EVM rehberi](docs/guides/evm/evm-bytecode.md) | +| Kaydedilmiş Linux çökmeleri | Ham note kayıtları, kaydedilen her iş parçacığının yazmaçları/sinyalleri ve isteğe bağlı eşleme adayları | Linux x64 üzerinde çağıranın sağladığı pwntools; isteğe bağlı GDB/pwndbg; [kaydedilmiş çökmeler](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Modüller, içe aktarmalar, kaynak haritaları, rotalar, IPC ve yerel eklenti ilişkileri | Node.js ve npm; [uygulama analizi](https://rea.tools/tr/guides/javascript/) | +| Web siteleri | Sayfa yapısı, betikler, ağ gözlemleri ve istenen ekran görüntüleri | Chrome ailesinden bir tarayıcı; [tarayıcı analizi](https://rea.tools/tr/guides/browser/) | +| Kaydedilmiş ağ yakalamaları | İstekler, yanıtlar, erişilebilir yük içerikleri ve kaynak konumları | HAR; mitmproxy'nin kendi biçimindeki yakalamalar için Linux üzerinde mitmdump; [ağ yakalama rehberi](docs/guides/web/web-network-captures.md) | +| Paket yakalamaları | Uç noktalar, DNS, TLS SNI, protokol dağılımı ve HTTP istekleri | Çağıranın sağladığı tshark ve capinfos; [pcap rehberi](docs/guides/data/pcap-analysis.md) | +| .NET derlemeleri | Meta veriler, CIL talimatları, bildirilmiş yerel bağımlılıklar ve derleme karşılaştırmaları | Statik inceleme; [yönetilen kod rehberi](docs/guides/managed/managed-code-analysis.md) | +| Android APK'leri | Manifest bildirimleri, sınıflar, tersine derlenmiş metotlar ve referanslar | Linux/macOS/Windows x64 üzerinde arayüzsüz JADX ve tam bir JDK; [Android rehberi](docs/guides/android/android-analysis.md) | +| Android cihazları | Cihazlar, paketler, süreçler, günlükler, dökümler, ekran görüntüleri ve APK/dosya aktarımları | Çağıranın sağladığı adb (emülatör veya cihaz); [ADB rehberi](docs/guides/android/adb-device-analysis.md) | +| JEB projeleri | Motor destekli proje birimleri, artefakt özetleri ve tür/metot sözdekodu | Çağıranın başlattığı, MCP sunan bir JEB istemcisi, REA_JEB_MCP_URL ile seçilir; [JEB rehberi](docs/providers/jeb-analysis.md) | +| Android kaynakları | Çözülmüş manifest, dize tabloları, diller ve sürüm bilgileri | Çağıranın sağladığı Apktool başlatıcısı; [kaynak rehberi](docs/guides/android/apktool-resource-analysis.md) | +| Flutter uygulamaları | Dart anlık görüntü karması, ABI başına kitaplık özetleri ve motor derleme kökeni | Yok (statik APK çözümleme); [Flutter rehberi](docs/guides/android/flutter-analysis.md) | +| Donanım yazılımı | Bölgeler, çıkarma sonuçları ve yerel kod analizine devirler | Linux üzerinde Binwalk / Unblob; [donanım yazılımı rehberi](docs/guides/firmware/firmware-analysis.md) | +| Kaydedilmiş paketler | Seçilen alanlar, yinelenen değerler, filtreler ve çözümleme kuralları | Linux: TShark 4.x + prlimit; [yakalama kılavuzu](docs/guides/data/packet-captures.md) | +| Kaydedilmiş mantık sinyalleri | Kod çözücü açıklamaları, örnek aralıkları ve tanılama | Linux: sigrok-cli 0.7.2 + prlimit; [sinyal kılavuzu](docs/guides/signals/signal-recordings.md) | | Paketler ve kaynaklar | Dosya envanterleri, özet değerleri, plist'ler, Apple paket yapısı ve çıkarılmış kaynaklar | [Artefakt ve JavaScript rehberi](docs/guides/javascript/javascript-artifact-reconstruction.md), [Apple uygulamaları](docs/guides/apple/apple-application-analysis.md) | -| Süreç davranışı | Terminal çıktısı, etkileşimler, sonlanma ve dosya sistemi gözlemleri, çalıştırma karşılaştırmaları | Yerel PTY ile Linux/macOS; [süreç yakalama](docs/guides/runtime/process-capture.md) | +| Süreç davranışı | Terminal çıktısı, etkileşimler, sonlanma ve dosya sistemi gözlemleri, çalıştırma karşılaştırmaları | Yerel PTY ile Linux/macOS; [süreç yakalama](docs/guides/runtime/process-capture.md) | Statik JavaScript ve .NET incelemesi, uygulamayı çalıştırmadan sağlanan dosyaları okur. Çalışma zamanı yakalaması, seçilen hedefi kullanıcı izinlerinizle çalıştırır veya onunla etkileşime girer; her çalışma zamanı rehberi etkilerini açıklar. @@ -261,7 +262,7 @@ Güvenlik açıklarını [SECURITY.md](SECURITY.md) üzerinden bildirin. ## Yıldız geçmişi -🎉 **GitHub'da 110.000 yıldız — teşekkürler!** +🎉 **GitHub'da 170.000 yıldız — teşekkürler!** REA'yı kullanan, hata bildiren, özellik talep eden, derlemeleri test eden ve düzeltmelere katkıda bulunan herkese teşekkürler. diff --git a/README_uk.md b/README_uk.md index d795bd5e6..34b4379eb 100644 --- a/README_uk.md +++ b/README_uk.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup REA потребує Node.js 22.x (>=22.19), 24.x (>=24.11) або 26+, а також npm. Додаткові інструменти й підтримувані системи залежать від цілі: -| Ціль | Що повертає REA | Вимоги й посібник | -| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra або IDA; [нативний аналіз](https://rea.tools/uk/guides/native/) | -| Структура ELF без запуску | Секції, сегменти, початкові символи/релокації та можливі захисні механізми за даними статичного аналізу | pwntools, наданий стороною, що викликає інструмент, у Linux x64; [діагностика бінарних файлів](docs/guides/native/binary-diagnostics.md) | -| Байт-код EVM | Селектори диспетчеризації, зміщення байтів, виведені припущення про аргументи та змінюваність стану | Локальні необроблені байти або шістнадцяткове представлення у Linux x64; [посібник EVM без запуску](docs/guides/evm/evm-bytecode.md) | -| Записані аварійні завершення в Linux | Необроблені записи note, регістри/сигнали кожного записаного потоку й необов'язкові кандидати зіставлення пам'яті | pwntools, наданий стороною, що викликає інструмент, у Linux x64; необов'язкові GDB/pwndbg; [записані аварійні завершення](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Модулі, імпорти, карти вихідного коду, маршрути, IPC і зв'язки з нативними доповненнями | Node.js і npm; [аналіз застосунків](https://rea.tools/uk/guides/javascript/) | -| Сайти | Структура сторінки, скрипти, мережеві спостереження й запитані знімки екрана | Браузер сімейства Chrome; [аналіз браузера](https://rea.tools/uk/guides/browser/) | -| Збережені мережеві захоплення | Запити, відповіді, доступні корисні дані та місця в джерелі | HAR; mitmdump у Linux для захоплень у власному форматі mitmproxy; [посібник мережевих захоплень](docs/guides/web/web-network-captures.md) | -| Збірки .NET | Метадані, інструкції CIL, оголошені нативні залежності й порівняння збірок | Статична перевірка; [посібник керованого коду](docs/guides/managed/managed-code-analysis.md) | -| Android APK | Оголошення маніфесту, класи, декомпільовані методи й посилання | JADX без графічного інтерфейсу й повний JDK у Linux/macOS/Windows x64; [посібник Android](docs/guides/android/android-analysis.md) | -| Пристрої Android | Пристрої, пакети, процеси, журнали, дампи, знімки екрана та передавання APK/файлів | adb, наданий викликаючою стороною (емулятор або пристрій); [підручник ADB](docs/guides/android/adb-device-analysis.md) | -| Проєкти JEB | Єдиниці проєкту від рушія, дайджести артефактів і псевдокод типів/методів | Запущений викликаною стороною клієнт JEB з MCP, обирається через REA_JEB_MCP_URL; [посібник JEB](docs/providers/jeb-analysis.md) | -| Ресурси Android | Декодований маніфест, таблиці рядків, мови та відомості про версію | Засіб запуску Apktool, наданий викликаючою стороною; [підручник ресурсів](docs/guides/android/apktool-resource-analysis.md) | -| Додатки Flutter | Хеш знімка Dart, дайджести бібліотек за ABI та походження збірки рушія | Не потрібні (статичний розбір APK); [підручник Flutter](docs/guides/android/flutter-analysis.md) | -| Прошивки | Області, результати видобування й передавання до нативного аналізу | Binwalk / Unblob у Linux; [посібник прошивок](docs/guides/firmware/firmware-analysis.md) | -| Записані пакети | Вибрані поля, повторювані значення, фільтри та правила декодування | Linux: TShark 4.x + prlimit; [посібник із записів пакетів](docs/guides/data/packet-captures.md) | -| Записані логічні сигнали | Анотації декодера, діапазони відліків і діагностика | Linux: sigrok-cli 0.7.2 + prlimit; [посібник із сигналів](docs/guides/signals/signal-recordings.md) | -| Пакети й ресурси | Переліки файлів, хеші, plist, структура пакетів Apple та видобуті ресурси | [Посібник артефактів і JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [застосунки Apple](docs/guides/apple/apple-application-analysis.md) | -| Поведінка процесів | Вивід термінала, взаємодії, спостереження за завершенням і файловою системою та порівняння запусків | Linux/macOS із нативним PTY; [захоплення процесів](docs/guides/runtime/process-capture.md) | +| Ціль | Що повертає REA | Вимоги й посібник | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| Нативні бінарні файли | Псевдокод, асемблерний код, рядки, символи, виклики й посилання | Hopper, Ghidra або IDA; [нативний аналіз](https://rea.tools/uk/guides/native/) | +| Структура ELF без запуску | Секції, сегменти, початкові символи/релокації та можливі захисні механізми за даними статичного аналізу | pwntools, наданий стороною, що викликає інструмент, у Linux x64; [діагностика бінарних файлів](docs/guides/native/binary-diagnostics.md) | +| Байт-код EVM | Селектори диспетчеризації, зміщення байтів, виведені припущення про аргументи та змінюваність стану | Локальні необроблені байти або шістнадцяткове представлення у Linux x64; [посібник EVM без запуску](docs/guides/evm/evm-bytecode.md) | +| Записані аварійні завершення в Linux | Необроблені записи note, регістри/сигнали кожного записаного потоку й необов'язкові кандидати зіставлення пам'яті | pwntools, наданий стороною, що викликає інструмент, у Linux x64; необов'язкові GDB/pwndbg; [записані аварійні завершення](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Модулі, імпорти, карти вихідного коду, маршрути, IPC і зв'язки з нативними доповненнями | Node.js і npm; [аналіз застосунків](https://rea.tools/uk/guides/javascript/) | +| Сайти | Структура сторінки, скрипти, мережеві спостереження й запитані знімки екрана | Браузер сімейства Chrome; [аналіз браузера](https://rea.tools/uk/guides/browser/) | +| Збережені мережеві захоплення | Запити, відповіді, доступні корисні дані та місця в джерелі | HAR; mitmdump у Linux для захоплень у власному форматі mitmproxy; [посібник мережевих захоплень](docs/guides/web/web-network-captures.md) | +| Захоплення пакетів | Кінцеві точки, DNS, TLS SNI, розподіл протоколів та HTTP-запити | Надані викликаючою стороною tshark та capinfos; [підручник pcap](docs/guides/data/pcap-analysis.md) | +| Збірки .NET | Метадані, інструкції CIL, оголошені нативні залежності й порівняння збірок | Статична перевірка; [посібник керованого коду](docs/guides/managed/managed-code-analysis.md) | +| Android APK | Оголошення маніфесту, класи, декомпільовані методи й посилання | JADX без графічного інтерфейсу й повний JDK у Linux/macOS/Windows x64; [посібник Android](docs/guides/android/android-analysis.md) | +| Пристрої Android | Пристрої, пакети, процеси, журнали, дампи, знімки екрана та передавання APK/файлів | adb, наданий викликаючою стороною (емулятор або пристрій); [підручник ADB](docs/guides/android/adb-device-analysis.md) | +| Проєкти JEB | Єдиниці проєкту від рушія, дайджести артефактів і псевдокод типів/методів | Запущений викликаною стороною клієнт JEB з MCP, обирається через REA_JEB_MCP_URL; [посібник JEB](docs/providers/jeb-analysis.md) | +| Ресурси Android | Декодований маніфест, таблиці рядків, мови та відомості про версію | Засіб запуску Apktool, наданий викликаючою стороною; [підручник ресурсів](docs/guides/android/apktool-resource-analysis.md) | +| Додатки Flutter | Хеш знімка Dart, дайджести бібліотек за ABI та походження збірки рушія | Не потрібні (статичний розбір APK); [підручник Flutter](docs/guides/android/flutter-analysis.md) | +| Прошивки | Області, результати видобування й передавання до нативного аналізу | Binwalk / Unblob у Linux; [посібник прошивок](docs/guides/firmware/firmware-analysis.md) | +| Записані пакети | Вибрані поля, повторювані значення, фільтри та правила декодування | Linux: TShark 4.x + prlimit; [посібник із записів пакетів](docs/guides/data/packet-captures.md) | +| Записані логічні сигнали | Анотації декодера, діапазони відліків і діагностика | Linux: sigrok-cli 0.7.2 + prlimit; [посібник із сигналів](docs/guides/signals/signal-recordings.md) | +| Пакети й ресурси | Переліки файлів, хеші, plist, структура пакетів Apple та видобуті ресурси | [Посібник артефактів і JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [застосунки Apple](docs/guides/apple/apple-application-analysis.md) | +| Поведінка процесів | Вивід термінала, взаємодії, спостереження за завершенням і файловою системою та порівняння запусків | Linux/macOS із нативним PTY; [захоплення процесів](docs/guides/runtime/process-capture.md) | Статична перевірка JavaScript і .NET читає надані файли, не запускаючи застосунок. Захоплення під час виконання запускає вибрану ціль або взаємодіє з нею з правами вашого користувача; відповідні посібники описують його вплив. @@ -261,7 +262,7 @@ npx rea-agents@latest setup ## Історія зірок -🎉 **110 000 зірок на GitHub — дякуємо!** +🎉 **170 000 зірок на GitHub — дякуємо!** Дякуємо всім, хто використовує REA, повідомляє про помилки, пропонує нові функції, тестує збірки й допомагає з виправленнями. diff --git a/README_vi.md b/README_vi.md index 3620181df..bfbadf2cd 100644 --- a/README_vi.md +++ b/README_vi.md @@ -130,26 +130,27 @@ Tác nhân gọi REA qua MCP để kiểm tra mục tiêu và lần theo mã li REA yêu cầu Node.js 22.x (>=22.19), 24.x (>=24.11) hoặc 26+, cùng với npm. Công cụ bổ sung và nền tảng chạy REA được hỗ trợ tùy thuộc vào mục tiêu: -| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn | -| ----------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](https://rea.tools/vi/guides/native/) | -| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](docs/guides/native/binary-diagnostics.md) | -| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](docs/guides/evm/evm-bytecode.md) | -| Sự cố Linux đã ghi lại | Bản ghi note thô, thanh ghi/tín hiệu của mọi luồng được ghi lại và các ứng viên ánh xạ tùy chọn | pwntools do bên gọi cung cấp trên Linux x64; GDB/pwndbg tùy chọn; [sự cố đã ghi lại](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](https://rea.tools/vi/guides/javascript/) | -| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](https://rea.tools/vi/guides/browser/) | -| Bản ghi lưu lượng mạng đã lưu | Yêu cầu, phản hồi, payload có thể truy cập và vị trí nguồn | HAR; mitmdump trên Linux cho bản ghi định dạng gốc của mitmproxy; [hướng dẫn bản ghi mạng](docs/guides/web/web-network-captures.md) | -| Assembly .NET | Siêu dữ liệu, lệnh CIL, các phụ thuộc mã máy được khai báo và so sánh bản dựng | Kiểm tra tĩnh; [hướng dẫn mã được quản lý](docs/guides/managed/managed-code-analysis.md) | -| APK Android | Khai báo manifest, lớp, phương thức được dịch ngược và tham chiếu | JADX không giao diện đồ họa và JDK đầy đủ trên Linux/macOS/Windows x64; [hướng dẫn Android](docs/guides/android/android-analysis.md) | -| Thiết bị Android | Thiết bị, gói, tiến trình, nhật ký, dump, ảnh chụp màn hình và truyền APK/tệp | adb do nơi gọi cung cấp (trình giả lập hoặc thiết bị); [hướng dẫn ADB](docs/guides/android/adb-device-analysis.md) | -| Dự án JEB | Đơn vị dự án từ engine, hash của artifact và mã giả của kiểu/phương thức | Một ứng dụng JEB do nơi gọi khởi động, phục vụ MCP, chọn bằng REA_JEB_MCP_URL; [hướng dẫn JEB](docs/providers/jeb-analysis.md) | -| Tài nguyên Android | Manifest đã giải mã, bảng chuỗi, ngôn ngữ và thông tin phiên bản | Trình khởi chạy Apktool do nơi gọi cung cấp; [hướng dẫn tài nguyên](docs/guides/android/apktool-resource-analysis.md) | -| Ứng dụng Flutter | Băm snapshot Dart, hash thư viện theo ABI và nguồn gốc build engine | Không cần (phân tích APK tĩnh); [hướng dẫn Flutter](docs/guides/android/flutter-analysis.md) | -| Phần sụn | Các vùng, kết quả trích xuất và dữ liệu chuyển sang phân tích mã máy | Binwalk / Unblob trên Linux; [hướng dẫn phần sụn](docs/guides/firmware/firmware-analysis.md) | -| Gói tin đã ghi | Trường được chọn, giá trị lặp, bộ lọc và quy tắc giải mã | Linux: TShark 4.x + prlimit; [hướng dẫn bản ghi gói tin](docs/guides/data/packet-captures.md) | -| Tín hiệu logic đã ghi | Chú thích bộ giải mã, phạm vi mẫu và chẩn đoán | Linux: sigrok-cli 0.7.2 + prlimit; [hướng dẫn tín hiệu](docs/guides/signals/signal-recordings.md) | +| Mục tiêu | REA trả về gì | Yêu cầu và hướng dẫn | +| ----------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| Tệp nhị phân mã máy | Mã giả, hợp ngữ, chuỗi, ký hiệu, lời gọi và tham chiếu | Hopper, Ghidra hoặc IDA; [phân tích mã máy](https://rea.tools/vi/guides/native/) | +| Bố cục ELF ngoại tuyến | Các section, segment, ký hiệu/thông tin tái định vị gốc và các biện pháp giảm thiểu có thể có từ phân tích tĩnh | pwntools do bên gọi cung cấp trên Linux x64; [chẩn đoán tệp nhị phân](docs/guides/native/binary-diagnostics.md) | +| Bytecode EVM | Bộ chọn điều phối, độ lệch byte, tham số suy luận và khả năng thay đổi trạng thái | Đầu vào cục bộ chứa byte thô hoặc dạng thập lục phân trên Linux x64; [hướng dẫn EVM ngoại tuyến](docs/guides/evm/evm-bytecode.md) | +| Sự cố Linux đã ghi lại | Bản ghi note thô, thanh ghi/tín hiệu của mọi luồng được ghi lại và các ứng viên ánh xạ tùy chọn | pwntools do bên gọi cung cấp trên Linux x64; GDB/pwndbg tùy chọn; [sự cố đã ghi lại](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | Mô-đun, các khai báo import, source map, tuyến, IPC và quan hệ với tiện ích mở rộng mã máy | Node.js và npm; [phân tích ứng dụng](https://rea.tools/vi/guides/javascript/) | +| Trang web | Cấu trúc trang, script, quan sát mạng và ảnh chụp màn hình được yêu cầu | Trình duyệt thuộc họ Chrome; [phân tích trình duyệt](https://rea.tools/vi/guides/browser/) | +| Bản ghi lưu lượng mạng đã lưu | Yêu cầu, phản hồi, payload có thể truy cập và vị trí nguồn | HAR; mitmdump trên Linux cho bản ghi định dạng gốc của mitmproxy; [hướng dẫn bản ghi mạng](docs/guides/web/web-network-captures.md) | +| Bắt gói tin | Điểm cuối, DNS, TLS SNI, phân bố giao thức và yêu cầu HTTP | tshark và capinfos do nơi gọi cung cấp; [hướng dẫn pcap](docs/guides/data/pcap-analysis.md) | +| Assembly .NET | Siêu dữ liệu, lệnh CIL, các phụ thuộc mã máy được khai báo và so sánh bản dựng | Kiểm tra tĩnh; [hướng dẫn mã được quản lý](docs/guides/managed/managed-code-analysis.md) | +| APK Android | Khai báo manifest, lớp, phương thức được dịch ngược và tham chiếu | JADX không giao diện đồ họa và JDK đầy đủ trên Linux/macOS/Windows x64; [hướng dẫn Android](docs/guides/android/android-analysis.md) | +| Thiết bị Android | Thiết bị, gói, tiến trình, nhật ký, dump, ảnh chụp màn hình và truyền APK/tệp | adb do nơi gọi cung cấp (trình giả lập hoặc thiết bị); [hướng dẫn ADB](docs/guides/android/adb-device-analysis.md) | +| Dự án JEB | Đơn vị dự án từ engine, hash của artifact và mã giả của kiểu/phương thức | Một ứng dụng JEB do nơi gọi khởi động, phục vụ MCP, chọn bằng REA_JEB_MCP_URL; [hướng dẫn JEB](docs/providers/jeb-analysis.md) | +| Tài nguyên Android | Manifest đã giải mã, bảng chuỗi, ngôn ngữ và thông tin phiên bản | Trình khởi chạy Apktool do nơi gọi cung cấp; [hướng dẫn tài nguyên](docs/guides/android/apktool-resource-analysis.md) | +| Ứng dụng Flutter | Băm snapshot Dart, hash thư viện theo ABI và nguồn gốc build engine | Không cần (phân tích APK tĩnh); [hướng dẫn Flutter](docs/guides/android/flutter-analysis.md) | +| Phần sụn | Các vùng, kết quả trích xuất và dữ liệu chuyển sang phân tích mã máy | Binwalk / Unblob trên Linux; [hướng dẫn phần sụn](docs/guides/firmware/firmware-analysis.md) | +| Gói tin đã ghi | Trường được chọn, giá trị lặp, bộ lọc và quy tắc giải mã | Linux: TShark 4.x + prlimit; [hướng dẫn bản ghi gói tin](docs/guides/data/packet-captures.md) | +| Tín hiệu logic đã ghi | Chú thích bộ giải mã, phạm vi mẫu và chẩn đoán | Linux: sigrok-cli 0.7.2 + prlimit; [hướng dẫn tín hiệu](docs/guides/signals/signal-recordings.md) | | Gói và tài nguyên | Danh sách tệp, giá trị băm, plist, cấu trúc bundle Apple và tài nguyên được trích xuất | [Hướng dẫn hiện vật phần mềm và JavaScript](docs/guides/javascript/javascript-artifact-reconstruction.md), [ứng dụng Apple](docs/guides/apple/apple-application-analysis.md) | -| Hành vi tiến trình | Đầu ra terminal, tương tác, quan sát khi thoát và hệ thống tệp, cùng so sánh các lần chạy | Linux/macOS có PTY gốc; [ghi lại tiến trình](docs/guides/runtime/process-capture.md) | +| Hành vi tiến trình | Đầu ra terminal, tương tác, quan sát khi thoát và hệ thống tệp, cùng so sánh các lần chạy | Linux/macOS có PTY gốc; [ghi lại tiến trình](docs/guides/runtime/process-capture.md) | Kiểm tra tĩnh JavaScript và .NET đọc các tệp được cung cấp mà không chạy ứng dụng. Ghi lại khi chạy sẽ khởi chạy hoặc tương tác với mục tiêu đã chọn bằng quyền người dùng của bạn; từng hướng dẫn mô tả tác động của nó. @@ -261,7 +262,7 @@ Báo cáo lỗ hổng theo [SECURITY.md](SECURITY.md). ## Lịch sử sao -🎉 **110.000 sao trên GitHub — xin cảm ơn!** +🎉 **170.000 sao trên GitHub — xin cảm ơn!** Cảm ơn mọi người đã sử dụng REA, báo lỗi, đề xuất tính năng, kiểm thử bản dựng và đóng góp bản sửa lỗi. diff --git a/README_zh-TW.md b/README_zh-TW.md index 277762817..72f4ef404 100644 --- a/README_zh-TW.md +++ b/README_zh-TW.md @@ -130,26 +130,27 @@ AI 代理通過 MCP 呼叫 REA,檢查目標並追蹤相關程式碼。REA 返 REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。額外工具和主機支援取決於分析目標: -| 目標 | REA 返回的內容 | 要求與指南 | -| --------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/zh-TW/guides/native/) | -| 離線 ELF 佈局 | 節、段、原始符號/重定位資訊及靜態防護機制候選項 | Linux x64 上由呼叫方提供的 pwntools;[二進位診斷](docs/guides/native/binary-diagnostics.md) | -| EVM 位元組碼 | 分派選擇器、位元組偏移、推斷的參數和狀態可變性 | Linux x64 上的本地原始位元組/十六進位輸入載體;[離線 EVM 指南](docs/guides/evm/evm-bytecode.md) | -| 已記錄的 Linux 崩潰 | 原始 note 記錄、每個已記錄執行緒的暫存器/訊號及可選的對映候選項 | Linux x64 上由呼叫方提供的 pwntools;可選的 GDB/pwndbg;[已記錄崩潰](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | 模組、匯入、source map、路由、IPC 和原生附加元件關係 | Node.js 和 npm;[應用分析](https://rea.tools/zh-TW/guides/javascript/) | -| 網站 | 頁面結構、腳本、網路觀察結果和按請求獲取的螢幕擷取畫面 | Chrome 系瀏覽器;[瀏覽器分析](https://rea.tools/zh-TW/guides/browser/) | -| 已保存的網路擷取 | 請求、回應、可訪問的酬載和來源位置 | HAR;原生 mitmproxy 擷取需要 Linux 上的 mitmdump;[擷取指南](docs/guides/web/web-network-captures.md) | -| .NET 程式集 | 中繼資料、CIL 指令、聲明的原生依賴和建置對比 | 靜態檢查;[托管程式碼指南](docs/guides/managed/managed-code-analysis.md) | -| Android APK | 清單聲明、類別、反編譯的方法和引用 | Linux/macOS/Windows x64 上的無界面 JADX 和完整 JDK;[Android 指南](docs/guides/android/android-analysis.md) | -| Android 裝置 | 裝置、套件、程序、日誌、傾印、螢幕擷取以及 APK/檔案傳輸 | 呼叫端提供的 adb(模擬器或實體裝置);[ADB 指南](docs/guides/android/adb-device-analysis.md) | -| JEB 專案 | 引擎支援的專案單元、成品摘要和型別/方法的虛擬碼 | 由呼叫端啟動、提供 MCP 的 JEB 用戶端,透過 REA_JEB_MCP_URL 選擇;[JEB 指南](docs/providers/jeb-analysis.md) | -| Android 資源 | 解碼後的清單、字串表、語系和版本資訊 | 呼叫端提供的 Apktool 啟動器;[資源指南](docs/guides/android/apktool-resource-analysis.md) | -| Flutter 應用 | Dart 快照雜湊、依 ABI 的程式庫雜湊及引擎建置來源 | 無(靜態 APK 解析);[Flutter 指南](docs/guides/android/flutter-analysis.md) | -| 韌體 | 區域、提取結果和轉交原生分析的內容 | Linux 上的 Binwalk / Unblob;[韌體指南](docs/guides/firmware/firmware-analysis.md) | -| 封包記錄 | 指定欄位、重複值、篩選條件與解碼規則 | Linux: TShark 4.x + prlimit; [封包分析指南](docs/guides/data/packet-captures.md) | -| 錄製的邏輯訊號 | 解碼註解、樣本範圍與診斷資訊 | Linux: sigrok-cli 0.7.2 + prlimit; [訊號記錄指南](docs/guides/signals/signal-recordings.md) | +| 目標 | REA 返回的內容 | 要求與指南 | +| --------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| 原生二進位檔案 | 偽程式碼、組合語言、字串、符號、呼叫和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/zh-TW/guides/native/) | +| 離線 ELF 佈局 | 節、段、原始符號/重定位資訊及靜態防護機制候選項 | Linux x64 上由呼叫方提供的 pwntools;[二進位診斷](docs/guides/native/binary-diagnostics.md) | +| EVM 位元組碼 | 分派選擇器、位元組偏移、推斷的參數和狀態可變性 | Linux x64 上的本地原始位元組/十六進位輸入載體;[離線 EVM 指南](docs/guides/evm/evm-bytecode.md) | +| 已記錄的 Linux 崩潰 | 原始 note 記錄、每個已記錄執行緒的暫存器/訊號及可選的對映候選項 | Linux x64 上由呼叫方提供的 pwntools;可選的 GDB/pwndbg;[已記錄崩潰](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | 模組、匯入、source map、路由、IPC 和原生附加元件關係 | Node.js 和 npm;[應用分析](https://rea.tools/zh-TW/guides/javascript/) | +| 網站 | 頁面結構、腳本、網路觀察結果和按請求獲取的螢幕擷取畫面 | Chrome 系瀏覽器;[瀏覽器分析](https://rea.tools/zh-TW/guides/browser/) | +| 已保存的網路擷取 | 請求、回應、可訪問的酬載和來源位置 | HAR;原生 mitmproxy 擷取需要 Linux 上的 mitmdump;[擷取指南](docs/guides/web/web-network-captures.md) | +| 封包擷取 | 端點、DNS、TLS SNI、通訊協定分佈和 HTTP 請求 | 呼叫端提供的 tshark 和 capinfos;[pcap 指南](docs/guides/data/pcap-analysis.md) | +| .NET 程式集 | 中繼資料、CIL 指令、聲明的原生依賴和建置對比 | 靜態檢查;[托管程式碼指南](docs/guides/managed/managed-code-analysis.md) | +| Android APK | 清單聲明、類別、反編譯的方法和引用 | Linux/macOS/Windows x64 上的無界面 JADX 和完整 JDK;[Android 指南](docs/guides/android/android-analysis.md) | +| Android 裝置 | 裝置、套件、程序、日誌、傾印、螢幕擷取以及 APK/檔案傳輸 | 呼叫端提供的 adb(模擬器或實體裝置);[ADB 指南](docs/guides/android/adb-device-analysis.md) | +| JEB 專案 | 引擎支援的專案單元、成品摘要和型別/方法的虛擬碼 | 由呼叫端啟動、提供 MCP 的 JEB 用戶端,透過 REA_JEB_MCP_URL 選擇;[JEB 指南](docs/providers/jeb-analysis.md) | +| Android 資源 | 解碼後的清單、字串表、語系和版本資訊 | 呼叫端提供的 Apktool 啟動器;[資源指南](docs/guides/android/apktool-resource-analysis.md) | +| Flutter 應用 | Dart 快照雜湊、依 ABI 的程式庫雜湊及引擎建置來源 | 無(靜態 APK 解析);[Flutter 指南](docs/guides/android/flutter-analysis.md) | +| 韌體 | 區域、提取結果和轉交原生分析的內容 | Linux 上的 Binwalk / Unblob;[韌體指南](docs/guides/firmware/firmware-analysis.md) | +| 封包記錄 | 指定欄位、重複值、篩選條件與解碼規則 | Linux: TShark 4.x + prlimit; [封包分析指南](docs/guides/data/packet-captures.md) | +| 錄製的邏輯訊號 | 解碼註解、樣本範圍與診斷資訊 | Linux: sigrok-cli 0.7.2 + prlimit; [訊號記錄指南](docs/guides/signals/signal-recordings.md) | | 軟體包與資源 | 檔案清單、摘要、plist、Apple bundle 結構和提取的資源 | [製品與 JavaScript 指南](docs/guides/javascript/javascript-artifact-reconstruction.md)、[Apple 應用](docs/guides/apple/apple-application-analysis.md) | -| 處理程序行為 | 終端輸出、互動、退出和檔案系統觀察結果,以及執行對比 | 支援原生 PTY 的 Linux/macOS;[處理程序擷取](docs/guides/runtime/process-capture.md) | +| 處理程序行為 | 終端輸出、互動、退出和檔案系統觀察結果,以及執行對比 | 支援原生 PTY 的 Linux/macOS;[處理程序擷取](docs/guides/runtime/process-capture.md) | 靜態 JavaScript 和 .NET 檢查讀取提供的檔案,不執行應用。執行階段擷取會以你的使用者權限執行目標或與之互動;各執行階段指南說明瞭具體影響。 @@ -263,7 +264,7 @@ npx rea-agents@latest setup ## Star 歷史 -🎉 **GitHub Star 達到 110,000 個,感謝大家!** +🎉 **GitHub Star 達到 170,000 個,感謝大家!** 感謝每一位使用 REA、報告錯誤、提出功能需求、測試建置和貢獻修復的朋友。 diff --git a/README_zh.md b/README_zh.md index b2d523b7a..a69db19db 100644 --- a/README_zh.md +++ b/README_zh.md @@ -130,26 +130,27 @@ npx rea-agents@latest setup REA 需要 Node.js 22.x(>=22.19)、24.x(>=24.11)或 26+,以及 npm。额外工具和主机支持取决于分析目标: -| 目标 | REA 返回的内容 | 要求与指南 | -| --------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/zh-CN/guides/native/) | -| 离线 ELF 布局 | 节、段、原始符号/重定位信息及静态防护机制候选项 | Linux x64 上由调用方提供的 pwntools;[二进制诊断](docs/guides/native/binary-diagnostics.md) | -| EVM 字节码 | 分派选择器、字节偏移、推断的参数和状态可变性 | Linux x64 上的本地原始字节/十六进制输入载体;[离线 EVM 指南](docs/guides/evm/evm-bytecode.md) | -| 已记录的 Linux 崩溃 | 原始 note 记录、每个已记录线程的寄存器/信号及可选的映射候选项 | Linux x64 上由调用方提供的 pwntools;可选的 GDB/pwndbg;[已记录崩溃](docs/guides/native/recorded-crashes.md) | -| JavaScript / Electron | 模块、导入、source map、路由、IPC 和原生扩展关系 | Node.js 和 npm;[应用分析](https://rea.tools/zh-CN/guides/javascript/) | -| 网站 | 页面结构、脚本、网络观察结果和按请求获取的截图 | Chrome 系浏览器;[浏览器分析](https://rea.tools/zh-CN/guides/browser/) | -| 已保存的网络捕获 | 请求、响应、可访问的载荷和来源位置 | HAR;原生 mitmproxy 捕获需要 Linux 上的 mitmdump;[捕获指南](docs/guides/web/web-network-captures.md) | -| .NET 程序集 | 元数据、CIL 指令、声明的原生依赖和构建对比 | 静态检查;[托管代码指南](docs/guides/managed/managed-code-analysis.md) | -| Android APK | 清单声明、类、反编译的方法和引用 | Linux/macOS/Windows x64 上的无界面 JADX 和完整 JDK;[Android 指南](docs/guides/android/android-analysis.md) | -| Android 设备 | 设备、软件包、进程、日志、转储、屏幕截图以及 APK/文件传输 | 调用方提供的 adb(模拟器或实体设备);[ADB 指南](docs/guides/android/adb-device-analysis.md) | -| JEB 项目 | 引擎支持的项目单元、工件摘要和类型/方法的伪代码 | 由调用方启动、提供 MCP 的 JEB 客户端,通过 REA_JEB_MCP_URL 选择;[JEB 指南](docs/providers/jeb-analysis.md) | -| Android 资源 | 解码后的清单、字符串表、语言区域和版本信息 | 调用方提供的 Apktool 启动器;[资源指南](docs/guides/android/apktool-resource-analysis.md) | -| Flutter 应用 | Dart 快照哈希、按 ABI 的库摘要及引擎构建溯源 | 无(静态 APK 解析);[Flutter 指南](docs/guides/android/flutter-analysis.md) | -| 固件 | 区域、提取结果和转交原生分析的内容 | Linux 上的 Binwalk / Unblob;[固件指南](docs/guides/firmware/firmware-analysis.md) | -| 抓包文件 | 指定字段、重复值、过滤条件与解码规则 | Linux: TShark 4.x + prlimit; [抓包分析指南](docs/guides/data/packet-captures.md) | -| 录制的逻辑信号 | 解码注释、样本范围和诊断信息 | Linux: sigrok-cli 0.7.2 + prlimit; [信号记录指南](docs/guides/signals/signal-recordings.md) | +| 目标 | REA 返回的内容 | 要求与指南 | +| --------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| 原生二进制文件 | 伪代码、汇编、字符串、符号、调用和引用 | Hopper、Ghidra 或 IDA;[原生分析](https://rea.tools/zh-CN/guides/native/) | +| 离线 ELF 布局 | 节、段、原始符号/重定位信息及静态防护机制候选项 | Linux x64 上由调用方提供的 pwntools;[二进制诊断](docs/guides/native/binary-diagnostics.md) | +| EVM 字节码 | 分派选择器、字节偏移、推断的参数和状态可变性 | Linux x64 上的本地原始字节/十六进制输入载体;[离线 EVM 指南](docs/guides/evm/evm-bytecode.md) | +| 已记录的 Linux 崩溃 | 原始 note 记录、每个已记录线程的寄存器/信号及可选的映射候选项 | Linux x64 上由调用方提供的 pwntools;可选的 GDB/pwndbg;[已记录崩溃](docs/guides/native/recorded-crashes.md) | +| JavaScript / Electron | 模块、导入、source map、路由、IPC 和原生扩展关系 | Node.js 和 npm;[应用分析](https://rea.tools/zh-CN/guides/javascript/) | +| 网站 | 页面结构、脚本、网络观察结果和按请求获取的截图 | Chrome 系浏览器;[浏览器分析](https://rea.tools/zh-CN/guides/browser/) | +| 已保存的网络捕获 | 请求、响应、可访问的载荷和来源位置 | HAR;原生 mitmproxy 捕获需要 Linux 上的 mitmdump;[捕获指南](docs/guides/web/web-network-captures.md) | +| 数据包捕获 | 端点、DNS、TLS SNI、协议分布和 HTTP 请求 | 调用方提供的 tshark 和 capinfos;[pcap 指南](docs/guides/data/pcap-analysis.md) | +| .NET 程序集 | 元数据、CIL 指令、声明的原生依赖和构建对比 | 静态检查;[托管代码指南](docs/guides/managed/managed-code-analysis.md) | +| Android APK | 清单声明、类、反编译的方法和引用 | Linux/macOS/Windows x64 上的无界面 JADX 和完整 JDK;[Android 指南](docs/guides/android/android-analysis.md) | +| Android 设备 | 设备、软件包、进程、日志、转储、屏幕截图以及 APK/文件传输 | 调用方提供的 adb(模拟器或实体设备);[ADB 指南](docs/guides/android/adb-device-analysis.md) | +| JEB 项目 | 引擎支持的项目单元、工件摘要和类型/方法的伪代码 | 由调用方启动、提供 MCP 的 JEB 客户端,通过 REA_JEB_MCP_URL 选择;[JEB 指南](docs/providers/jeb-analysis.md) | +| Android 资源 | 解码后的清单、字符串表、语言区域和版本信息 | 调用方提供的 Apktool 启动器;[资源指南](docs/guides/android/apktool-resource-analysis.md) | +| Flutter 应用 | Dart 快照哈希、按 ABI 的库摘要及引擎构建溯源 | 无(静态 APK 解析);[Flutter 指南](docs/guides/android/flutter-analysis.md) | +| 固件 | 区域、提取结果和转交原生分析的内容 | Linux 上的 Binwalk / Unblob;[固件指南](docs/guides/firmware/firmware-analysis.md) | +| 抓包文件 | 指定字段、重复值、过滤条件与解码规则 | Linux: TShark 4.x + prlimit; [抓包分析指南](docs/guides/data/packet-captures.md) | +| 录制的逻辑信号 | 解码注释、样本范围和诊断信息 | Linux: sigrok-cli 0.7.2 + prlimit; [信号记录指南](docs/guides/signals/signal-recordings.md) | | 软件包与资源 | 文件清单、摘要、plist、Apple bundle 结构和提取的资源 | [制品与 JavaScript 指南](docs/guides/javascript/javascript-artifact-reconstruction.md)、[Apple 应用](docs/guides/apple/apple-application-analysis.md) | -| 进程行为 | 终端输出、交互、退出和文件系统观察结果,以及运行对比 | 支持原生 PTY 的 Linux/macOS;[进程捕获](docs/guides/runtime/process-capture.md) | +| 进程行为 | 终端输出、交互、退出和文件系统观察结果,以及运行对比 | 支持原生 PTY 的 Linux/macOS;[进程捕获](docs/guides/runtime/process-capture.md) | 静态 JavaScript 和 .NET 检查读取提供的文件,不运行应用。运行时捕获会以你的用户权限运行目标或与之交互;各运行时指南说明了具体影响。 @@ -263,7 +264,7 @@ npx rea-agents@latest setup ## Star 历史 -🎉 **GitHub Star 达到 110,000 个,感谢大家!** +🎉 **GitHub Star 达到 170,000 个,感谢大家!** 感谢每一位使用 REA、报告错误、提出功能需求、测试构建和贡献修复的朋友。 diff --git a/SECURITY.md b/SECURITY.md index 56d9ca784..86d88e128 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -24,9 +24,12 @@ provider-dependent behavior to be reproduced safely. ## Security boundary -REA authenticates each local provider bridge session with a random capability -token and a current-user Unix socket. Tokens are transferred through private -session descriptors rather than process arguments or environment variables. +REA authenticates its Hopper and Ghidra bridges with per-session random +capability tokens. POSIX uses current-user Unix sockets; Windows Ghidra uses +authenticated loopback TCP with a private NTFS runtime whose DACL admits only +the current user and SYSTEM. See [Windows Ghidra P0](docs/providers/windows-ghidra-p0.md#private-runtime-transport-and-lifecycle). +Tokens are transferred through private session descriptors rather than process +arguments or environment variables. This is not a sandbox and does not protect against malicious processes already running as the same operating-system user. Opening an untrusted binary delegates parsing and analysis to the selected local provider with that user's diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 3faad0dba..5fceaaa47 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -28,6 +28,13 @@ entries preserve the declared license and author metadata and include a clearly labeled standard license text. These are documented upstream notice gaps, not recovered copyright notices or a claim that attribution has been fully verified. +The optional `frida@17.23.2` npm archive and tagged Node binding source also +omit a standalone license/copyright document. Its declared +`LGPL-2.0 WITH WxWindows-exception-3.1` license is recorded with unchanged +[Frida licensing text](licenses/frida-17.23.2-COPYING.txt) and the +[GNU Library GPL v2](licenses/LGPL-2.0.txt). These are licensing supplements, +not recovered Node binding or prebuild-component copyright notices. + ## Open-source engine credits and licenses We thank the maintainers and contributors of the projects below. Their diff --git a/bridge/ghidra/ReaGhidraBridge.java b/bridge/ghidra/ReaGhidraBridge.java index e45f97172..02fc0f148 100644 --- a/bridge/ghidra/ReaGhidraBridge.java +++ b/bridge/ghidra/ReaGhidraBridge.java @@ -106,6 +106,8 @@ public final class ReaGhidraBridge extends HeadlessScript { private static final int MAX_HIGH_PCODE_INPUTS_PER_OP = 64; private static final int MAX_HIGH_PCODE_DEF_USE_EDGES = 12000; private static final Gson GSON = new GsonBuilder().serializeNulls().create(); + private final Map targetSourceIdentity = new IdentityHashMap<>(); + private String admittedTargetSha256; private static final Set DESCRIPTOR_KEYS = Set.of( "transport", "endpoint_path", @@ -207,6 +209,7 @@ public final class ReaGhidraBridge extends HeadlessScript { "Ghidra imported-byte digest does not match the admitted target" ); } + admittedTargetSha256 = descriptor.targetSha256; // GhidraScript wraps run() in a transaction. End it before serving so // each edit owns a real outer transaction and can roll back immediately. end(true); @@ -633,7 +636,7 @@ public final class ReaGhidraBridge extends HeadlessScript { return result; } - private JsonObject addressToFileOffset(JsonObject params) { + private JsonObject addressToFileOffset(JsonObject params) throws Exception { requireKeys(params, Set.of("document", "address")); requireDocument(params); Address address = requireAddress(params, "address"); @@ -643,14 +646,15 @@ public final class ReaGhidraBridge extends HeadlessScript { Long fileOffset = null; int mappings = 0; for (MemoryBlockSourceInfo source : block.getSourceInfos()) { - if (!source.contains(address) || source.getFileBytes().isEmpty()) continue; + if (!source.contains(address) || source.getFileBytes().isEmpty() || + !isTargetSource(source.getFileBytes().get())) continue; long offset = source.getFileBytesOffset(address); if (offset < 0) continue; fileOffset = offset; mappings++; } if (mappings != 1) - throw new RequestFailure("invalid_request", "Address has " + mappings + " authoritative source mappings: " + canonicalAddress(address)); + throw new RequestFailure("invalid_request", "Address has " + mappings + " authoritative target-file mappings: " + canonicalAddress(address)); JsonObject result = new JsonObject(); result.addProperty("address", canonicalAddress(address)); result.addProperty("file_offset", fileOffset); @@ -673,14 +677,96 @@ public final class ReaGhidraBridge extends HeadlessScript { private JsonElement procedurePseudocode(JsonObject params) throws Exception { requireKeys(params, Set.of("document", "procedure")); requireDocument(params); - Function function = resolveProcedure(requireString(params, "procedure")); - String value = decompiledText(decompile(function)); - return functionObservation( - value == null ? JsonNull.INSTANCE : GSON.toJsonTree(value), - noReturnCallLimitations( - currentProgram.getListing().getInstructions(function.getBody(), true) - ) - ); + String selector = requireString(params, "procedure"); + JsonObject selection = new JsonObject(); + Function function = resolveDecompileProcedure(selector, selection); + try { + String value = decompiledText(decompile(function)); + JsonObject result = functionObservation( + value == null ? JsonNull.INSTANCE : GSON.toJsonTree(value), + noReturnCallLimitations( + currentProgram.getListing().getInstructions(function.getBody(), true) + ) + ); + if (selection.size() > 0) result.add("selection", selection); + return result; + } catch (RequestFailure failure) { + if (selection.size() == 0) throw failure; + // Preserve completed resolution facts without changing the backend's + // failure code or suggesting that the successful mapping was invalid. + throw new RequestFailure(failure.code, "Selector " + selector + + " mapped to analysis address " + selection.get("mapped_address").getAsString() + + " and procedure " + canonicalAddress(function.getEntryPoint()) + + "; " + failure.getMessage()); + } + } + + private Function resolveDecompileProcedure(String selector, JsonObject selection) throws Exception { + String prefix = "file-offset:"; + boolean explicitOffset = selector.startsWith(prefix); + if (!explicitOffset) { + try { + return resolveProcedure(selector); + } catch (RequestFailure failure) { + // Existing names/addresses win. Only an unresolved numeric input + // can fall back to source coordinates; ambiguity never falls back. + if (!failure.code.equals("not_found") || !selector.matches("0x[0-9a-fA-F]+")) + throw failure; + } + } + String coordinate = explicitOffset ? selector.substring(prefix.length()) : selector; + if (!coordinate.matches("0x[0-9a-fA-F]+")) + throw new RequestFailure("invalid_request", "File offsets require hexadecimal file-offset:0x... syntax"); + BigInteger parsed = new BigInteger(coordinate.substring(2), 16); + if (parsed.compareTo(BigInteger.valueOf(9007199254740991L)) > 0) + throw new RequestFailure("invalid_request", "File offset exceeds the exact JSON integer range"); + long offset = parsed.longValueExact(); + monitor.checkCancelled(); + // Ghidra's convenience lookup spans every FileBytes and uses coordinates + // local to each object. Only a complete, digest-matched target source + // establishes that the caller's offset belongs to the admitted file. + Set
mappedAddresses = new java.util.LinkedHashSet<>(); + for (MemoryBlock block : currentProgram.getMemory().getBlocks()) { + for (MemoryBlockSourceInfo source : block.getSourceInfos()) { + monitor.checkCancelled(); + FileBytes backing = source.getFileBytes().orElse(null); + if (backing == null || !isTargetSource(backing)) continue; + Address mapped = source.locateAddressForFileOffset(offset); + if (mapped != null) mappedAddresses.add(mapped); + } + } + List
candidates = new ArrayList<>(mappedAddresses); + if (candidates.size() > 1) + throw new RequestFailure("ambiguous", "File offset " + coordinate + + " has multiple loaded mappings: " + candidates.stream().map(ReaGhidraBridge::canonicalAddress).toList() + + "; select an explicit analysis address"); + if (candidates.isEmpty()) + throw new RequestFailure("not_found", "File offset " + coordinate + + " has no loaded source mapping for the admitted target file; Ghidra image base: " + canonicalAddress(currentProgram.getImageBase()) + + ". Inspect mappings with rea inspect-native-load-image --provider ghidra --json or MCP inspect_native_load_image."); + Address mapped = candidates.get(0); + Function function = functionAtOrContaining(mapped); + if (function == null) + throw new RequestFailure("not_found", "File offset " + coordinate + + " maps to analysis address " + canonicalAddress(mapped) + + ", but no procedure starts at or contains that address in the current Ghidra analysis. " + + "Choose an observed procedure with CLI rea search . --kind procedures --mode regex --provider ghidra --json or MCP list_procedures."); + selection.addProperty("file_offset", offset); + selection.addProperty("mapped_address", canonicalAddress(mapped)); + selection.addProperty("procedure_address", canonicalAddress(function.getEntryPoint())); + return function; + } + + private boolean isTargetSource(FileBytes source) throws Exception { + Boolean observed = targetSourceIdentity.get(source); + if (observed != null) return observed; + // Original FileBytes are immutable even when analysis memory is edited. + // Partial/auxiliary sources remain inspectable but cannot establish an + // original-target offset from their object-local coordinates alone. + boolean matched = source.getFileOffset() == 0 && + constantTimeEquals(hashFileBytes(source, false), admittedTargetSha256); + targetSourceIdentity.put(source, matched); + return matched; } private JsonElement procedureAssembly(JsonObject params) throws Exception { @@ -1833,14 +1919,25 @@ public final class ReaGhidraBridge extends HeadlessScript { Address address = explicitAddress ? parseReaAddress(value) : tryParseAddress(value); if (address == null) throw new RequestFailure("not_found", "Unknown Ghidra procedure name or address: " + value); - Function function = currentProgram.getFunctionManager().getFunctionAt(address); - if (function == null && address.isMemoryAddress()) - function = currentProgram.getFunctionManager().getFunctionContaining(address); + Function function = functionAtOrContaining(address); if (function == null) - throw new RequestFailure("not_found", "No procedure exists at the requested address: " + value); + // Other procedure operations retain their analysis-address semantics. + throw new RequestFailure("not_found", "No procedure exists at the requested address: " + value + + "; Ghidra image base: " + canonicalAddress(currentProgram.getImageBase()) + + ". Choose an observed analysis address. CLI: rea search . --kind procedures --mode regex --provider ghidra --json; " + + "MCP: list_procedures. Inspect the loaded base and source mappings with CLI rea analyze --provider ghidra --json " + + "and rea inspect-native-load-image --provider ghidra --json, or MCP binary_overview and inspect_native_load_image. " + + "Repeat the original target options. For decompile, select source coordinates explicitly with --file-offset=0x... or MCP procedure file-offset:0x...."); return function; } + private Function functionAtOrContaining(Address address) { + Function function = currentProgram.getFunctionManager().getFunctionAt(address); + return function == null && address.isMemoryAddress() + ? currentProgram.getFunctionManager().getFunctionContaining(address) + : function; + } + private JsonObject nativeApiBoundary( Function function, DecompileResults decompilation diff --git a/bridge/mitmproxy/capture.py b/bridge/mitmproxy/capture.py index fa0535c02..dcd90e745 100644 --- a/bridge/mitmproxy/capture.py +++ b/bridge/mitmproxy/capture.py @@ -93,7 +93,7 @@ def project_record(state, secrets): safe_bytes, credential_url = transport_value(value, path, transport_url) content_base64 = base64.b64encode(value).decode("ascii") digest = hashlib.sha256(value).hexdigest() - hidden = any(secret in value or secret in safe_bytes for secret in byte_secrets) or any(secret in content_base64 or secret in digest for secret in secrets) + hidden = any(secret in value or secret in safe_bytes for secret in byte_secrets) or any(secret in content_base64 or secret in digest or secret in str(len(value)) for secret in secrets) safe_text = None try: safe_text = safe_bytes.decode("utf-8", errors="strict") diff --git a/docs/.vitepress/documentation.ts b/docs/.vitepress/documentation.ts index 4acb71728..fc339b3cd 100644 --- a/docs/.vitepress/documentation.ts +++ b/docs/.vitepress/documentation.ts @@ -228,6 +228,11 @@ export const documentationSections = [ source: "guides/data/packet-captures.md", route: "/packet-captures", }, + { + text: "Packet capture summaries", + source: "guides/data/pcap-analysis.md", + route: "/pcap-analysis", + }, ], }, { diff --git a/docs/README.md b/docs/README.md index 88926fd83..65a8d3613 100644 --- a/docs/README.md +++ b/docs/README.md @@ -73,6 +73,7 @@ product pages. The VitePress documentation source is this `docs/` tree. - [SQLite database snapshots](guides/data/sqlite-databases.md) - [Recorded packet capture inspection](guides/data/packet-captures.md) +- [Packet capture summaries](guides/data/pcap-analysis.md) ## Process capture and instrumentation diff --git a/docs/development/client-verification.md b/docs/development/client-verification.md index 07ee7e45b..c786b2800 100644 --- a/docs/development/client-verification.md +++ b/docs/development/client-verification.md @@ -298,13 +298,42 @@ subsequent wire recovery and clean shutdown. Caller timeout does not interrupt Hopper's synchronous native operation. Socket boundary tests deterministically cover active and queued expiry, late replies and timer cleanup. -The Linux demo lane remains a separate `verify:hopper:linux` command. Its -lifecycle checks attempt competing CLI launches for the active target and a +The Linux demo lane remains a separate `verify:hopper:linux` command. Hopper +6.4.2's ELF loader did not recognize the original 4,119-byte literal or three +non-ASCII byte strings in the measured fixtures. The lane retains complete raw +byte checks for those literals through source-owned symbols. Recognition of the +original full-length literal is bound to its exact source address; its decoded +object coverage remains explicitly unverified on Linux even when recognized. +Absent non-ASCII recognition also reports decoded-object coverage as unverified. +Recognized non-ASCII and control-text objects must still match their source +bytes, encoding, filters and searches. +A separate 548-byte ASCII literal requires native fragmentation, shortened +provider display, complete decoded fragments and dossier provenance on Linux; +the macOS lane retains the original full-length recognition requirement. These +are observed fixture/build capabilities, not universal Hopper length limits. +Its lifecycle checks attempt competing CLI launches for the active target and a different target, requiring rejection before either can change the owning MCP session's documents or procedures. Lease boundary tests also preserve unresponsive or malformed live endpoints while allowing confirmed stale sockets to recover. +`verify:setup:linux` exercises installation on a clean supported Linux runner as +root. Use a disposable VM: this lane installs Hopper and its Linux runtime +dependencies through the system package manager. Set `REA_VERIFY_SERVER_COMMAND` +to the CLI entrypoint being verified. The command builds and checks source-owned +ELF fixtures before testing the read-only Hopper setup plan, approved +installation, scoped doctor, real CLI/MCP analysis, rejection of a modified +launcher, idempotent setup without requesting a reinstall, and owned child +cleanup. Before installation and after teardown, a clean-runner process scan +also rejects surviving Hopper demo helpers or Xvfb groups, including orphans +whose launcher exited. This scan observes processes without signaling them. +Hopper detection compares executable file identity through `/proc`, covering +alternate or configured launcher paths even after an invoked symlink is removed. +The dedicated runner must have no unrelated Hopper/Xvfb sessions. It requires +the repository's pinned development toolchain and an +existing host C compiler, `file`, `nm`, and `strings`. Use `verify:hopper:linux` +instead when Hopper is already installed. + `verify:hopper:fat` is a separate macOS lane requiring installed Hopper and the existing Xcode clang/lipo toolchain. It compiles arm64/x86-64 thin executables and one- and two-slice FAT32 containers, verifies exact/interior address mappings diff --git a/docs/development/releasing.md b/docs/development/releasing.md index 5190ca8d3..80fd1252d 100644 --- a/docs/development/releasing.md +++ b/docs/development/releasing.md @@ -6,7 +6,10 @@ checks to pass. Merging that PR into main starts publication automatically. The Release workflow validates the merged release metadata and ancestry before creating a tag. npm and MCP Registry publication use the exact reviewed merge -SHA returned by Release Please. Later main commits cannot change that source. +SHA returned by Release Please. Before either registry is published, the release +run calls full CI qualification at that exact revision, including coverage, +portable providers, and every native package host. Later main commits cannot +change or cancel that proof. Ordinary main pushes and closed, unmerged PRs cannot publish packages. Check both publication jobs and the published-package canary; a merged PR or GitHub tag alone does not establish that publication finished. Retry failed jobs in @@ -196,8 +199,14 @@ both registry publishes. See [npm's provenance implementation](https://github.com/npm/cli/blob/v11.16.0/workspaces/libnpmpublish/lib/provenance.js) for the use of GitHub's workflow ref and commit SHA. -The workflow builds the bundled Windows controls and verifies the packaged -artifact before npm publication. It then verifies the published CLI, the +Full qualification builds the bundled Windows controls and verifies the packaged +artifact on its native hosts. The Linux x64 verifier retains the exact tarball +it installed and tested, after its workspace cleanup completes. The npm job +downloads that archive from the same workflow run and checks its source SHA, +run identity/attempt, package and Node versions, host identity, and SHA-256. +It publishes that archive without rebuilding or repacking it. Re-running failed +publisher jobs can reuse a prior successful attempt from the same run. +The workflow then verifies the published CLI, the capability-scoped MCP catalog, and the isolated package update path before publishing MCP Registry metadata. @@ -218,6 +227,15 @@ release baseline and can propose an already-published version again. After publication, open a PR from the release branch back to main. Preserve main's later implementation changes and regenerate ignored build outputs from the combined contracts with the released package version. +Before merging, check whether GitHub permits merge commits: + +```bash +gh api repos/morluto/rea --jq .allow_merge_commit +``` + +If disabled, a maintainer must arrange an approved ancestry-preserving merge +path before synchronization can finish. Squash and rebase merges do not put the +released tag in main's ancestry. Do not substitute them for this step. Review and test this synchronization PR, then use a merge commit so the release tag remains in main's ancestry. Keep the released tag unchanged. diff --git a/docs/development/testing.md b/docs/development/testing.md index 9f657d44e..77d160a13 100644 --- a/docs/development/testing.md +++ b/docs/development/testing.md @@ -263,17 +263,62 @@ CI owns coverage; aggregate and domain/contract thresholds are maintained in Coverage does not replace named boundary or real-provider scenarios. CI runs six native Vitest shards without retries. Each shard emits a blob -report; the merge job produces aggregate coverage plus JUnit and JSON timing +report; the merge job produces JUnit and JSON diagnostics, a module timing +report, plus aggregate coverage during full qualification. It retains available reports even when a shard fails, uploads available diagnostics, and writes the slowest files to the workflow summary. Partial reports are marked diagnostic only. Failed, cancelled, or missing selected shards still fail the required gate, -and aggregate coverage thresholds remain enforced by the merge command. -Only successful complete merges publish the small `test-timings` artifact, with +and aggregate coverage thresholds remain enforced in full qualification. +Only successful complete full-tier merges publish the small `test-timings` artifact, with checkout-relative paths; the build job downloads that artifact for the sequencer -instead of the coverage/JUnit bundle. Missing history falls back to native +instead of the coverage/JUnit bundle. Timing weights come from Vitest module +diagnostics and include tests and hooks, worker preparation, environment, +imports, and setup. Import timings already include transform waits, which are +not added again. The weights describe file costs under the measured worker and +coverage settings; their sum is not workflow elapsed time. The diagnostic +artifact retains the phase breakdown, while shard history keeps only each +file's total. Legacy test-body-only history and missing history fall back to native sharding. Static checks, documentation, build, package verification, and real-system lanes remain separate jobs so one kind of evidence cannot stand in -for another. +for another. Workflow syntax and expression validation runs inside the required +static-check job when workflow changes select it, avoiding a separate runner. +Native, provider, fixture, SQLite compatibility, and website lanes wait for +static checks to succeed before allocating their runners. This avoids spending +those runner slots on revisions that already fail static validation. Portable +test shards and documentation checks remain independent of static results, so +they can still provide diagnostic feedback. The required gate rejects skipped +selected lanes when static checks fail; passing revisions retain all selected +coverage. This ordering reduces peak demand on invalid revisions but can add +static-check waiting to otherwise passing runs; it is not a measured reduction +in end-to-end latency. + +Core jobs have execution limits of five minutes for classification, ten minutes +for static checks, builds, docs, and report merging, and thirty minutes per +portable test shard. These limits leave headroom for cold setup and full coverage +while preventing a hung job from holding the active main run for hours. They do +not bound runner queue waiting. Timeouts still fail the required gate. + +The separate `CI timings` workflow batches recent completed CI and Release runs +hourly or on manual dispatch. It uploads `ci-job-timings-batch` with raw API pages and +a normalized point-in-time report for each collected workflow attempt, plus a +batch manifest describing examined coverage, failures, and limits. Overlapping +lookback windows may collect an attempt again; identify records by run ID and +attempt. Each batch examines at most 100 completed runs per workflow created in +the preceding 24 hours, with a four-minute API collection budget. It collects the +latest attempt of each selected run and does not claim an exhaustive archive. +It runs the reporter from the trusted default branch with read-only permissions, +treating workflow runs as API data. It does not allocate a new reporter job for +every completed, cancelled, or skipped workflow. Reports separate queue +waiting (`created_at` to `started_at`) from completed execution and report +percentiles plus matched `npm ci` and artifact-step durations. +Queue excludes dependency waiting before job creation and does not establish +whether account concurrency or runner availability caused the wait. Queued jobs with +placeholder start times, skipped jobs, and missing or invalid timestamps remain +unknown. The reporter targets each selected run and attempt explicitly. +Summed job elapsed time is parallel work, not workflow wall time, CPU time, +memory usage, or billing. Step names identify samples, not complete transfer +costs. Its queue, execution, and failures are independent of the required gate +and publication. CPU time and peak process-family memory are not measured by this API. The build job saves portable Turbo outputs across runs. Eight Linux real-system lanes restore this cache without waiting for the build job. The shared action @@ -697,6 +742,44 @@ specifications, independent mappings, unchanged bytes, and decompilation of a known return value. AArch64 remains covered by deterministic tests rather than this real-provider lane. See [raw binary analysis](../providers/raw-binary.md). +`npm run verify:ghidra:address-context` runs on Linux with a caller-installed +Ghidra, full JDK, and an x86-64 ELF GCC toolchain (`CC` selects another compatible +compiler). It builds +`tests/conformance/c/pie-address-context.c` as a PIE ELF without executing it. +The compiled CLI and real stdio MCP workflow must expose the measured image +base, retain segment address spaces, agree on the overview, resolve explicit and +numeric file offsets, and reject unmapped analysis addresses with actionable +guidance. It checks the reverse `address-to-file-offset` mapping, file-coordinate +Evidence locations, and the suggested CLI search and load-image commands. +The verifier compares mapped bytes with the source file and checks source +identity, session preservation after failed lookup, owned runtime cleanup, and +verified empty process lineage. This lane does not establish Windows or macOS +real-provider coverage. + +For source-identity boundaries that a normal single-file import cannot create, +`tests/conformance/ghidra/ReaFileOffsetSourceProbe.java` exercises the production +bridge against real Ghidra `FileBytes`. It rejects auxiliary and partial sources, +checks the original target's round trip, and retains ambiguity when duplicate +target bytes have distinct loaded mappings. Injected decompiler failures and +cancellation verify that completed source/function resolution facts and backend +failure codes survive; these injections do not establish natural engine failures. +On Windows, after creating the +source-owned PE fixture, run from the repository root: + +```powershell +node scripts/create-ghidra-windows-fixture.mjs +$proofRoot = Join-Path $env:TEMP 'rea-file-offset-source-proof' +New-Item -ItemType Directory -Path $proofRoot -Force | Out-Null +Copy-Item bridge/ghidra/ReaGhidraBridge.java, bridge/ghidra/ReaGhidraExtensions.java, tests/conformance/ghidra/ReaFileOffsetSourceProbe.java -Destination $proofRoot +& "$env:GHIDRA_INSTALL_DIR/support/analyzeHeadless.bat" $proofRoot source-proof -import "$PWD/build/fixtures/rea-ghidra-windows.exe" -scriptPath $proofRoot -postScript ReaFileOffsetSourceProbe.java -deleteProject +``` + +Require the `REA_FILE_OFFSET_SOURCE_OK` marker and no script errors; Ghidra may +exit successfully even when a post-script fails. The probe edits only its +temporary analysis database and does not execute the fixture. This producer +regression supplements public CLI/MCP coverage and does not establish Linux +host behavior or native process-supervision controls. + ## Apple Interface Builder archives `npm run verify:interface-builder` compiles the source-owned AppKit XIB into a @@ -717,11 +800,32 @@ or the GitHub issue and pull-request templates run formatting and generated-document validation, including the small onboarding example consistency suite, without the source-test shards or native package lanes. Classification compares the PR head with its merge base, so later -base-branch changes do not expand that scope. Static and coverage aggregate jobs +base-branch changes do not expand that scope. Static and portable-test aggregate jobs remain present and fail if classification fails. Every code change retains the complete six-shard Linux suite; individual test files are not selected by imports or filenames. +Ordinary PRs also produce an **observational** test-selection plan. The candidate +leaf-adapter ownership table lives in `scripts/ci/test-selection.mjs`, separately +from provider-job scopes. It proposes keeping affected owners plus every unowned +test, including all CLI/MCP, acceptance, composition, conformance, and process +tests. Shared inputs, unknown paths, missing owner tests, and removed tests fall +back to the complete inventory. Renames account for both paths. Main, scheduled, +manual, and `ci:full` runs always propose the full suite. + +All six shards still execute the complete suite. The existing report merge +compares the proposal with actual module outcomes and retains +`.cache/ci-test-selection/report.json` in `test-results`, including selected and +omitted paths, changed input paths, missed failures, unobserved files, scheduling weights, PR head and +executed merge SHA. This adds no test reruns or runner jobs. Missing, duplicate, +skipped, interrupted, or unhandled results cannot establish a complete comparison; +even a complete passing comparison is not proof of ownership completeness. +Before enabling omissions, review representative full-run comparisons and +cross-owner consumers, including failures, and measure completed CI feedback and +runner demand. There is no automatic promotion or switch to skip tests. The +initial proposal measures only leaf producer-test omissions; it does not promise +the savings of a broader affected-test planner. + `scripts/ci/plan.mjs` selects lanes using the ownership table in `scripts/ci/scopes.mjs`. Provider implementation changes run their real-provider verifiers and the Linux x64 installed-package/Inspector baseline. The `apple` @@ -736,9 +840,19 @@ lane. Edits to verifier entrypoints run only by manual, licensed or self-hosted workflows run static checks and the Linux suite. Website changes run website checks. Provider workflow changes validate the workflow and run that provider's verifier. Manual-provider/Android workflow changes run workflow validation only. +The four-version SQLite compatibility matrix has its own `sqlite` scope for +SQLite implementation, contracts, CLI/MCP registration, fixtures, and shared +runtime boundaries. SQLite and server-lifecycle test edits and the SQLite npm +scripts also select it. Unrelated code edits retain the complete portable suite +on the pinned Node version without starting four additional compatibility jobs. +Full qualification retains every SQLite version. Shared process/contract/CLI boundaries, dependencies, other packaging inputs, -unknown paths, and changes to the planner select the full baseline. Package -script-only edits select their owning verifier when its entrypoint is +unknown paths, and changes to the planner select the full baseline. +CI timing collection, timing history, and test-report helper edits retain static +checks and the complete portable suite without selecting unrelated host/provider +lanes. Classification, qualification, gate, release receipt, and unknown CI +scripts keep the broad fallback. +Package script-only edits select their owning verifier when its entrypoint is identifiable; unknown or shared script changes select everything. Android build-script edits retain the Linux suite and workflow validation; real Android verification stays manual. Renames account for both paths. @@ -746,38 +860,84 @@ verification stays manual. Renames account for both paths. This narrower selection trades PR-time coverage for runner capacity. A change to unowned shared runtime code that fails only on arm64, macOS, Windows, the Apple artifact lane, or a provider lane that does not own the file is not caught on -the PR; the main-push full baseline reports it after merge. Ownership globs do +the PR; scheduled full qualification reports it after merge. Ownership globs do not follow imports. Use the `ci:full` label when a change may have native-host or provider effects outside its owners. -Main pushes and manual dispatch retain the full baseline, including all portable -provider lanes and the native matrix below. A `ci:full` PR label selects the full -baseline on the next PR run; manual dispatch can request it immediately. Each +Ordinary main pushes use the same owner scopes as PRs. Their diff starts at a +successful ancestor push run of this CI workflow, rather than the preceding +push: changes from failed or cancelled intermediate runs remain in scope. +Missing, untrusted, or non-ancestor history selects every lane. The lookup is +bounded to the last 100 successful push runs; lookup failures broaden selection. +Every code change still runs all six portable shards, without coverage +instrumentation in this fast tier. This deliberately avoids relying on an +import graph for generated files, filesystem inputs, subprocesses, or bridges. + +Scheduled qualification is admitted hourly at minute 23. A forced full run at +03:23 UTC refreshes runner and dependency drift every day. Other hourly runs +can reuse a successful full-qualification receipt for the exact source SHA +from the same repository's trusted CI workflow on its default branch. Both the +receipt and original workflow run must be less than 24 hours old, so retrying an +old gate cannot renew stale proof. Missing, expired, failed, foreign, or uncertain proof runs full +validation; API lookup failure also runs full. Lookups examine at most 100 named +receipts and three candidate runs within a 20-second budget. Reused runs select +no validation lanes, identify the original run, and produce no new receipt, so +reuse cannot indefinitely extend proof freshness. They make no fresh provider +observation. Manual dispatch, `ci:full`, and exact release qualification always +run full validation. + +Full qualification includes aggregate coverage, +every portable provider lane, and all native hosts below. Adding `ci:full` +immediately starts the separate `Full PR qualification` workflow against the +label event's merge revision; subsequent PR revisions also select the full tier +in normal CI while that label remains. Unrelated labels do not start validation +jobs or replace the main CI checks. Manual dispatch also requests full validation. +Fast-tier broad fallbacks retain all owner lanes and the three-host +package matrix; Intel macOS and coverage remain full-tier obligations. Each classification job records its selection and broad-fallback reasons in the run summary. Representative Git-diff cases live in `tests/boundary/filesystem/ciChangeScope.test.ts`. -`CI required` checks classification and every selected lane, rejecting failed, -cancelled, or unexpectedly skipped work. Existing required check names are -preserved; changing branch protection to require the new aggregate is a separate -repository-settings operation. Newer commits cancel superseded CI for the same -PR or main branch. Release publication has its own concurrency group and retains -its package verification and public-registry canary. Licensed/self-hosted +`CI required` always runs and checks classification and every selected lane, +rejecting failed, cancelled, or unexpectedly skipped work. It rejects missing or +unknown tiers and requires every canonical scope to be explicitly `true` or +`false`; incomplete classification cannot silently omit verification lanes. +Branch protection +should require this aggregate, `Static checks`, `Portable tests`, and +`Conventional PR title`. Title validation runs separately on PR opening, +reopening, commits, and edits; correcting a title refreshes only this lightweight +check. It reads title text through an environment variable, executes no PR code, +and has no token permissions. Its separate concurrency group cannot cancel +test runs. Fast PR runs cancel superseded feedback for the same PR. Main push +runs keep one active run and the latest pending run for that branch. +Scheduled/manual qualification has a separate concurrency group: active work +finishes and only the latest pending run is retained. Release qualification uses +its exact source SHA and cannot be cancelled by newer main pushes. Provider and +website lanes inherit their caller's scheduling; reusable +workflows have no independent cancellation group. Direct manual lane dispatches +run independently on disposable hosted runners. Publication +requires that qualification to succeed and consumes its exact verified tarball, +checking source SHA, workflow run, run attempt, package/Node version and SHA-256 +before npm publication. Earlier attempts from the same workflow run are accepted +when rerunning failed publisher jobs; future attempts and other runs are rejected. +The public-registry canary still verifies the published package. Licensed/self-hosted provider workflows and the Android smoke test retain their explicit triggers. CI exercises the pinned Node.js runtime on native hosted runners: -| Host | Runner | Baseline checks | -| --------------------- | ------------------ | ---------------------------------------------------------------------------------------- | -| Linux x64 | `ubuntu-latest` | Installed package and real Node Inspector CLI/MCP | -| Linux arm64 (aarch64) | `ubuntu-24.04-arm` | Installed package and real Node Inspector CLI/MCP | -| macOS 15 arm64 | `macos-15` | Installed package and real Node Inspector CLI/MCP | -| macOS 15 x64 | `macos-15-intel` | Installed package and real Node Inspector CLI/MCP (main, dispatch and `ci:full` only) | -| Windows x64 | `windows-latest` | Curated capabilities, native controls, installed package and real Node Inspector CLI/MCP | +| Host | Runner | Baseline checks | +| --------------------- | ------------------ | ------------------------------------------------------------------------------------------- | +| Linux x64 | `ubuntu-latest` | Installed package and real Node Inspector CLI/MCP | +| Linux arm64 (aarch64) | `ubuntu-24.04-arm` | Installed package and real Node Inspector CLI/MCP | +| macOS 15 arm64 | `macos-15` | Installed package and real Node Inspector CLI/MCP | +| macOS 15 x64 | `macos-15-intel` | Installed package and real Node Inspector CLI/MCP (hourly, dispatch, release and `ci:full`) | +| Windows x64 | `windows-latest` | Curated capabilities, native controls, installed package and real Node Inspector CLI/MCP | -macOS x64 is the slowest package host. Pull requests without the `ci:full` label -omit it, so darwin x64 installed-package and Inspector regressions surface on -the main-push full baseline rather than on the PR. +macOS x64 is the slowest package host. Ordinary PRs and main pushes omit it, +so darwin x64 installed-package and Inspector regressions surface in full +qualification. Schedule admission can be delayed by GitHub; the hourly trigger +does not guarantee an hourly completed result. Release publication waits for +its own complete result at the exact released revision. Package lanes assert the actual Node platform/architecture before verification and record those values with the Node version. The package matrix runs up to @@ -803,17 +963,34 @@ The Linux source-test shards download a shared runtime and generated test metadata snapshot produced by the build job with `npm run test:prepare`. The snapshot includes `dist/`, generated skills, the MCP tool catalog, product catalog, and managed-conformance metadata. Each shard still installs the locked -dependencies and runs its assigned coverage-enabled tests; it no longer +dependencies and runs its assigned tests; full qualification enables coverage. It no longer regenerates the same metadata independently. -The build job also retrieves the merged timing report from the last successful -default-branch push and includes that same report in each shard's snapshot. +The build job also finds an available `test-timings` artifact from a successful +trusted default-branch scheduled or manual qualification and includes that same +report in each shard's snapshot. The bounded lookup verifies the artifact's +producer; newer schedules that reuse qualification without producing timings do +not hide the last full run's artifact. CI assigns discovered files by historical duration, with a deterministic fallback weight for new files, rather than dividing only by file count. Every -discovered file still belongs to exactly one shard; worker limits, project -ordering, coverage instrumentation, and aggregate thresholds remain unchanged. +discovered file still belongs to exactly one shard; worker limits and project +ordering remain unchanged. The merge job rejects successful reports with missing, +unexpected, or duplicate portable files. Coverage instrumentation and aggregate +thresholds remain enforced in full qualification. Missing or unusable history falls back to Vitest's default assignment. Only -timing data is reused; persistent compile caches remain disabled. +timing data is reused; live provider results are never cached. Turbo outputs are +restored by task hash, with trusted default-branch runs as cache writers and PRs +as restore-only consumers. npm caches hold downloads, not `node_modules`. + +The eight automatic browser, binary-layout, EVM, JavaScript-recovery, +recorded-crash, and web provider lanes download `rea-build-cache` from their own +run after the build and static jobs succeed. Their existing build commands still +validate task hashes and rebuild mismatched inputs; provider observations always +run. Provider-workflow-only edits also admit the build without enabling source +test shards. Direct provider dispatches retain the cross-run restore-only cache. +This removes repeated compilation on fresh source revisions, but adds the build +as a prerequisite: a delayed build can delay provider admission. Compare queue +and execution times before claiming an end-to-end speedup. These native baseline checks complement the Linux source-test shards and the separate Apple-artifact and real-provider lanes. Actual Hopper, Ghidra, IDA, @@ -849,6 +1026,14 @@ establish passing Android coverage; inspect its execution receipt. The `termux-browser-diagnostics` artifact retains the Termux command log, exit status, and Android logcat on success or failure. The emulator is disposable. +## Packet capture analysis + +`npm run verify:pcap -- --pcap PATH` exercises caller-supplied tshark and +capinfos against a saved capture. Linux verification uses Wireshark 4.6.6 +and captures containing DNS, TLS and HTTP traffic. Native Windows and macOS +engine behavior remains unverified; process fixtures do not establish it. +See [Packet capture analysis](../guides/data/pcap-analysis.md) for contracts and budgets. + ## Apple native metadata and UI `npm run verify:apple-dispatch` compiles the Objective-C fixture (classes, diff --git a/docs/getting-started/client-configuration.md b/docs/getting-started/client-configuration.md index ac9028a90..971f65886 100644 --- a/docs/getting-started/client-configuration.md +++ b/docs/getting-started/client-configuration.md @@ -6,6 +6,12 @@ for the reviewed setup transaction and [client IDs](installation.md#supported-ag The versioned verification notes below describe their stated runs; live service acceptance is verified only where explicitly recorded. +## Fiddler Everywhere alongside REA + +Connect Fiddler Everywhere's MCP server separately for HTTP traffic debugging, +preserving your REA client entry. See the +[setup instructions and public skills](../guides/web/web-network-captures.md#fiddler-everywhere-mcp-and-public-skills). + ## GitHub Copilot CLI For GitHub Copilot CLI 1.0.95, `gpt-4.1` model metadata can block ordinary @@ -95,6 +101,11 @@ Setup and doctor follow Qwen Code's tilde and working-directory-relative home overrides. Qwen Code also discovers personal skills in `~/.agents/skills`, where setup installs the bundled workflow. +## Antigravity + +Antigravity 2.0 discovers personal skills in `~/.gemini/config/skills`. +Setup installs its selected skill copy there. + ## Gemini CLI Gemini CLI uses `$GEMINI_CLI_HOME/.gemini/settings.json` when that home override diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 23b27b2f1..2a0f33557 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -57,6 +57,10 @@ Hopper installation or any file write. Declining or pressing Ctrl-C makes no changes. Agent configuration writes preserve unrelated entries and comments, create backups, use atomic replacement, and verify their result. Setup and uninstall retain an existing `.rea.backup` rather than replacing the first snapshot. +If that snapshot differs from the current configuration, setup previews and +preserves a verified `.rea.backup..recovery` copy of the current bytes. +Both snapshots remain available; a failed rollback reports the current recovery +copy's path and the restore failure. Setup also retains valid environment overrides in REA's existing server entry, such as `REA_MCP_INPUT_SCHEMA_PROFILE` and `REA_MCP_MAX_RESPONSE_BYTES`. Detected provider settings replace only matching environment keys. @@ -101,13 +105,11 @@ rea setup --yes --all-detected --install-hopper --json ### Skill destinations -The bundled skill is installed where each selected client discovers personal -skills: Claude Code uses `~/.claude/skills` (or -`$CLAUDE_CONFIG_DIR/skills` when configured). Gemini CLI uses `.agents/skills` -under its selected home; Antigravity 2.0 uses `~/.gemini/config/skills`. -Other integrations, including Qwen Code, use `~/.agents/skills`. -A mixed selection plans each distinct destination. Selecting the skill without a client uses the shared -directory. Setup leaves existing skill copies in other locations untouched. +The bundled skill is installed in each selected client's personal skill directory. +See [client configuration](client-configuration.md) for client-specific roots, +profiles, and environment overrides. A mixed selection plans each distinct +destination. Selecting the skill without a client uses `~/.agents/skills`. +Setup leaves existing skill copies in other locations untouched. `rea setup --skill-client claude_code --yes --json` refreshes and verifies the selected skill destination independently of MCP registration selection. The @@ -319,8 +321,8 @@ The Hopper launcher action used by REA creates a document from an executable; its supported command-line interface does not attach to an already-open document. While another live REA session owns the same target and loader profile, a second session reports the owning run ID instead of opening a -duplicate document. Closing the owning REA session releases this guard; Hopper -keeps its document open. A later REA session can therefore open another +duplicate document. On macOS, closing the owning REA session releases this guard; +Hopper keeps its document open. A later REA session can therefore open another document for the same target. REA does not currently identify, focus, or reuse that existing GUI document, and the supported launcher exposes no attach or reuse action for it. @@ -343,8 +345,14 @@ Hopper application per user across cooperating REA processes. A competing CLI or MCP session receives the owning session ID before Hopper is launched, for both the same target and a different target. Switch targets through that MCP session, or close it before starting another session. Closing the owner -releases the reservation. This does not attach to or claim ownership of -manually opened Hopper applications. +releases the reservation and stops REA's owned demo application and private +display; the headless Linux demo does not retain documents after MCP shutdown. +Its helper watches a private lifetime pipe, so an owner crash or SIGKILL also +stops those children, without relying on a reusable PID or a process-name scan. +A later session recovers the dead owner's stale lease after child cleanup; +private runtime files can remain when REA itself was killed. This does not attach to +or claim ownership of manually opened Hopper applications. An application left +running by an older REA version must still be closed before starting a new session. Stale lease recovery is serialized. If an interrupted recovery leaves its reservation directory, the diagnostic identifies that exact path. Stop REA @@ -437,8 +445,9 @@ For cursor navigation, string decoding, symbol-name limits, and regex matching, see [Hopper analysis behavior](../guides/native/native-investigation.md#hopper-analysis-behavior). Closing or switching a target closes its bound Hopper document, shuts down REA's -bridge and removes its temporary socket directory while preserving the Hopper -application and unrelated documents. A `cleanup_incomplete` +bridge and removes its temporary socket directory. The macOS Hopper application +and unrelated documents remain open; the owned Linux demo application stops. +A `cleanup_incomplete` result identifies resources whose cleanup could not be verified. REA retains unresolved cleanup ownership and any confirmed shutdown phases. After addressing the reported failure, retry `close_binary` on the same diff --git a/docs/guides/android/adb-device-analysis.md b/docs/guides/android/adb-device-analysis.md index ea871ce77..a0d77e8d1 100644 --- a/docs/guides/android/adb-device-analysis.md +++ b/docs/guides/android/adb-device-analysis.md @@ -136,8 +136,8 @@ existing analysis families directly, for example ## Resource and lifecycle limits - Caller values reach adb only as positional arguments in fixed vectors; - no tool accepts an arbitrary shell command line, and UI interaction - (`input`, `am`, `monkey`) is deliberately not exposed. + no tool accepts an arbitrary shell command line, `input`, or `monkey`. + The app/activity lifecycle tools use `am start -W` and `am force-stop`. - Per-invocation budgets: client/devices 10-20 s, shell reads 20-60 s with 64 KiB-8 MiB capture caps (logcat 4 MiB, screen 32 MiB), transfers and bugreports 600 s. Exceeded budgets report `resource_constraint`; stopped diff --git a/docs/guides/android/android-analysis.md b/docs/guides/android/android-analysis.md index b1fc4d058..81ef5aa90 100644 --- a/docs/guides/android/android-analysis.md +++ b/docs/guides/android/android-analysis.md @@ -9,6 +9,27 @@ This family is present on repository main and in npm 4.1.0. Check the [released package boundary](../../getting-started/installation.md#released-package-and-main) and the connected server's tool list before selecting it. +## Optional package delivery + +The MCP `inspect_android_package` request keeps complete output when `detail` is +omitted or `"complete"`. Select `detail: "summary"` explicitly to receive all +package, SDK and permission declarations, engine identity and class/resource +counts without decoded manifest text or duplicate raw provider replies. A +retaining session keeps the complete original Evidence and returns a distinct +linked `inspect_analysis_view` summary. This changes delivery, not JADX analysis. + +Use the returned `normalized_result.parent_evidence_id` with +`inspect_analysis_view`, source kind `retained-evidence`, and +`view: {kind: "android", facet: "manifest", offset: 0, limit: 4096}` to read the +exact decoded manifest without reopening the APK. Offsets and limits count UTF-16 +code units; follow `coverage.next_offset`. The page preserves `source_status` and +`reported_total_bytes`: exhausting retained text does not make a partial decoded +manifest complete. Complete source Evidence remains exportable under the existing +session lifetime. Servers without retention reject summary before starting JADX. +One-shot CLI output remains complete. Older servers require the existing complete +request after schema discovery. APK authenticity and runtime behavior remain +unverified. + ## Supply tools Use a **full JDK 17 or newer** (including its compiler module) and diff --git a/docs/guides/android/flutter-analysis.md b/docs/guides/android/flutter-analysis.md index 75c23dd66..ebf0ccd84 100644 --- a/docs/guides/android/flutter-analysis.md +++ b/docs/guides/android/flutter-analysis.md @@ -25,6 +25,26 @@ The equivalent MCP methods are `identify_flutter_build` (with `path`) and arm64-v8a, then x86_64, then x86, then armeabi-v7a, then the remaining ABIs alphabetically). +## Optional retained AOT delivery + +MCP `inspect_dart_aot` keeps complete output when `detail` is omitted or +`"complete"`. Explicit `detail: "summary"` returns the selected target/ABI/library +identity, all snapshot headers, structural coverage, string-pool coverage and +original lower-bound counts without the string lists. It retains complete source +Evidence and returns a distinct linked `inspect_analysis_view` summary. Analysis +and the caller's ABI choice are unchanged; one-shot CLI output stays complete. + +Use `normalized_result.parent_evidence_id` as the retained source for +`inspect_analysis_view`, with `view: {kind: "dart-aot", collection: "package_uris", +offset: 0, limit: 64}`. Collections are `package_uris`, `dart_uris` and +`class_like_tokens`. Pages preserve the original strings and order, selected ABI, +library identity and source coverage. `returned_counts` describe producer-returned +rows; counts ending in `_at_least` remain lower bounds. Exhausting a page sequence +does not make a partial pool complete or turn byte-pattern tokens into typed +classes/functions. Views do not reopen the APK. Original Evidence remains +exportable under its existing session lifetime. Summary requires a retaining +server; older servers keep the complete request after schema discovery. + ## What the AOT inspection returns `inspect_dart_aot` reads one ABI's `libapp.so` in full and reports: diff --git a/docs/guides/apple/apple-application-analysis.md b/docs/guides/apple/apple-application-analysis.md index e00454c3e..666717fc5 100644 --- a/docs/guides/apple/apple-application-analysis.md +++ b/docs/guides/apple/apple-application-analysis.md @@ -174,7 +174,7 @@ Resolution follows dyld: - `@rpath` tries each `LC_RPATH` of the loading image first, then those of the image that loaded it, up to the process root. - Dependencies load dependents-first in load-command order, and each image - loads once per process. A later request whose install name matches an + loads once per process. A later @rpath request whose install name matches an already loaded image reuses it. - Symlinks such as `Versions/Current` are followed inside the analyzed root. An escape through `..` or an absolute link is `escapes-target`. diff --git a/docs/guides/data/packet-captures.md b/docs/guides/data/packet-captures.md index d56a80037..32cedb11b 100644 --- a/docs/guides/data/packet-captures.md +++ b/docs/guides/data/packet-captures.md @@ -4,7 +4,7 @@ in an existing capture. Network, USB or Bluetooth recordings can use the same field/filter interface when the installed TShark supports their encapsulation and dissectors. This tool does not acquire traffic, open an interface or control -a device. HAR/mitmproxy web-capture workflows remain separate. +a device. HAR/SAZ/mitmproxy web-capture workflows remain separate. Supply an existing TShark 4.x installation **on Linux**, with util-linux `prlimit` available at `/usr/bin/prlimit`. Override its absolute path with @@ -128,3 +128,49 @@ Each provider admits one inspection at a time, including acquisition and cleanup An occupied provider returns a retryable capacity error before acquiring another file or worker. Closing the provider stops new admission and drains accepted work; failed cleanup remains owned and can be retried. + +## Discover protocols and field names + +`inspect_packet_fields` / `inspect-packet-fields` queries the installed TShark +registration glossary before selecting fields for capture inspection: + +```sh +rea inspect-packet-fields --query usb +rea inspect-packet-fields --kind fields --protocol usb --query idVendor +rea inspect-packet-fields --kind fields --protocol udp --all +``` + +`kind` defaults to `protocols`; `fields` selects field definitions. `protocol` +selects an exact protocol abbreviation (the protocol itself or its child fields). +`query` is a case-insensitive literal substring in name, abbreviation or field +description. `offset` skips matching records; `limit` defaults to 50. MCP +`limit: null` or CLI `--all` requests all remaining matches within the resource +budget. `--all` and `--limit` conflict. The window reports examined records of +the selected kind before filters, matching records, returned records and +`has_more`; it never counts capture packets. + +Returned records preserve field type, parent protocol, display base, bitmask, +description and original glossary line number. Empty producer strings remain +empty; protocol records have null field-only properties. Repeated abbreviations +remain separate registrations. A listed field is an installation capability, not +proof that the field appears in a selected recording. + +The adapter uses the documented `tshark -G fields` grammar under its existing +private empty profile and Linux process limits. TShark 4.6.9's full glossary was +measured at 22,303,197 bytes; discovery admits at most **32 MiB** combined command +output (capture inspection remains at **4 MiB**). Parsing walks lines once and +constructs objects only for the selected page. Returned strings are copied so +retained pages do not retain the complete glossary string. Before constructing a selected +record it charges six times the source UTF-8 bytes plus 512 bytes against an +**8 MiB** representation budget, covering JSON escaping and record bookkeeping. +If that budget would be exceeded, narrow the query or page size; results are not +silently truncated. This is a conservative admission budget, not measured heap +usage. Parent pipe buffers and producer per-process limits remain distinct. + +Tool/limiter identity, version, stderr and selected arguments are retained in +Evidence. No capture, interface or device is opened. Discovery shares capture +analysis's admission slot and cleanup owner. Each call rereads the glossary; +installed plugins, libraries and global configuration remain trusted and are not +fully fingerprinted. There is no cache or snapshot-consistent pagination claim. +The real Linux lane checks public CLI/MCP queries against the direct glossary, +including USB vendor-ID typing, negative queries and paging. diff --git a/docs/guides/data/pcap-analysis.md b/docs/guides/data/pcap-analysis.md new file mode 100644 index 000000000..1df3e5ccd --- /dev/null +++ b/docs/guides/data/pcap-analysis.md @@ -0,0 +1,118 @@ +# Packet capture summaries + +REA summarizes already saved pcap/pcapng files through caller-selected Wireshark +4.x `tshark` and `capinfos`. Use `inspect_packet_capture` for selected fields, +filters and decode-as rules; use this family for address, DNS, SNI, protocol-stack +and URI inventories. It does not acquire traffic or fetch recorded targets. + +## Supply tools + +```sh +export REA_TSHARK_COMMAND=/absolute/path/tshark +export REA_CAPINFOS_COMMAND=/absolute/path/capinfos +# Linux only; default /usr/bin/prlimit +export REA_TSHARK_PRLIMIT_COMMAND=/absolute/path/prlimit +rea inspect-pcap-client +rea inspect-pcap-capture /captures/session.pcapng --json +``` + +Without explicit tool commands, this family resolves them through PATH and +records that selection source. Client inspection reads no capture file. Capture +inspection requires Linux with util-linux prlimit or Windows with owned Job +Objects. macOS capture inspection returns a capability gap because the new +native memory boundary is unverified; its version probes remain available. +Tools and installed libraries/plugins are caller-trusted. An empty private +personal Wireshark configuration is used; this is not an OS sandbox. + +## Inspect only the needed facts + +MCP `inspect_pcap_capture` accepts `path` and optional `detail: "summary"`. +Complete delivery remains the default. Summary commits and retains the same +complete Evidence, returning identity, capture metadata, observed counts, +retained counts, source coverage and diagnostic lengths without large lists. +Then use its `normalized_result.parent_evidence_id` with +`inspect_analysis_view` source kind `retained-evidence`: + +```json +{"kind":"pcap","facet":"endpoints","offset":0,"limit":20} +{"kind":"pcap","facet":"dns-queries","offset":0,"limit":20} +{"kind":"pcap","facet":"dns-addresses","query":"example.com","offset":0,"limit":20} +{"kind":"pcap","facet":"tls-sni","offset":0,"limit":20} +{"kind":"pcap","facet":"diagnostics","stream":"tshark","offset":0,"limit":4096} +``` + +Other row facets are `protocols`, `http-uris` and `unattributed-addresses`. +Defaults are offset 0 and limit 64. DNS question pages give address counts; +select one exact retained question to page its addresses. Diagnostic windows +count UTF-16 code units; other windows count rows. Missing/ambiguous selectors +fail. Unknown legacy diagnostics remain unknown, not an observed empty stream. +Portable CLI views use the existing `inspect-analysis-view` workflow with inline +complete Evidence. Views never reread the source or launch Wireshark and work +after the original file is deleted. Page exhaustion covers the retained facet; +it does not establish network completeness or recover missing traffic. + +## Interpret provenance and coverage + +`target.sha256` binds observations to an admitted stable capture snapshot. Both +tools read that copy, which is hashed again after analysis. Capture metadata and +literal field values are producer observations; address/protocol counts and DNS +associations are derivations. Capture Evidence has historical-reference authority. + +Addresses count once per packet, including loopback and nested IP occurrences. +DNS addresses are associated only with one question in the same response packet; +additional records may be included, so this does not prove final resolution. +Ambiguous addresses remain in a separate inventory. Protocol distribution counts +exact `frame.protocols` stack strings. TLS SNI is recorded handshake metadata, +not process identity or proof of the destination's authenticity. + +All examined inventories are retained within the resource budget; no fixed +200/100/50-item truncation is applied. HTTP transport credentials are excluded +without rewriting other URI bytes; ambiguous credential spans cause omission. +Counts preserve distinct observed source URIs before omission or coalescing. +`coverage: "partial"` records unresolved DNS attribution or URI item loss; +component credential exclusion is also counted explicitly. Diagnostics retain +both tool stderr streams. Recorded fields do not establish decrypted payloads, +causality, process identity, absence of unrecorded traffic or current deployments. + +## Resources and lifecycle + +One inspection is admitted at a time per provider. Concurrent calls return a +capacity error; close drains active work before releasing resources. Captures +are streamed into a read-only owned snapshot with a 2 GiB disk budget. Native +capture commands enforce Linux address-space ceilings of at most 1 GiB, +300 CPU seconds, 64 MiB per file and no core dumps, preserving stricter inherited +limits. Windows uses a 1 GiB committed-memory limit for each owned tool tree. +These are not aggregate machine or filesystem quotas. + +TShark output is bounded at 8 MiB; its known five-level selected-field shape and +128 MiB graph-expansion estimate are checked before allocation. Retained facts +have a separate 16 MiB estimate. Capinfos output is limited to 64 KiB. Command +wall deadlines are 300 s for dissection, 60 s for metadata and 20 s for probes. +Native ownership preparation has its own bounded lifecycle. + +Malformed/oversized output returns no partial success. Unvalidated partial JSON +is not returned as facts. Cancellation reaches probes, acquisition, commands and +projection. Cleanup failure returns a typed error, retains completed Evidence +when available, and retains owned resources for retry on close. + +## Verification scope + +Current follow-up verification uses Linux/Node 24.18.0 and Wireshark 4.0.17. +Private real recorded corpora are checked against independent raw-frame/IP +parsing and Python aggregation, public CLI/stdio MCP parity, SDK schemas, source +hashes and retained views. Synthetic native tools separately test malformed +output, cancellation, source/snapshot mutation, capacity and cleanup; they do +not establish real Wireshark or other-platform behavior. + +The original proposal reported Linux 4.6.6, macOS/Windows 4.6.9 verification on +its earlier implementation. Those reports do not verify the new final memory +boundary. Actual Windows/Bun Wireshark execution is unverified here; macOS +capture support needs a separate enforceable-bound decision. + +```sh +npm run verify:pcap -- --pcap /absolute/saved-capture.pcapng +``` + +This verifier exercises built CLI/stdio MCP, schemas, artifact identity and +cleanup. Without `--pcap`, capture inspection is reported as unverified. Private +captures, keys and provider runtime files are not committed. diff --git a/docs/guides/javascript/javascript-application-graph.md b/docs/guides/javascript/javascript-application-graph.md index 2290491a5..48e17bf44 100644 --- a/docs/guides/javascript/javascript-application-graph.md +++ b/docs/guides/javascript/javascript-application-graph.md @@ -104,6 +104,15 @@ static inferences. Dynamic or ambiguous IPC is retained without a pairing edge. Runtime entities retain passive-CDP authority, while a successful static/runtime correspondence is a separately identified cross-layer inference. +Source module links retain their resolution mode. Static imports in `.ts` and +`.tsx` are `compiler-dependent` when compiler options have not been retained. +REA compares Node import and require resolution: a shared outcome remains +available with a limitation; divergent outcomes remain unavailable with both +conditional branches and their limitations. This models source relationships, +not verified emitted code or execution. A declaration file found only through +an emitted-extension fallback is retained as a candidate, not a runtime target; +an explicitly selected path keeps its original identity. + ## Evidence and authority Every observation and edge carries all of the following: diff --git a/docs/guides/javascript/javascript-application-workflows.md b/docs/guides/javascript/javascript-application-workflows.md index 80b850763..c3982cf1b 100644 --- a/docs/guides/javascript/javascript-application-workflows.md +++ b/docs/guides/javascript/javascript-application-workflows.md @@ -23,6 +23,14 @@ artifact digest and structural graph ID. Semantic tracing requires the semantic relation graph and reports when it is unavailable rather than treating missing data as an empty graph. +Explicit TypeScript `import type` and `export type` declarations remain source +facts and do not create runtime import or export relationships. Type export names +are reported separately from value export names. Inline `type` specifiers can +leave an empty import or re-export with side effects under +[`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html); +REA retains those dependency candidates and reports the unavailable compiler +options rather than assuming the dependency is erased. + The semantic graph wire format stores shared non-location provenance once in its required `evidence_contexts` table. Each node, relation, fingerprint, and unknown retains its exact `evidence.location` and names the owning context with @@ -156,9 +164,12 @@ to the comparison Evidence in a live session. `compare_source_to_bundle` compares one cryptographically committed `HistoricalSourceGraph` with authenticated application-graph Evidence. The stable scoring model reports every admitted signal and weight: exact source -digest, source-map original path, exact current path, path suffix, basename, and -language extension. Exact digest wins over location inference; weak basename -or extension evidence never forces a mapping. +digest, source-map original path, exact current path, path suffix, Unicode- +equivalent path, basename, and language extension. Exact digest wins over +location inference; weak basename, extension, and Unicode-equivalence evidence +never forces a mapping. Unicode-equivalent spellings are candidate evidence +only because distinct filesystem paths can preserve those spellings as separate +files; multiple canonical-equivalent candidates remain unknown. Each historical source file is classified as `unchanged`, `modified`, `removed`, `split`, `merged`, `duplicated`, or `unknown`. Multiple equally diff --git a/docs/guides/javascript/javascript-runtime-reconciliation.md b/docs/guides/javascript/javascript-runtime-reconciliation.md index af59e825b..a0a600574 100644 --- a/docs/guides/javascript/javascript-runtime-reconciliation.md +++ b/docs/guides/javascript/javascript-runtime-reconciliation.md @@ -1,28 +1,31 @@ # JavaScript static/runtime reconciliation REA can combine an existing static JavaScript Application Graph with one or -more passive browser, Electron page, or Node/Electron V8 Inspector captures without collapsing their different -authorities. The `reconcile_javascript_runtime` MCP tool and +more browser, Electron, or Node/Electron V8 Inspector observations while +preserving their different authorities. The `reconcile_javascript_runtime` MCP tool and `rea reconcile-javascript-runtime` CLI command accept Evidence records and return derived Evidence containing a combined JavaScript Application Graph and explicit match, ambiguity, mismatch, and unknown classifications. The operation performs no filesystem, browser, or Electron I/O. It accepts only semantically verified Evidence produced by `analyze_javascript_application`, -`inspect_web_page`, `inspect_electron_page`, or -`observe_javascript_runtime`; matching operation names alone +`inspect_web_page`, `inspect_electron_page`, `observe_javascript_runtime`, or +`capture_electron_scenario`; matching operation names alone is insufficient. Provider identity, predicate type, subject digest, target parameters, and normalized-result schemas are checked before reconciliation. +`capture_electron_scenario` supplies target-only partial observations. It does +not establish loaded-script coverage; see [Electron observation](electron-observation.md). + ## Workflow 1. Run `analyze_javascript_application` against exactly one application layer. Optional cache or assets directories can be analyzed independently and supplied as additional layers. 2. Run `inspect_web_page`, `inspect_electron_page`, or the attach-only - `observe_javascript_runtime`. Capturing script sources - is optional, but a source capture provides the strongest byte - identity. + `observe_javascript_runtime`, or supply existing `capture_electron_scenario` + Evidence with the partial scope above. Capturing script sources is optional, + but a source capture provides the strongest byte identity. 3. Pass the resulting Evidence records to `reconcile_javascript_runtime`. Browser URLs normally need an explicit URL-prefix mapping. Extracted Electron and V8 Inspector file locations are mapped automatically when runtime files remain @@ -104,7 +107,7 @@ nodes. REA evaluates compatible static candidates conservatively: Every successful cross-layer `observed_as` edge has `authority: cross-layer-reconciliation` and `state: inferred`. The underlying -artifact/AST observations and passive-CDP observations remain unchanged and +artifact/AST observations and runtime observations remain unchanged and retain their own Evidence links. ## Loaded, resident, and not observed diff --git a/docs/guides/managed/managed-code-analysis.md b/docs/guides/managed/managed-code-analysis.md index 879b93d56..3fdf4342c 100644 --- a/docs/guides/managed/managed-code-analysis.md +++ b/docs/guides/managed/managed-code-analysis.md @@ -151,7 +151,7 @@ assembly. Older member Evidence without `selection` remains readable. Start by identifying the artifact with `inspect_managed_artifact`, then inspect its types and CIL with `inspect_managed_members`. Use [member comparison](#member-comparison) -for another build, and [managed/native boundary rules](#managednative-boundary-rules) +for another build, and [managed/native boundary rules](#managed-native-boundaries) when matching declared native calls to supplied native Evidence. Static inspection does not load or execute the assembly. Reconstructed structure and unresolved native/runtime questions retain their own authority and coverage. @@ -221,6 +221,7 @@ provider evidence; names or vtable similarity alone do not prove that a native function implements a specific managed method.
+
## Managed/native boundary rules diff --git a/docs/guides/signals/signal-recordings.md b/docs/guides/signals/signal-recordings.md index 520d6e882..69b14d193 100644 --- a/docs/guides/signals/signal-recordings.md +++ b/docs/guides/signals/signal-recordings.md @@ -106,3 +106,37 @@ One decode is admitted at a time, including acquisition and cleanup. Excess requests receive a retryable capacity error before acquiring another file or worker. Shutdown closes admission and drains accepted work; failed cleanup remains owned and retryable. + +## Discover decoders before choosing settings + +`inspect_signal_decoders` / `inspect-signal-decoders` queries the **installed** +sigrok catalog without opening a recording or scanning devices: + +```sh +rea inspect-signal-decoders --query uart +rea inspect-signal-decoders --decoder uart --query baud +rea inspect-signal-decoders --decoder i2c --offset 0 --limit 50 +``` + +Omit `decoder` to search decoder IDs and names. Supply one exact decoder ID to +read its literal help, including required/optional channels, options, annotation +classes and documentation. `query` is a case-insensitive literal substring; +matching help retains original one-based line numbers. Empty query selects all. +`offset` skips matches; `limit` defaults to 50. MCP `limit: null` or CLI `--all` +returns all remaining matches; CLI `--all` and `--limit` conflict. +The window reports examined, matching and returned records and `has_more`. +A filtered empty page is not evidence that the installation has no decoders. + +Discovery refuses more than 65,535 line separators before constructing record +objects (65,536-line representation budget), in addition to the 4 MiB output cap. +Exceeding that budget is a resource failure with captured output. Returned text +is copied so a retained page does not keep the complete producer output alive. + +Discovery shares decoding's owned process, admission slot, resource limits, +cleanup retries and Evidence delivery. It records the executable and limiter +identities, version banner and warnings. Failed version checks and malformed +producer output preserve diagnostics. Help is producer text, not an independently +validated parameter schema. Each request probes again; it does not cache or claim +stable pages across installation changes. Libraries/decoder modules remain +trusted and are not fully fingerprinted. Catalog output includes a SHA-256 of +its executable, not a digest of the complete installation. diff --git a/docs/guides/web/browser-observation.md b/docs/guides/web/browser-observation.md index 6c8267864..3898fa5f8 100644 --- a/docs/guides/web/browser-observation.md +++ b/docs/guides/web/browser-observation.md @@ -8,6 +8,10 @@ exported script's native imports under an explicit URL/import-map context. REA can attach to a user-owned Chrome-family browser through the Chrome DevTools Protocol (CDP) and produce bounded Evidence about an existing page. This is a passive reverse-engineering capability, not a general browser automation or remote-control surface. +For request/response bodies and traffic debugging, see +[Fiddler Everywhere captures and MCP](web-network-captures.md#reading-fiddler-captures-saz). +Inspect native SAZ or HAR 1.2 offline with REA, or connect Everywhere's separate MCP server. + ## Shipped surfaces - `list_browser_targets` / `rea list-browser-targets` discovers all eligible page targets at the endpoint by default, with an optional exact-origin filter. diff --git a/docs/guides/web/web-network-captures.md b/docs/guides/web/web-network-captures.md index d49f1dcc3..c447c4783 100644 --- a/docs/guides/web/web-network-captures.md +++ b/docs/guides/web/web-network-captures.md @@ -25,6 +25,36 @@ and original zero-based producer ordinals; duplicate or out-of-range selections are input errors. Every record is validated before selection, so selecting one entry does not hide a malformed entry elsewhere. +For agent discovery over MCP, request `detail: "summary"`. REA retains the +complete selected Evidence in the session and returns identity and counts. +Use `normalized_result.parent_evidence_id` with `inspect_analysis_view`: + +```json +{ + "source": { + "kind": "retained-evidence", + "evidence_id": "" + }, + "view": { "kind": "capture", "detail": "preview", "offset": 0, "limit": 20 } +} +``` + +Preview pages select recorded HTTP headline fields, event names/times when +present, original locations and byte descriptors; they omit headers, XML and +payload content. Choose `detail: "complete"` in that view for exact record +pages, including all sidecars. Offsets follow the parent's selected record +order; producer ordinals remain unchanged. `total_records` counts the original +capture while `retained_records` and page coverage count records in the parent. +An exhausted page does not establish absence from unselected records. + +Views do not reopen the file or rerun its decoder. They remain historical +Evidence if the source changes or disappears; inspect the capture again to +observe new bytes. The inspection tool's default `detail: "complete"` preserves +existing inline delivery. For CLI use, save complete inspection JSON and pass +it as inline Evidence to `inspect-analysis-view`; the same summary and capture +page contracts apply. Large complete records can still exceed MCP's response +budget; export the retained Evidence when a single record cannot fit. + ## Formats and upstream profiles HAR uses unchanged `har-schema@2.0.0` draft-06 schemas, `ajv@8.20.0`, @@ -57,11 +87,80 @@ tested upstream source is tag `v12.2.3`, commit an explicit unsupported-profile diagnostic. Non-Linux native decoding is not supported by this adapter. +## Reading Fiddler captures (`.saz`) + +Fiddler Everywhere saves traffic in **Session Archive Zip (`.saz`)** files. +Inspect native SAZ directly, without installing Fiddler or converting to HAR: + +```sh +rea inspect-web-network-capture /absolute/session.saz saz --json +rea inspect-web-network-capture /absolute/session.saz saz --record 0 --json +``` + +MCP uses the same `capture_path`, `format: "saz"`, and optional +`record_ordinals` fields as the examples above. REA pairs `raw/_c.txt` +requests, `_s.txt` responses, and `_m.xml` metadata by filename stem. Archive +member names identify the source; zero-based ordinals follow each session's +first member in ZIP directory order, not its numeric ID or capture time. + +HTTP fields and ordered duplicate headers are retained, with stored body bytes +in binary sidecars. Bodies are not dechunked or decompressed. Metadata is an +XML node tree; optional `_w.txt` and `_g.txt` files retain opaque WebSocket and +gRPC message bytes. Missing members remain null, distinct from empty bodies. +See Telerik's [SAZ format reference](https://www.telerik.com/fiddler/fiddler-everywhere/documentation/knowledge-base/fiddler-archives). + +The existing ZIP reader verifies read members; expanded archive contents are +limited to 32 MiB in addition to the input/output budgets below. Encrypted +archives and unrecognized raw session members are unsupported. SAZ requires an +enforced decoder memory bound: Node's fixed heap, or the Windows Job Object +commit limit. Bun on hosts without that Job Object limit returns capability +unavailable before starting the SAZ decoder. Non-session +members are inventoried without decoding their content. Original files remain +unchanged. Linux verification includes independently checked public recorded +Mattermost captures from [FOREST](https://github.com/dfrc-korea/FOREST/tree/405c9154658a128ea203a6c10040cec55111ed03/api-results/dataset) +and the Fiddler author's [encoding corpus](https://github.com/ericlaw1979/Clearinet/blob/b6faf78cde1e72042980364f180ceb34b77d1434/Test/data/Encodings.saz), +plus synthetic malformed/limit fixtures. Their exporting product versions are +not authenticated. An interactive export from a current Fiddler Everywhere +installation and its live MCP server remain unverified. Support here is the +bounded documented raw HTTP/XML SAZ layout, not every product/version profile. + +For visual inspection, use Everywhere's **Import Snapshot**, then **Inspectors** +and **Overview**. HAR remains an alternative: select sessions, choose +**Export > HTTPArchive**, and confirm `log.version` is `"1.2"`. Preserve the +original SAZ when exporting. See the [import/export instructions](https://www.telerik.com/fiddler/fiddler-everywhere/documentation/collaboration/exporting-and-importing). + +## Fiddler Everywhere MCP and public skills + +For agent-driven traffic debugging, connect Everywhere's MCP server separately +from REA. Run a current Everywhere release with MCP access (Trial, Pro, or +higher), internet access, and a compatible MCP client. Use +**Settings > MCP Server > Coding agent**, or **Manual setup** with the generated +API key. The default endpoint is `http://localhost:8868/mcp`. See Telerik's +[MCP setup guide](https://www.telerik.com/fiddler/fiddler-everywhere/documentation/agent-tools/fiddler-mcp-server) +and [agent-skills prerequisites](https://www.telerik.com/fiddler/fiddler-everywhere/documentation/agent-tools/agent-skills). + +Telerik's [public skills](https://github.com/telerik/fiddler-agent-tools) cover +installation (`fiddler-download-setup`), connection setup, and traffic analysis: + +```sh +npx skills add telerik/fiddler-agent-tools --skill fiddler-mcp-setup +npx skills add telerik/fiddler-agent-tools --skill fiddler-traffic-debugging +``` + +After setup, reload the agent client and use the connected server's advertised +tool names and schemas. Check status, list sessions, then inspect relevant +session IDs. Set `sessionsSource` to `LiveTraffic` for HTTP(S) traffic or +`AgentCalls` for enriched LLM calls; active filters affect the session list. +For an existing run, skip the skill's pre-capture steps that replace process +filters and clear sessions. The documented MCP session sources do not provide +a saved-snapshot selector; use the SAZ workflow above for saved files. REA does +not register or wrap the Fiddler MCP server. + ## Reading the evidence - `artifact` identifies the caller-selected file and stable snapshot digest. -- `records` preserve producer order/ordinals and original JSON pointers or byte - ranges. No live browser transaction or scenario IDs are invented. +- `records` preserve producer order/ordinals and original JSON pointers, byte + ranges, or SAZ member names. No live browser transaction or scenario IDs are invented. - `reported` retains the producer's fields. HAR container metadata is returned separately, with `log.entries` replaced by `null` and `records_pointer` identifying the record collection. This is an inspection representation, @@ -156,7 +255,7 @@ response fields, including HAR's `status: 0` and an empty `mimeType`, remain unknown, not invented statuses or MIME types. The view makes no handler-identity, schema or causality claim. It performs no -network activity. Native mitmproxy captures return a typed unsupported error. +network activity. Native mitmproxy, SAZ and qlog captures return a typed unsupported error. Parents inspected with `sensitive_values`, or whose Evidence does not record `sensitive_value_count`, return a typed unsupported error whose reason is the canonical token `sensitive_values_unretained`. The view would write path @@ -192,14 +291,15 @@ Complete evidence has a 32 MiB input, 96 MiB decoder reply and 64-level nesting budget. Exceeding a budget returns no partial success. Oversized selected captures return an input error identifying `capture_path` and the byte budget; owned reply/output failures remain output or provider errors. -HAR runs in an owned -192 MiB Node old-generation heap with one V8 worker. Native decoding applies +HAR, SAZ and qlog run in an owned +192 MiB Node old-generation heap with one V8 worker. Mitmproxy decoding applies Linux limits of 768 MiB address space, 30 seconds CPU and 96 MiB file output; both commands have a 30-second wall deadline and independently supervised process cleanup. Owned decoder diagnostics retain at most 1 MiB across stdout and stderr; the collector drops overflow as it arrives, reports the limit failure and verifies cleanup. Heap limits alone do not establish aggregate RSS limits. -When REA runs on Bun, the HAR decoder runs on Bun, which ignores these V8 heap +SAZ and qlog refuse decoding when neither a Node heap limit nor a Windows Job Object bound can be enforced. Existing HAR availability is preserved. +When REA runs on Bun, the HAR/SAZ/qlog decoder runs on Bun, which ignores these V8 heap flags; its limitations and resource failures then omit the heap sizes. On Windows, the decoder's owned Job Object instead limits its committed memory to 704 MiB, the 192 MiB budget plus a 512 MiB reserve for Bun itself. The @@ -207,7 +307,7 @@ limitations state that limit, and reaching it returns `resource_constraint` with `process_memory_limit_bytes`, whatever exit status Bun reports. Observed decoder memory exhaustion returns `resource_constraint`, with the -selected capture, applicable limits and retained process diagnostics. HAR's +selected capture, applicable limits and retained process diagnostics. HAR/SAZ/qlog's old-generation heap is fixed; inherited `NODE_OPTIONS` cannot raise it. Record selection happens after complete decoding and does not reduce that workload. Use a smaller capture exported by its producer or another decoder @@ -234,3 +334,108 @@ Command cleanup failures retain the original status and both diagnostic streams; the decoder's ownership preparation receives the same cancellation signal. MCP advertises the same strict named input contract used by the application. Historical inspection delegates argument validation to that shared application boundary so accepted explicit-sensitive declarations also cover invalid argument names and other correction details. The SDK receives raw arguments through its Standard Schema interface; malformed inputs still fail before decoder or filesystem effects and return the normal structured REA error. Protocol-envelope validation remains owned by MCP. + +## Retained aioquic qlog + +Select `format: "qlog"` through `inspect_web_network_capture`, or: + +```bash +rea inspect-web-network-capture /absolute/origin.qlog qlog --json +rea inspect-web-network-capture /absolute/origin.qlog qlog --record 95 --record 0 --json +``` + +The initial profile is **aioquic 1.5.0, JSON qlog 0.3**: one JSON object with +`qlog_format: "JSON"`, `qlog_version: "0.3"`, `traces` containing object events +with `name`, finite numeric `time` and object `data`. JSON-SEQ, JSONL, columnar +array events and other versions are unsupported. Duplicate JSON members, +malformed UTF-8, invalid interpreted QUIC integers and excessive nesting fail +without partial success, including in events outside the selected ordinals. +Well-formed event subsets and missing frame metadata remain inspectable. +Unknown extensions are retained; this is not validation of every qlog schema. + +Choosing the format selects the interpretation profile; the file does not +necessarily report or authenticate an aioquic version. The profile's clock +uses Unix-epoch milliseconds, verified in aioquic 1.5.0's `QuicLoggerTrace` +`log_event`/`encode_time`. The `qlog.clock.basis` and Evidence analysis profile +state that assumption explicitly. Numeric lexemes survive independently of +safe JSON-number projections; decimal spelling does not establish physical +clock precision or monotonicity. + +Every event has a global ordinal from trace/event source traversal and its +original `/traces/T/events/E` pointer. This order is not a global time sort. +Trace index and the selected artifact identify a connection observation; +reported ODCID is preserved without claiming global uniqueness. Streams are +scoped by trace, stream ID and sent/received direction. Control/QPACK streams +are retained, so counting streams does not count HTTP requests. + +`qlog` is a typed facet required exactly for this format. Its scope is +`all-recorded-events-before-selection`: selection changes returned event +records while facts cite the original ordinals across the entire recorded +file. The container retains trace metadata with each events array replaced +by null; there is no single events pointer shared by all traces. + +| Fact | Basis and limits | +| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Original event and loss declaration | Observed endpoint report; `recovery:packet_lost` does not prove actual network loss. Missing packet number/type remains unknown. | +| STREAM ranges and byte totals | Derived per trace and direction from reported offsets and lengths using exact integer arithmetic. `unique_bytes` unions intervals; `frame_length_sum` includes overlaps; `repeated_bytes` is their difference. Overlap alone does not prove retransmission or equal contents. | +| FIN final sizes | Reported offset plus length where FIN is true; multiple conflicting sizes remain visible. A final size does not establish complete coverage or a received body. | +| Incomplete fact records | Ordinals with omitted/redacted interpretable frame metadata; usable fields in other records survive. An empty list does not establish complete logging or capture. | +| HTTP bodies and causality | `body_bytes: "not-reported"`; lengths and headers are metadata, with no reconstructed body, hash, timing causality or live process attribution. | + +QUIC integer fields interpreted here accept exact nonnegative JSON integer +values through `2^62 - 1`, including equivalent exponent notation. Offsets plus +lengths must fit that range. Derived sums are decimal strings and are not +rounded to JavaScript numbers. A missing offset is unknown, never defaulted to +zero. Ranges can start above zero or contain gaps. Packet headers, HTTP events, +raw lengths and unknown extensions remain producer evidence rather than being +normalized into invented HAR requests. + +The adapter excludes authorization/proxy authorization/cookie/set-cookie +values in known HTTP frame events, reset tokens in transport parameters and +NEW_CONNECTION_ID frames, and NEW_TOKEN frame tokens. Known URL header userinfo +and explicit sensitive values follow the shared exclusions. Ordinary extension +fields and token-looking query text remain retained. Explicit declarations also +cover normalized numeric projections, derived totals and trace pointers; facts +that cannot be safely shown are omitted with incomplete-record coordinates. +No keylog, PCAP, live URL or recorded target is opened by the qlog decoder. + +To repeat the real-provider lane with **local caller-supplied evidence** from +the educational aioquic 1.5.0 experiment (one origin trace, known 32,803-byte +stream coverage and one 1,169-byte repeated range in the loss case): + +```bash +npm run verify:web:qlog -- /absolute/control/origin.qlog /absolute/loss/origin.qlog /absolute/new-report.json +``` + +This lane checks built CLI/stdio MCP parity, SDK-converted JSON Schemas, +artifact digests, original event count, selection scope, retained parent lookup, +credential exclusions and the known control/loss facts. The report is created +exclusively and contains no keys or captured credential values. It is a +fixture-specific verification, not a general loss detector. CI uses synthetic +format inputs for malformed cases and limits; those tests do not establish +producer provenance. PCAP parsing and correlation remain outside this stage. + +### Focused qlog views + +Use MCP `inspect_web_network_capture` with `format: "qlog", detail: "summary"` +for identity, profile, scope and retained-fact counts. Then pass its +`normalized_result.parent_evidence_id` to `inspect_analysis_view` as a +`retained-evidence` source. + +```json +{"kind":"qlog","facet":"traces","offset":0,"limit":10} +{"kind":"qlog","facet":"streams","trace_index":0,"offset":0,"limit":10} +{"kind":"qlog","facet":"contributions","trace_index":0,"stream_id":"0","direction":"sent","offset":0,"limit":20} +``` + +Trace pages omit nested lists and give their counts. Stream pages preserve +exact byte totals but omit contributions, ranges and final-size lists. For +those lists select `contributions`, `ranges` or `final-sizes` with all three +stream selectors. `loss-declarations` and `incomplete-records` need only +`trace_index`. Offsets count rows in that retained facet; defaults are 0 and 64. Missing or ambiguous selectors fail rather than choosing a connection. + +These views page already interpreted facts without decoding again or opening +the source, and work after its deletion. Facts still cover all recorded events +before parent record selection. Their exhaustion does not prove logging or +network completeness. Event preview/complete pages remain available through +kind `capture`, with original numeric lexemes and producer ordinals preserved. diff --git a/docs/providers/ghidra-provider.md b/docs/providers/ghidra-provider.md index d30ac388f..8a50d1573 100644 --- a/docs/providers/ghidra-provider.md +++ b/docs/providers/ghidra-provider.md @@ -41,6 +41,80 @@ does not prove text is absent. Both list and search Evidence carry this limitation. When an address is known, use `read_bytes` and `xrefs` to inspect bytes and references. +## Loaded addresses and file offsets + +`rea analyze --provider ghidra --json` and MCP `binary_overview` report +the observed loaded `image_base` in `normalized_result`. They retain each +segment's reported `image_base` and `address_space`. A provider that does not +report a base, or whose segments disagree, omits the overview field, following +the existing contract on main. REA does not substitute zero or the first +segment's address. All reported bases and address spaces remain visible in the +complete segment inventory, including conflicting observations. + +`function` and most MCP procedure selectors use procedure names or +provider analysis addresses. Ghidra `decompile` / MCP `procedure_pseudo_code` +also accept source-file byte offsets. Existing symbols and analysis addresses +take precedence; a `0x`-prefixed number that resolves to no procedure falls back +to its observed source mapping. Use `--file-offset=0x...` on the CLI or +`procedure: "file-offset:0x..."` through MCP to select file coordinates explicitly. +Multiple mapping candidates fail as ambiguous rather than selecting a bank or +address space. A successful conversion retains the file offset, mapped address +and procedure entry in raw Evidence and `locations`. + +If an offset maps to loaded target bytes but no procedure starts at or contains +the mapped address, the failure preserves both the original file offset and +analysis address. This differs from an unmapped offset and does not recommend +retrying the same offset syntax. +If the function resolves but the backend fails or cancels decompilation, the +failure retains the selector, mapped address and procedure entry without +changing the backend failure code. + +Both mapping directions require a complete original `FileBytes` source whose +SHA-256 matches the admitted target. Auxiliary files and partial source objects +remain visible in the load-image inventory but do not establish offsets in the +original target. Ghidra's object-local offsets are not silently treated as +original-file coordinates. Original-source identity is checked once per source +object per session; analysis-memory edits do not change the original bytes. + +ELF virtual addresses and file offsets are +different coordinates. Ghidra can rebase a PIE ELF during import: in the +source-owned verification fixture, ELF entry `0x1013` becomes Ghidra procedure +`0x101013` with image base `0x100000`. That example is not a general conversion +rule. + +Use `list_procedures` to select an observed procedure address. To relate file +bytes to loaded memory, call MCP `inspect_native_load_image` or: + +```sh +rea search . --kind procedures --mode regex --provider ghidra --json +rea inspect-native-load-image --provider ghidra --json +rea decompile --provider ghidra --json +rea decompile --file-offset=0x1013 --provider ghidra --json +rea address-to-file-offset --provider ghidra --json +``` + +The load-image result preserves source-file indexes, file offsets, address +spaces, and inclusive mapping ranges. Follow the mapping for the selected +source file and region; adding `image_base` to an arbitrary file offset is not +valid. For a linear byte-addressed, file-backed mapping, a file offset `F` in +`[mapping.file_offset, mapping.file_offset + mapping.length)` maps to +`mapping.start + (F - mapping.file_offset)` in the reported `address_space`. +If several mappings cover the same file offset, keep those candidates distinct +and select the procedure from the observed inventory. Uninitialized regions may +have no file backing. ELF mappings are observed +without independent format-specific load-image verification, as the result's +status and limitations state. + +An unsuccessful numeric procedure lookup reports the current Ghidra image base +and gives the CLI commands above alongside the corresponding MCP operations. +Repeat any target-format, architecture, and entry-point options used to open the +target. Other procedure operations keep their analysis-address semantics; +file-offset fallback applies only to decompilation. + +Overview workflow revision 3 binds this output to snapshot identity. Older +serialized overview Evidence remains readable; it is not replayed as a current +overview merely because its source artifact is unchanged. + ## Admitted function-analysis semantics | Concern | Ghidra contract | diff --git a/docs/providers/ghidra-riscv.md b/docs/providers/ghidra-riscv.md index 6be9394ea..931836c72 100644 --- a/docs/providers/ghidra-riscv.md +++ b/docs/providers/ghidra-riscv.md @@ -22,16 +22,16 @@ header declarations, not proof that every instruction conforms to that ISA. Provider selection returns the specific unsupported constraint rather than guessing a compatible profile: -| Declaration | Outcome | -| ----------------------------------------------- | --------------------------------------------------------------------------- | -| Little-endian ELF64 `ET_EXEC`, double-float ABI | admitted, `RISCV:LE:64:default` + `gcc` | -| Little-endian ELF32 `ET_EXEC`, double-float ABI | admitted, `RISCV:LE:32:default` + `gcc` | -| Big-endian | refused; Ghidra 12.1.4 ships no big-endian RISC-V language | -| `ET_REL`, `ET_DYN`, other `e_type` | refused with the declared value | -| `EF_RISCV_RVE` | refused; the embedded 15-register ABI needs its own processor specification | -| `EF_RISCV_TSO` | refused; the total-store-order memory model is unverified here | -| Soft, single, or quad float ABI | refused; the pinned generic compiler specification models double-float | -| Reserved or newer `e_flags` bits | refused with the offending bits named | +| Declaration | Outcome | +| ----------------------------------------------- | ---------------------------------------------------------------------------------------- | +| Little-endian ELF64 `ET_EXEC`, double-float ABI | admitted, `RISCV:LE:64:default` + `gcc` | +| Little-endian ELF32 `ET_EXEC`, double-float ABI | admitted, `RISCV:LE:32:default` + `gcc` | +| Big-endian | refused; Ghidra 12.1.4 ships no big-endian RISC-V language | +| `ET_REL`, `ET_DYN`, other `e_type` | refused with the declared value | +| `EF_RISCV_RVE` | refused; the embedded 16-register profile (x0–x15) needs its own processor specification | +| `EF_RISCV_TSO` | refused; the total-store-order memory model is unverified here | +| Soft, single, or quad float ABI | refused; the pinned generic compiler specification models double-float | +| Reserved or newer `e_flags` bits | refused with the offending bits named | `e_type` is the only load-shape declaration this lane reads. A fixed-address `ET_EXEC` declaration does **not** establish static linkage: `PT_INTERP` and diff --git a/docs/providers/ida-provider.md b/docs/providers/ida-provider.md index fe68c5d22..4384496b1 100644 --- a/docs/providers/ida-provider.md +++ b/docs/providers/ida-provider.md @@ -138,6 +138,8 @@ Run `npm run verify:ida -- --target /absolute/path/to/program --procedure main` Native verification requires `--second-procedure other_function --second-marker unique_second_body_text`; these options remain optional for the other profiles. The marker must occur in the second function's pseudocode and be absent from the first; the verifier also checks that returning to the first restores its text. +The verifier requires the resolved procedure in both inventory and procedure search, then compares address, assembly, pseudocode, instruction windows and relationship results with the CLI/MCP dossier. Supply `--expected-string known_literal` to check a known positive string inventory/search result and `--expected-xref 0xSOURCE` to check a known reference source address. Choose those oracles independently from the operation under test. Without them, string and xref correctness are listed in `unverified`; valid output shapes alone do not establish those behaviors. Callee parity does not independently establish semantic completeness. Native callee successes must report an explicit truncation marker; missing markers remain protocol failures. + The initial real workflows use stdio registrations for the legacy Windows GUI profile and a Windows x64 headless supervisor with IDA 9.3. The headless workflow has also passed on macOS arm64 with IDA Professional 9.1 (build 9.1.250226) against the same upstream commit `c133c3853faa111a9b00ee615c013b720d0c4acd`, using a source-built arm64 Mach-O fixture; Mach-O C symbols carry a leading underscore, so the procedure name is `_rea_fixture_add`. Streamable HTTP is tested against a loopback MCP fixture with the pinned client SDK; a real IDA HTTP-supervisor workflow remains unverified. Linux headless engine operation, other IDA releases, architectures, and modern attached GUI tools require their corresponding real workflows before support is claimed. Native Windows verification uses IDA Pro 9.3 with the public two-function fixture and Windows `whoami.exe`, using upstream `c9d15d98e8a143fc74f6e14037c48f63889b6d6c` with a loopback-listener change. It covers production CLI/MCP parity, distinct-function switching, identity and connection cleanup. See the [correctness and performance measurements](https://github.com/morluto/rea/blob/main/experiments/analysis-efficiency/ida-native-windows.md). This follow-up did not run Windows IDA Free or native macOS. diff --git a/docs/providers/raw-binary.md b/docs/providers/raw-binary.md index 43fcd54f4..8e277568b 100644 --- a/docs/providers/raw-binary.md +++ b/docs/providers/raw-binary.md @@ -61,7 +61,7 @@ Independent raw verification streams the complete private snapshot digest and extent with bounded memory and supports cancellation during the read. Hopper and IDA refuse raw-binary targets. Windows Ghidra P0 continues to admit -PE applications only. +native PE applications and DLLs only; raw-binary targets are unsupported. ## Limitations diff --git a/docs/providers/windows-ghidra-p0.md b/docs/providers/windows-ghidra-p0.md index 8fa9e125d..a569be793 100644 --- a/docs/providers/windows-ghidra-p0.md +++ b/docs/providers/windows-ghidra-p0.md @@ -153,8 +153,12 @@ the private runtime, isolating Ghidra preferences, logs, and caches. Process creation assigns a suspended child atomically to an owned Job Object. Membership and kill-on-owner-close policy are verified before resume. Breakaway is disabled. Only the child's default file owner is normalized; -the caller token stays unchanged. Caller CPU affinity and priority are -preserved. Close, cancellation, timeout, startup failure, and provider failure +the caller token stays unchanged. Caller priority is preserved, and caller CPU +affinity whenever the caller and the child share a processor group. A child that +Windows places in another group keeps that group's default when the caller asked +for no bound of its own; a caller pinned to fewer processors than its group +holds is refused there rather than widened. +Close, cancellation, timeout, startup failure, and provider failure terminate the job and verify all members have settled before runtime cleanup. Cleanup removes admitted objects by handle and unlinks reparse entries without following their targets. Abrupt owner death kills the job but can leave diff --git a/docs/reference/mcp-contracts.md b/docs/reference/mcp-contracts.md index 766510cfb..f230b7ecb 100644 --- a/docs/reference/mcp-contracts.md +++ b/docs/reference/mcp-contracts.md @@ -21,6 +21,12 @@ directly to `compare_functions`, and `inspect_artifact` Evidence to `compare_artifacts`. Use `get_evidence_bundle` when the task needs broader retained session history or an explicit bundle for transfer. +Evidence and bundle imports reject unsupported fields in their envelopes, +identities, manifests and other fixed metadata before authentication. Imports +leave retained session state unchanged when validation fails. Keep application +metadata in the supported JSON payloads (`parameters`, `raw_result`, +`normalized_result`, or analysis-profile parameters), where keys are preserved. + Tool execution failures return `isError: true` and the complete canonical `{ "error": ... }` diagnostic as JSON in text `content`. Read that diagnostic for the error code, target details, partial observations, and remediation. @@ -141,8 +147,8 @@ after target content was read. ## Retained application Evidence inputs -`analyze_javascript_application`, `inspect_binary_layout`, `inspect_artifact`, and -`inspect_wasm_artifact` accept `detail`: +`analyze_javascript_application`, `inspect_binary_layout`, `inspect_artifact`, +`inspect_wasm_artifact`, and `inspect_macho` accept `detail`: `complete` (default) returns the complete analysis Evidence; `summary` records that complete Evidence in the session and returns the derived `inspect_analysis_view` summary Evidence instead. Its @@ -212,6 +218,19 @@ attempting oversized delivery, and returns the same summary with an exact `parent_evidence_id` for later export or facet reads. Delivery detail does not reach WABT or change the original source Evidence ID. +Completed `inspect_macho` Evidence supports a summary and +`view: {kind: "macho", facet: "exports", offset: 0, limit: 64}`. Facets are +`entrypoints`, `architectures`, `build_metadata`, `load_commands`, +`dependencies`, `imports`, `exports`, `segments`, and `provenance`; pages return +the original rows. The summary keeps the selected slice, header fields and UUID, +and replaces each collection with its returned count, reported total and +`exhaustive` flag. Each page repeats the paged collection's `source_total` and +`source_exhaustive`; exhausting a non-exhaustive collection does not establish +that unreturned symbols are absent. Large frameworks return megabytes of +symbols (Electron Framework: 2.5 MB of imports and exports, 3.3 KB as a +summary), so select `detail: "summary"` on the first call. Delivery detail +never reaches the native tools or changes the source Evidence ID. + `trace_application_feature`, `trace_javascript_semantics`, `compare_application_versions`, `compare_source_to_bundle`, and `compare_javascript_export_shapes` accept complete inline application Evidence diff --git a/experiments/analysis-efficiency/README.md b/experiments/analysis-efficiency/README.md index e41e6b7df..5f656a02c 100644 --- a/experiments/analysis-efficiency/README.md +++ b/experiments/analysis-efficiency/README.md @@ -7,6 +7,18 @@ JSON measurements belong outside the checkout. This document keeps the measured findings, verification scope and revision references; the scripts and `corpus.json` keep the reproduction inputs. Generated `results/` is ignored. +Follow-up: [latest-main capability audit](latest-main-audit.md) records the +Flutter, SQLite, TShark and sigrok priorities and the first shipped Dart AOT +baseline, preserving existing controls before introducing another selector. + +Follow-up: [Dart AOT summary and retained string pools](flutter-aot-summary.md) +records real LocalSend delivery pairs and old Evidence continuation, preserving +ABI selection, snapshot identity, original lower bounds and partial coverage. + +Follow-up: [SQLite existing-control measurements](sqlite-existing-controls.md) +tests QGIS's shipped GeoPackage through the existing column selection, preserving +full selected-table schema and typed cells before considering another API. + Follow-up: [native PE/DOS entry views and real model verification](native-entry-views.md) records the post-merge native continuation, including a small-function case where four selected replies cost more bytes than the complete dossier. @@ -32,6 +44,20 @@ records two shipped assembly checks, previous-runtime portable Evidence, and fou actual Codex trials. Selected replies shrink substantially; observed model input tokens increase and latency is mixed, so model-token savings are not claimed. +Follow-up: [model tool context and per-response usage](model-context.md) separates +raw MCP replies from observed client execution/discovery and usage. Optional +trial capture retains tool/usage items while excluding account and ambient state; +existing ephemeral trials keep their default behavior. + +Follow-up: [Android package delivery and retained manifest](android-package-summary.md) +records real NewPipe SDK pairs, unchanged old requests/Evidence, exact retained +text, and actual Codex outcomes including client errors and a failed discovery. +Reply bytes fall; model-token/time gains are not established. + +Follow-up: [resource counters at payload completion](resource-counters.md) adds +optional owned counter observations while preserving unknown whole-scope final +counters, default receipt shape and the unchanged CPU/memory safeguards. + The 12 detailed checkpoint receipts were archived byte-for-byte before removal from the final PR tree. The archive `review-receipts-00d51e0fc-20261012` is in the private experiment lab outside the checkout; its `archive-index.json` records diff --git a/experiments/analysis-efficiency/agent-trial.py b/experiments/analysis-efficiency/agent-trial.py index 8392000ca..6dcc7d7f8 100644 --- a/experiments/analysis-efficiency/agent-trial.py +++ b/experiments/analysis-efficiency/agent-trial.py @@ -11,6 +11,8 @@ import subprocess import tempfile import time +from codex_context import capture_tool_context + def file_digest(path): digest = hashlib.sha256() @@ -48,7 +50,20 @@ def main(): parser.add_argument('--providers', type=Path) parser.add_argument('--enabled-tools', type=Path) parser.add_argument('--authority', choices=['static', 'browser'], default='static') + parser.add_argument('--capture-tool-context', action='store_true', + help='Retain owned tool/usage items; excludes account/ambient state') + parser.add_argument('--guide-enabled-tools', action='store_true', + help='Opt-in exact-name discovery guidance for selected REA tools') args = parser.parse_args() + if args.guide_enabled_tools and args.enabled_tools is None: + parser.error('--guide-enabled-tools requires --enabled-tools') + enabled_tools = None + if args.enabled_tools: + enabled_tools = json.loads(args.enabled_tools.read_text()) + if not isinstance(enabled_tools, list) or not all(isinstance(name, str) and name for name in enabled_tools) or len(enabled_tools) != len(set(enabled_tools)): + raise ValueError('enabled-tools must be a unique list of exact tool names') + if args.guide_enabled_tools and not enabled_tools: + parser.error('--guide-enabled-tools requires a nonempty selected tool list') def terminate(signum, _frame): # The outer resource scope terminates descendants together. Ensure the # runner's copied credentials are also removed on a resource abort. @@ -130,11 +145,14 @@ def main(): 'possible and select the requested normalized_result fields before returning ' 'intermediate output to model context. Keep real Evidence IDs and limitations.' ) - enabled_tools = None - if args.enabled_tools: - enabled_tools = json.loads(args.enabled_tools.read_text()) - if not isinstance(enabled_tools, list) or not all(isinstance(name, str) and name for name in enabled_tools) or len(enabled_tools) != len(set(enabled_tools)): - raise ValueError('enabled-tools must be a unique list of exact tool names') + if args.guide_enabled_tools: + instruction += ( + ' Configured REA tool function names for this trial: ' + + json.dumps(['mcp__rea__' + name for name in enabled_tools]) + + '. For discovery select only these exact names from ALL_TOOLS and ' + 'return only their metadata. Preserve the original analyst question, ' + 'dependency order and source Evidence.' + ) quote = json.dumps config = '\n'.join([ 'approval_policy = "never"', 'sandbox_mode = "read-only"', @@ -160,6 +178,7 @@ def main(): 'inspect_android_package', 'search_android_classes', 'inspect_android_class', 'inspect_android_method', 'inspect_firmware_regions', 'inspect_managed_artifact', + 'inspect_sqlite_database', 'inspect_managed_members', 'inspect_managed_native_boundaries', 'inspect_artifact', 'inspect_wasm_artifact', 'inspect_evm_interface', 'get_evidence_bundle', 'export_evidence_bundle', @@ -183,6 +202,8 @@ def main(): (args.output / 'prompt.txt').write_text(prompt) (args.output / 'trial-settings.json').write_text(json.dumps({ 'mode': args.mode, 'model': args.model, 'reasoning': args.reasoning, + 'capture_tool_context': args.capture_tool_context, + 'guide_enabled_tools': args.guide_enabled_tools, 'driver_commit': subprocess.check_output( ['git', 'rev-parse', 'HEAD'], cwd=driver_repository, text=True).strip(), 'runtime_revision': args.revision, @@ -196,7 +217,7 @@ def main(): 'package_lock_sha256': file_digest(repository / 'package-lock.json'), 'experiment_sources_sha256': { name: hashlib.sha256((experiment / name).read_bytes()).hexdigest() - for name in ['agent-trial.py', 'provider-environment.json'] + for name in ['agent-trial.py', 'codex_context.py', 'provider-environment.json'] }, 'developer_instructions': instruction, 'developer_instructions_sha256': hashlib.sha256(instruction.encode()).hexdigest(), @@ -212,7 +233,8 @@ def main(): 'multi_agent': False, 'code_mode': args.mode == 'client-code', 'code_mode_only': args.mode == 'client-code'}, }, indent=2) + '\n') - invocation = [args.codex, '--no-daemon', 'exec', '--strict-config', '--ephemeral', + invocation = [args.codex, '--no-daemon', 'exec', '--strict-config', + *([] if args.capture_tool_context else ['--ephemeral']), '--skip-git-repo-check', '--ignore-rules', '--json', '--color', 'never', '-C', str(workspace), '--output-last-message', str(args.output.resolve() / 'answer.txt'), '-'] @@ -234,26 +256,28 @@ def main(): usage = [] tools = [] event_types = {} - for line in (args.output / 'events.jsonl').open(): - if not line.strip(): - continue - event = json.loads(line) - kind = event.get('type', 'unknown') - event_types[kind] = event_types.get(kind, 0) + 1 - if 'usage' in event: - usage.append(event['usage']) - item = event.get('item', {}) - if item.get('type') == 'mcp_tool_call' and kind == 'item.completed': - tools.append({ - **{k: item.get(k) for k in ['server', 'tool', 'arguments', 'status', 'error']}, - 'codex_event_result_json_utf8_bytes': len(json.dumps( - item.get('result'), separators=(',', ':'), ensure_ascii=False - ).encode()), - }) + with (args.output / 'events.jsonl').open() as event_file: + for line in event_file: + if not line.strip(): + continue + event = json.loads(line) + kind = event.get('type', 'unknown') + event_types[kind] = event_types.get(kind, 0) + 1 + if 'usage' in event: + usage.append(event['usage']) + item = event.get('item', {}) + if item.get('type') == 'mcp_tool_call' and kind == 'item.completed': + tools.append({ + **{k: item.get(k) for k in ['server', 'tool', 'arguments', 'status', 'error']}, + 'codex_event_result_json_utf8_bytes': len(json.dumps( + item.get('result'), separators=(',', ':'), ensure_ascii=False + ).encode()), + }) final_target_digest = file_digest(Path(args.artifact_path)) if args.artifact_path else None summary = { 'mode': args.mode, 'requested_model': args.model, 'reasoning': args.reasoning, 'runtime_revision': args.revision, + 'capture_tool_context_requested': args.capture_tool_context, 'selected_artifact_sha256_before': target_digest, 'selected_artifact_sha256_after': final_target_digest, 'selected_artifact_bytes_unchanged': target_digest == final_target_digest if target_digest else None, @@ -268,9 +292,13 @@ def main(): (args.output / 'summary.json').write_text(json.dumps(summary, indent=2) + '\n') print(json.dumps(summary)) finally: - # Always remove copied credentials, config, caches and profile state. - shutil.rmtree(profile) - (args.output / 'cleanup.json').write_text(json.dumps({'profile_removed': not profile.exists()}) + '\n') + try: + if args.capture_tool_context: + capture_tool_context(trial_codex_home, args.output) + finally: + # Capture failure must never prevent copied-credential cleanup. + shutil.rmtree(profile) + (args.output / 'cleanup.json').write_text(json.dumps({'profile_removed': not profile.exists()}) + '\n') raise SystemExit(124 if timeout else exit_code) diff --git a/experiments/analysis-efficiency/android-package-summary.md b/experiments/analysis-efficiency/android-package-summary.md new file mode 100644 index 000000000..448202d87 --- /dev/null +++ b/experiments/analysis-efficiency/android-package-summary.md @@ -0,0 +1,166 @@ +# Android package summary and exact retained manifest + +Continues [#2016](https://github.com/morluto/rea/issues/2016) and +[#2438](https://github.com/morluto/rea/pull/2438). The recurring NewPipe question +asks for APK/package/version identity, all case-sensitive MainActivity matches +and all reported onCreate entries, including explicit null DEX descriptors. +Complete package replies delivered decoded manifest text and duplicate upstream +calls unrelated to those selected facts. + +## Compatibility and ownership + +MCP `inspect_android_package` accepts explicit `detail: "summary"`; omitted and +`"complete"` requests preserve the complete output and provider request. The +one-shot CLI stays complete. Summary selection happens in the application +workflow, independently of the engine protocol, using the existing retained +analysis-view machinery. No third-party plugin API or persistent analysis cache +is introduced. Servers lacking retention reject summary before provider work. + +The complete original Evidence stays under its original ID and session lifetime. +A distinct linked derived view returns all package/SDK/permission declarations, +engine identity, class/resource counts and signature-verification status. +Manifest metadata retains the producer's partial/complete status, nullable +reported byte total, and observed UTF-16 length. Text and duplicate raw calls +remain in the original record, rather than being rewritten under its ID. + +Use `inspect_analysis_view` with the parent's ID and +`view: {kind: "android", facet: "manifest", offset: 0, limit: 4096}` to read exact +retained decoded text. Follow `coverage.next_offset`; surrogate boundaries use +the existing text-page implementation. Exhaustion describes the retained text, +not global completeness when the producer says partial. APK signatures and +runtime behavior remain unverified. Engine artifact SHA-256 identifies the JAR; +views require the authenticated APK subject and never substitute the engine +hash for a missing target identity. Older servers require schema discovery and +the original complete request; automatic fallback is not introduced. + +## Frozen runtime and real SDK pairs + +Source runtime: `28c84e78cf2fbfde4aceed345b773c59eb889f68`; later test-only schema +typing corrections do not relabel these receipts. Compiled dist/bridge file-table +SHA-256: `5332dda13981f043e146b3601ebec1f380d9f698280ca53d75786b638a912e11`. +The frozen old runtime is `8bc1601ca51e417ca472d90ea0367e9418a1a0f2`, digest +`9e7380f537301bf0cfe2926f5619011af848af7c220750e75189498e65d825e1`. + +Real NewPipe 0.29.1 bytes, acquisition and digest are pinned in `corpus.json`. +Actual configured JADX headless MCP 0.7.1/Java runs use the same selected +provider settings and search-path digests, one worker and 768 MiB Java heap. +Node is 24.18.0; actual SDK client/server are 2.3.1. Processes and engines are +fresh per trial; host page caches are not flushed. SDK schema mode is selected +in both treatments. Heavy runs are serial, with one CPU, unchanged 3 GiB early +stop/4 GiB hard memory, no swap, and 192 tasks. + +All four candidate workflows use three successful public MCP calls. Only the +first package delivery changes. Both pairs pass settings and selected-fact +comparison, including all declarations, manifest status/length, engine identity, +original limitations, matching class rows and onCreate entries. Original replies +and IDs remain separate. A fresh old-runtime complete workflow also passes +comparison against the candidate complete request; both complete package replies +are exactly 119,527 compact client-result JSON bytes. This is scoped compatibility +evidence, not a guarantee for every historical release/client/host. + +| Trial | Package reply bytes | SDK workflow seconds | Payload CPU seconds | Kernel peak bytes | +| -------------- | ------------------: | -------------------: | ------------------: | ----------------: | +| sdk-complete-1 | 119,527 | 24.059 | 25.259 | 1,225,076,736 | +| sdk-summary-1 | 8,659 | 23.694 | 24.894 | 1,226,870,784 | +| sdk-summary-2 | 8,659 | 24.407 | 25.611 | 1,228,296,192 | +| sdk-complete-2 | 119,527 | 24.509 | 25.740 | 1,229,844,480 | + +Summary replies are 8,659 bytes, about 92.8% smaller; all three replies together +fall from 149,577 to 38,709 bytes. This is a delivery result, not a model-token +or engine-work saving. The SDK timing differences are small. CPU and memory do +not establish a reduction. No provider setting or analysis scope changes. +Transport roundtrip includes server/client work and is not an engine-only timer. + +The complete catalog is 2,506,213 compact JSON bytes versus 2,497,635 on the old +runtime: about 0.34% growth, including intervening main changes. Discovery cost +remains visible alongside selected-delivery savings. + +## Authentic old Evidence continuation + +A real package record from old runtime 8bc160 imports into the candidate and +supports retained summary, exact manifest pages, inline portable summary and +export through actual public SDK tools. The new session explicitly selects an +absent JADX JAR; this workflow performs no package analysis. Eleven successful +calls preserve the original record, original ID, all declarations and all 25,222 +manifest UTF-16 units. Manifest UTF-8 SHA-256: +`fee192fe2a6d7892c22cba115184c74c7e2c42ce464e8bb37be6289f2c16881d`. +The exported original record is deeply equal to the imported record. + +## Actual Codex task outcomes + +Four serial trials run in complete/summary/summary/complete order on the same +frozen candidate. Requested configuration: Codex CLI 0.161.0, `gpt-5.6-terra` high, +three exact selected tool names and the same optional context/discovery capture +settings. The requested alias does not certify the server-resolved model. The +original analyst question is unchanged; equal treatment instructions explicitly +choose package detail and explain the summary carrier. Temporary configuration +points to the frozen modified REA MCP; no global configuration is edited. + +| Trial | Input | Cached | Uncached | Output | Seconds | MCP calls | Usage records | Facts | +| ---------------- | ------: | -----: | -------: | -----: | ------: | --------: | ------------: | ----- | +| model-complete-1 | 39,267 | 23,040 | 16,227 | 1,690 | 94.053 | 3 | 3 | Pass | +| model-summary-1 | 128,417 | 93,440 | 34,977 | 3,633 | 150.401 | 8 | 9 | Pass | +| model-summary-2 | 54,437 | 37,120 | 17,317 | 2,185 | 123.677 | 3 | 4 | Pass | +| model-complete-2 | 21,332 | 9,984 | 11,348 | 667 | 20.774 | 0 | 2 | Fail | + +Three answers pass the original selected-fact gate against the actual SDK +producer. Each trial preserves APK bytes and removes its isolated profile. +The first summary trial makes five successful calls and three rejected requests: +an invented `case_sensitive` argument, empty class-search input and empty +class-inspection input. It then repeats successful package/search work. These +errors and correction turns remain part of measured task cost; strict existing +schemas correctly reject them. The second summary trial uses the intended three +successful calls, but still does not establish improved total/uncached input or +latency against the factually acceptable first complete control. + +The final complete control's first client executor filters `ALL_TOOLS` for the +same three exact names and receives an empty array. It makes zero MCP calls, +reports all requested facts unknown and fails the factual gate. Identical name +filters worked in the other trials. Stderr contains no explanatory error; the +client visibility failure remains unexplained and is not attributed to REA or +summary delivery. Its short duration is not comparable completed work. The +original failed receipt is retained rather than replaced by a successful trial. + +These measurements demonstrate no real-model token or speed gain. Smaller raw +MCP envelopes do not establish smaller model context; observed usage also +includes discovery, execution context, corrections and extra responses. Usage +records count captured usage items rather than asserting exact remote request +contents or equating MCP calls with model rounds. The complete default and +opt-in choice remain unchanged; this is useful delivery/retention capability, +not a general performance recommendation. + +All model runs have verified payload-completion witnesses with only the observer +remaining and zero memory/task limit events at that phase. Kernel peaks are +602,472,448–1,444,945,920 bytes; the failed no-analysis control is included in that +range and is not evidence of lower analysis memory. Whole-scope final counters +remain unknown and the existing full resource grader stays false. No broader +CPU, memory, OS/provider or model claim is made. + +## Resource interpretation + +Every SDK run and portable continuation has a verified owned +payload-exited-observer-alive witness, with only the observer remaining and no +memory/task limit events at that phase. Kernel peak and CPU include that opt-in +observer. Whole-scope terminal counters remain unknown; the existing complete +physical resource grader is not changed or called successful. No OOM stress or +resource-limit increase is used. + +## Verification and scope + +Twenty-seven relevant converted-schema, SDK, domain and existing Android +failure/cancellation/cleanup checks pass. A three-case focused rerun passes after +a test-only schema typing correction. The 1 MiB manifest protocol fixture verifies +original default/full output, reconstruction after source removal, unchanged +exported Evidence and one engine launch. Other cases preserve nulls and partial +status, Unicode boundaries and tagged malformed/missing-identity failures, and +reject unavailable retention or cancelled requests before provider work. These +fixtures verify production boundaries; actual JADX claims use the real NewPipe +runs above. Full supported single-thread compiler and unchanged lint pass under +the same memory safeguards. No other Android OS/device/provider lane is inferred. + +Raw SDK/model replies, private profiles and resource receipts stay outside Git. +Reproduce SDK pairs using the existing `measure.mjs` with `--artifact newpipe.apk`, +`--schemas selected`, identical explicit provider configuration and frozen runtime, +and alternating `--delivery complete` / `--delivery summary`. Preserve failed +attempts and run `compare.mjs` on both pair orders. Model findings require their +own identical analyst facts and explicit delivery controls. diff --git a/experiments/analysis-efficiency/codex_context.py b/experiments/analysis-efficiency/codex_context.py new file mode 100644 index 000000000..cce8bf9cf --- /dev/null +++ b/experiments/analysis-efficiency/codex_context.py @@ -0,0 +1,117 @@ +"""Retain owned Codex tool/usage observations without account or ambient state.""" + +import hashlib +import json +import os + + +def token_counts(value): + if not isinstance(value, dict): + raise ValueError('Expected a token-count object') + result = {} + for key in ['input_tokens', 'cached_input_tokens', 'cache_write_input_tokens', + 'output_tokens', 'reasoning_output_tokens', 'total_tokens']: + if key in value: + count = value[key] + if not isinstance(count, int) or isinstance(count, bool) or count < 0: + raise ValueError('Expected nonnegative integer token counts') + result[key] = count + return result + + +def selected_event(event): + """Select observed items; these are not the exact submitted model request.""" + if not isinstance(event, dict) or not isinstance(event.get('payload'), dict): + raise ValueError('Expected an event object with an object payload') + if not isinstance(event.get('type'), str): + raise ValueError('Expected an event type string') + if event.get('timestamp') is not None and not isinstance(event['timestamp'], str): + raise ValueError('Expected a timestamp string or omission') + payload = event['payload'] + kind = event.get('type') + if kind == 'response_item' and payload.get('type') in [ + 'custom_tool_call', 'custom_tool_call_output', + 'function_call', 'function_call_output', + ]: + keys = ['type', 'call_id', 'name', 'input', 'arguments', 'output'] + elif kind == 'token_usage_record': + keys = ['response_id', 'usage', 'turn_token_usage', 'thread_token_usage'] + payload = {key: token_counts(payload[key]) if key != 'response_id' + else payload[key] for key in keys if key in payload} + elif kind == 'event_msg' and payload.get('type') == 'token_count': + keys = ['type', 'info'] + info = payload.get('info') + if info is not None: + if not isinstance(info, dict): + raise ValueError('Expected token-count info') + selected_info = {key: token_counts(info[key]) for key in + ['total_token_usage', 'last_token_usage'] if key in info} + window = info.get('model_context_window') + if 'model_context_window' in info: + if window is not None and (not isinstance(window, int) or isinstance(window, bool) or window <= 0): + raise ValueError('Expected a positive model context window') + selected_info['model_context_window'] = window + payload = {'type': 'token_count', 'info': selected_info} + else: + payload = {'type': 'token_count', 'info': None} + else: + return None + return { + 'timestamp': event.get('timestamp'), + 'type': kind, + 'payload': {key: payload[key] for key in keys if key in payload}, + } + + +def capture_tool_context(codex_home, output): + """Capture only an explicitly selected trial's rollouts; never its auth/config.""" + sessions = codex_home / 'sessions' + blocked = sessions.is_symlink() + sources = [] if blocked else sorted(sessions.rglob('*.jsonl')) + target = output / 'codex-tool-context.jsonl' + source_receipts = [] + errors = [{'source': 'sessions', 'reason': 'not_an_owned_directory'}] if blocked else [] + retained = 0 + with os.fdopen(os.open(target, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600), + 'w', encoding='utf-8') as result: + for source in sources: + name = source.relative_to(codex_home).as_posix() + if source.is_symlink() or not source.is_file(): + errors.append({'source': name, 'reason': 'not_an_owned_regular_file'}) + continue + digest = hashlib.sha256() + counts = {} + with source.open('rb') as lines: + for ordinal, line in enumerate(lines, 1): + digest.update(line) + try: + event = json.loads(line) + selected = selected_event(event) + except ValueError as error: + errors.append({'source': name, 'line': ordinal, + 'reason': type(error).__name__}) + continue + kind = event.get('type') + counts[str(kind)] = counts.get(str(kind), 0) + 1 + if selected is not None: + result.write(json.dumps(selected, ensure_ascii=False) + '\n') + retained += 1 + source_receipts.append({'source': name, 'sha256': digest.hexdigest(), + 'event_counts': counts}) + retained_digest = hashlib.sha256() + with target.open('rb') as captured: + for chunk in iter(lambda: captured.read(1024 * 1024), b''): + retained_digest.update(chunk) + receipt = { + 'status': 'partial' if errors else 'captured' if source_receipts else 'unavailable', + 'retained_file': target.name, + 'retained_sha256': retained_digest.hexdigest(), + 'retained_events': retained, 'sources': source_receipts, 'errors': errors, + 'scope': 'Owned client tool-call/reply and per-response usage items, not ' + 'the exact submitted model request. Session/account metadata, ' + 'world state, user/developer messages, encrypted reasoning and ' + 'internal passthrough are omitted. Authentication, configuration ' + 'and ambient environment are never copied by this capture.', + } + (output / 'context-receipt.json').write_text(json.dumps(receipt, indent=2) + '\n') + return receipt diff --git a/experiments/analysis-efficiency/corpus.json b/experiments/analysis-efficiency/corpus.json index 540e88cdd..163b3b49a 100644 --- a/experiments/analysis-efficiency/corpus.json +++ b/experiments/analysis-efficiency/corpus.json @@ -235,6 +235,34 @@ }, "immutable_scope": "Published Hardhat artifact does not record an immutable-reference map; absence is unknown, not proof of no immutables. Runtime template bytes remain exact." } + }, + { + "id": "localsend-arm64.apk", + "file": "LocalSend-1.18.2-android-arm64v8.apk", + "bytes": 46558706, + "sha256": "82ec3568fba2aa5295b9aae8b76f701d7a4703d86b9f8bad749472038fbaeab3", + "provenance": { + "project": "LocalSend", + "version": "1.18.2", + "upstreamFile": "LocalSend-1.18.2-android-arm64v8.apk", + "url": "https://github.com/localsend/localsend/releases/download/v1.18.2/LocalSend-1.18.2-android-arm64v8.apk", + "transport_sha256": "82ec3568fba2aa5295b9aae8b76f701d7a4703d86b9f8bad749472038fbaeab3", + "transport_bytes": 46558706, + "derivation": "Official arm64 release APK, compared with GitHub release asset digest; byte-only analysis without execution" + } + }, + { + "id": "qgis-world-map.gpkg", + "file": "qgis-world-map.gpkg", + "bytes": 12914688, + "sha256": "01d293159d1b77bd9212b5252587853f61aa9e25b2387135f34afaba8d057190", + "provenance": { + "project": "QGIS bundled world map", + "source_commit": "e1223b8e9e71fc50ee995ed556f711c54ccc101b", + "git_blob_sha1": "c9ff80228dff0de93c9acdef16a97545ba360244", + "url": "https://raw.githubusercontent.com/qgis/QGIS/e1223b8e9e71fc50ee995ed556f711c54ccc101b/resources/data/world_map.gpkg", + "derivation": "unmodified official resource file; streaming Git blob and SHA-256 verification" + } } ] } diff --git a/experiments/analysis-efficiency/evm-descriptor.md b/experiments/analysis-efficiency/evm-descriptor.md index 8e3611f28..0fcdf4d44 100644 --- a/experiments/analysis-efficiency/evm-descriptor.md +++ b/experiments/analysis-efficiency/evm-descriptor.md @@ -179,3 +179,40 @@ interface question through an explicitly selected precise view, retain full bytecode/original Evidence under the existing lifetime, and preserve complete defaults. Discover support before sending new options to an older server. Include discovery, follow-up, failures and retries in the complete task cost. + +## Static contract admission verification + +The follow-up from main `c462a4ebd3a10e59253bcf38353a0914b176738b` tests the +pilot's actual static boundary, without adding a dynamic module registry or +changing production code. Complete-project TypeScript checking now verifies +that the inferred descriptor type rejects a WASM operation contract, a WASM +CLI command, a WASM service factory, an unrelated input schema and an unrelated +output schema. These are negative assignability assertions: their guarantee +comes from the compiler, not from executing an incompatible descriptor. +The existing named contract and CLI identity are also checked at runtime; +separate factory calls produce distinct service/provider owners. Invalid target +input remains an application error without launching a worker. + +The actual public in-memory MCP SDK test additionally spies on the provider: +duplicate EVM registration throws the named `already registered` error before +any provider call. Converted input/output JSON Schemas validate before the +first valid operation. Invalid client arguments are rejected before execution; +incompatible provider reply data is validated **after** execution and is not +presented as a pre-use contract guarantee. Existing healthy-peer, cancellation, +retained summary/default and cleanup-retry scenarios remain covered. + +Full project typecheck passes with the installed compiler's supported single +thread scheduling; it includes all source/test files. The two exact focused +files pass 12 runtime cases. The resource scopes sample 2,057,961,472 bytes for +typecheck and 2,426,290,176 bytes for required build plus focused tests, below the +unchanged 3 GiB early-stop/4 GiB hard ceiling. Final transient-cgroup counters +remain unknown. No new real-provider or performance improvement is claimed by +these compile/SDK checks; the earlier pinned real EVMole/WABT/lifecycle evidence +retains its original scope and source identity. + +This proves the one statically composed descriptor's named/schema/factory +compatibility and duplicate-registration guard. It does not implement runtime +admission of arbitrary JavaScript descriptors, third-party plugin ABI/version +negotiation or a general plugin SDK. Those remain deferred by the original plan. +Existing callers, full defaults, provider inputs, owned lifetimes and output +identities are unchanged. diff --git a/experiments/analysis-efficiency/flutter-aot-summary.md b/experiments/analysis-efficiency/flutter-aot-summary.md new file mode 100644 index 000000000..8893cd917 --- /dev/null +++ b/experiments/analysis-efficiency/flutter-aot-summary.md @@ -0,0 +1,160 @@ +# Dart AOT summary and retained string pools + +Continues [#2016](https://github.com/morluto/rea/issues/2016) and +[#2455](https://github.com/morluto/rea/pull/2455). The selected analyst question +asks for shipped LocalSend target/ABI/library identity, every nullable snapshot +observation, string-pool lower bounds and returned counts, and original coverage +and limitations. It does not require individual observed strings. + +## Compatibility and ownership + +MCP `inspect_dart_aot` accepts explicit `detail: "summary"`. Omitted and complete +requests preserve the complete result and original provider inputs. The CLI +remains complete. ABI omission and explicit ABI selection retain their original +meaning; the provider never receives the delivery field. Missing retention, +invalid detail and pre-cancellation fail before provider work. + +The existing application workflow retains the complete original Evidence, then +returns a distinct derived summary linked to its parent ID. It preserves target +and libapp digests, every snapshot section and nullable fact, original pool and +overall coverage, lower-bound counts and limitations. `returned_counts` reports +the lengths of the producer-returned arrays; it does not upgrade lower bounds +to a complete snapshot inventory. The analysis and original source retention +are unchanged. No new engine, persistent cache or plugin SDK is introduced. + +Read exact retained strings using `inspect_analysis_view`, the parent ID, and +`view: {kind: "dart-aot", collection: "package_uris", offset: 0, limit: 64}`. +Other collections are `dart_uris` and `class_like_tokens`. Follow the returned +next offset. Pages preserve source order, ABI/library identity and partial pool +coverage without opening the APK again. Page exhaustion describes retained +strings, not the entire snapshot. Strings remain byte-pattern observations, +rather than recovered typed class/function semantics. Missing historical +subjects remain explicitly unknown; conflicting recorded target digests fail. + +## Frozen runtime and real SDK pairs + +The official LocalSend 1.18.2 arm64 APK acquisition, size and SHA-256 are pinned +in `corpus.json`. No APK installation, target execution or version-dataset +lookup occurred. Source runtime: `811034a7283c9751a3ecbff33e8b2f28bec55793`; +compiled dist/bridge file-table SHA-256: +`dabbb63536c5862be839ecdc0f3eaad05b29c2a3816f57041528d30f754311be`. +The previous runtime is `28c84e78cf2fbfde4aceed345b773c59eb889f68`, digest +`5332dda13981f043e146b3601ebec1f380d9f698280ca53d75786b638a912e11`. +Its production sources were verified byte-equal to main f254 at acquisition. +Subsequent test-only changes and main's SAZ addition do not relabel these pins. + +Node is 24.18.0 and the SDK client/server are 2.3.1. Each workflow starts a fresh +server and validates the selected live advertised schema. Artifact bytes, +provider environment/search-path fingerprints, driver and locked dependencies +stay equal. Host page caches are not flushed. Heavy tasks run serially under +the unchanged CPU, memory, task and host guards. + +| Trial | AOT reply bytes | SDK workflow seconds | Payload CPU seconds | Kernel peak bytes | +| -------------- | --------------: | -------------------: | ------------------: | ----------------: | +| sdk-complete-1 | 151,341 | 5.139 | 6.819 | 691,441,664 | +| sdk-summary-1 | 12,037 | 5.219 | 6.608 | 639,430,656 | +| sdk-summary-2 | 12,037 | 5.064 | 6.405 | 640,868,352 | +| sdk-complete-2 | 151,341 | 5.128 | 6.468 | 633,614,336 | + +Both pairs use one successful public tool call and pass settings/fact comparison, +including all snapshot fields, coverage, original limitations and all counts. +Reply bytes fall 92.05%. Whole SDK time stays approximately 5.1 seconds; these +trials do not establish engine speed, CPU or memory savings. Payload CPU includes +driver/catalog work beyond the SDK workflow timer. Catalog JSON grows from +2,506,213 bytes on the previous runtime to 2,514,896 (about 0.35%). + +A fresh old-runtime complete request passes comparison against candidate +complete, including identical 151,341-byte replies. This is scoped compatibility +evidence, not a guarantee for every historical release or third-party client. + +## Real old Evidence continuation + +Fifteen successful public MCP calls import genuine old-runtime AOT Evidence, +project retained summary, reconstruct all 500 package URIs, 216 Dart URIs and +2,000 class-like tokens, compare inline portable summary, and export the original +record. The APK is absent during all these operations. Original string order, +lower bounds, partial coverage, nullable snapshot facts, subject and parent ID +remain intact; the original exported record is deeply equal to its source. + +The first private verification attempt used a nonexistent receipt filename and +failed before import or artifact relocation. That driver error is retained; +the corrected attempt selects the fresh old-runtime record. It is not a REA +defect or a successful migration trial. + +## Actual Codex task outcomes + +Four serial trials use the same frozen candidate in complete/summary/summary/ +complete order. Requested configuration is Codex CLI 0.161.0, `gpt-5.6-terra` +high, one exact enabled tool (`inspect_dart_aot`), and identical optional owned +context capture/discovery guidance. This requested alias does not certify the +server-resolved model. Temporary configuration points to the modified frozen +REA MCP; all copied credential profiles are removed and target bytes remain +unchanged. The source question is fixed; equal treatment instructions choose +detail and explain the summary carrier and parent reference. + +| Trial | Input | Cached | Uncached | Output | Seconds | MCP attempts | Failed attempts | Facts | +| ---------------- | -----: | -----: | -------: | -----: | ------: | -----------: | --------------: | ----- | +| model-complete-1 | 74,641 | 50,176 | 24,465 | 2,765 | 116.898 | 3 | 1 | pass | +| model-summary-1 | 38,253 | 22,016 | 16,237 | 1,449 | 88.904 | 1 | 0 | pass | +| model-summary-2 | 38,363 | 22,016 | 16,347 | 1,515 | 55.190 | 1 | 0 | pass | +| model-complete-2 | 66,585 | 38,144 | 28,441 | 2,217 | 79.180 | 2 | 0 | pass | + +Both pairs pass checks for every selected producer fact, exact nullable +observations, target digest, observed response Evidence IDs, original limitations, +artifact preservation and profile cleanup. The grader compares the reported +facts with producer observations; it is not an independent Dart deserializer. +Total input falls 48.75% / 42.38%, uncached input 33.63% / 42.52%, reported output +47.59% / 31.66%, and whole-task time 23.95% / 30.30%. Usage is the final aggregate +reported by the actual CLI, one usage record per trial; cached tokens are not +subtracted from total input. Reported output includes reasoning output (1,262, +321, 383 and 709 tokens respectively). + +The first complete trial initially supplied `artifact_path` instead of the +advertised `path`, corrected it, then repeated a successful complete call. +The second complete trial made two successful calls. Both summary trials made +one successful call. All attempts, discovery and correction costs remain +included. The paired whole-task improvement therefore includes actual model +decisions and the convenience of explicit returned counts; it does not isolate +serialization as the sole cause or establish engine acceleration. Two pairs on +one app/question/model configuration support this scope, not a universal gain. + +Payload CPU seconds / kernel peak bytes are respectively 12.556 / 876,937,216; +9.213 / 785,272,832; 9.108 / 793,939,968; and 13.164 / 803,209,216. Model payload +observations verify owned cleanup and zero phase limit events, with no guard +aborts. Whole-scope final counters remain unknown, so every strict all-selected +resource grade remains false even though the separate factual grade passes. + +## Resource and verification scope + +SDK and migration payload-exit observations verify owned cleanup and zero +observed memory/pids limit events, with peaks below 692 MB. Missing whole-scope +terminal counters remain unknown; the strict whole-resource grader stays false. +One-CPU quotas are experiment controls rather than CPU-efficiency claims. + +Production-provider fixture tests cover explicit ABI, old complete defaults, +actual SDK-converted schemas, exact pages after APK removal, portable records, +nullable/partial facts, malformed inputs, target digest conflicts and early +refusals. CLI/MCP acceptance covers original report equality, duplicate-member +refusals and unsupported snapshot kinds. Fixture successes are distinguished +from the real LocalSend SDK/migration workflows. Other Flutter apps, architectures, +SDK layouts, typed class recovery and runtime behavior remain unverified here. +Raw replies, binaries, model traces and temporary credentials stay outside Git. + +## Integration with the newer main + +The rebased verification runtime is `63984ce0898bd7997e6d9b138e6d96d0a24f2b09` +on main `a2d8b94dd50dab8d966239dd63ab84718aa8b4b4`, with compiled file-table +SHA-256 `19c8ccdd3e99bb46a5c54f4edd8c6b2d2eb4f3a4870b3c129061d38145382b68`. +Targeted Flutter/SAZ/shared-view integration passes 35 tests; one opposite +runtime-capacity branch is skipped because this host enforces decoder memory. +Documentation checks and two README conformance tests pass. + +Fresh real complete/summary SDK checks on this runtime match the earlier selected +facts and settings, with unchanged 151,341 / 12,037-byte AOT replies. Fifteen +old-Evidence migration calls again preserve every original string and record +with the source APK absent. The real one-shot CLI complete result also matches +the previous-runtime normalized report, subject, parameters and original ID. +An initial CLI-only controller check lacked an owned resource receipt; it is +retained and excluded from resource/performance claims, then repeated in the +bounded owned scope. These checks establish integration, rather than relabeling +the earlier paired model/SDK measurements as the rebased runtime. diff --git a/experiments/analysis-efficiency/ida-native-windows.md b/experiments/analysis-efficiency/ida-native-windows.md index 835662fc4..9adbd2143 100644 --- a/experiments/analysis-efficiency/ida-native-windows.md +++ b/experiments/analysis-efficiency/ida-native-windows.md @@ -23,6 +23,25 @@ connecting. Dossier relationship coverage remains unknown when direct callers are unavailable, while standalone callee coverage retains its own observed state. It preserves the attached GUI database. +The later verification follow-up rejects native callee successes without an +explicit truncation marker, checks positive procedure inventory/search and +compares normalized function results. String and xref correctness require +independent positive oracles; runs without those oracles label them unverified. +Earlier reports established contract validity for these operations and did not +by themselves establish string/xref semantic correctness. + +The follow-up passed eight production checks with a known CRT literal confirmed +in the unchanged fixture bytes and a reference source address independently +identified from `main` assembly matching the C source. A loopback response-only +proxy in front of the real IDA Pro provider reproduced the earlier verifier +passing empty function inventories and xrefs. The corrected verifier rejected +those replies with positive oracles, empty string results and missing native +callee truncation markers. The comparison used verifier source `d1aaeee40` +with the same current adapter runtime; it is a verifier comparison, not an +engine performance comparison. Only response payloads were modified; the original +input digest stayed unchanged, the target was never executed, and the attached +GUI database was preserved. + The real application was a digest-verified, unchanged copy of Windows `whoami.exe`: 94,208 bytes, 243 recognized functions, and 314 upstream C-string observations. The selected 1,741-byte function had 20 resolved diff --git a/experiments/analysis-efficiency/latest-main-audit.md b/experiments/analysis-efficiency/latest-main-audit.md new file mode 100644 index 000000000..8f767fb64 --- /dev/null +++ b/experiments/analysis-efficiency/latest-main-audit.md @@ -0,0 +1,75 @@ +# Latest-main efficiency continuation + +Continues [#2016](https://github.com/morluto/rea/issues/2016). The 2026-10-13 +fetch resolved main to `f254f5ac2b804b353a711264bb178f43fdf07867`, the same +revision as the preceding Android conclusion. Newer capabilities below were +added during that earlier cycle; they are additional measurement scopes, not +new commits after that conclusion. + +| Capability | Existing controls | Next evidence needed | +| ----------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Flutter / Dart AOT (#1582) | Explicit ABI, bounded string observations, partial coverage | Real shipped snapshot/count question; opt-in delivery only if unrelated strings dominate | +| SQLite (#2271) | Compact inventory, selected table/columns, row limit | Real application database and model workflow before adding another selector | +| TShark (#2318) | Fields, filter, decode-as, pass, default 50 matching rows, paging, explicit null for all | Real public capture and repeated task cost; paging repeats dissection | +| sigrok (#2339) | Decoder/channels/annotation selection, default 50 display lines, paging | Real public capture; display-line count is not annotation count and paging repeats decoding | +| Retained unknown head results | Existing retained paging | Reuse the existing view rather than duplicate its implementation | + +Attached IDA, Frida and other live runtime workflows involve separate authority +and lifecycle questions and are outside this static parsing continuation. +Plugin SDKs and cross-session engine caches remain deferred until an observed +need and benefit justify them. + +## First selected scope: Dart AOT + +The official LocalSend 1.18.2 arm64 APK is pinned in `corpus.json`. The initial +real public SDK baseline inspected actual bytes without executing/installing +the APK. Its complete default AOT reply was 151,341 compact client-result JSON +bytes (70,487 normalized bytes), with 500 package URIs, 216 Dart URIs and 2,000 +class-like tokens. String-pool and overall coverage were partial. A second +explicit arm64 request returned the same normalized facts. + +These are exploratory first/warm calls, not an optimization pair. The frozen +runtime source is `28c84e78cf2fbfde4aceed345b773c59eb889f68`, with production +source bytes verified equal to main f254 at baseline acquisition. Its compiled +file-table digest is +`5332dda13981f043e146b3601ebec1f380d9f698280ca53d75786b638a912e11`; +the receipt is not relabeled as a newer build. + +The candidate adds explicit MCP `detail: "summary"` and retained pool pages. +Omitted/complete requests and the CLI preserve the old complete path. Analysis, +ABI selection and original Evidence stay intact. Summary retains target/libapp +identity, exact nullable snapshot observations, lower bounds, returned counts, +coverage and limitations. Pages preserve original string order and source +coverage without rescanning. No engine cache, provider protocol or third-party +plugin API is introduced. + +Follow-up measurements must compare identical selected facts, portable old +Evidence and actual model tasks. Reply bytes do not establish token or latency +improvements. Whole-scope final counters remain unknown if their cgroup has +disappeared, even when the narrower payload-exit observation is verified. +Raw records, binaries and model traces stay in the private lab outside Git. +Heavy work remains serial under the unchanged one-CPU, 3 GiB early-stop / 4 GiB +hard memory, no-swap and host-availability guards. + +## Main advanced during the experiment + +Main subsequently advanced to `a2d8b94dd50dab8d966239dd63ab84718aa8b4b4`, +adding native Fiddler SAZ parsing. Its web-network capture contract already +offers opt-in summary and retained capture pages, archive-member coordinates +and exact exposed encoded bytes. It decodes all records before ordinal +selection and rejects malformed/oversized inputs without partial success. +Measure real public SAZ artifacts using these controls before adding another +API or changing decoding or credential-redaction semantics. SAZ performance +remains unverified in this Flutter continuation. + +The Flutter cohorts keep their original frozen runtime; subsequent integration +onto this newer main does not relabel earlier measurement receipts. + +Main advanced again to `bb154d106` during CI, adding retained aioquic 1.5.0 +qlog 0.3 JSON parsing and qlog views. The existing capture summary/page path +already applies. Qlog's trace-scoped STREAM interval unions and endpoint loss +declarations have separate semantics: they do not recover bodies, prove network +loss or establish PCAP correlation. Measure genuine supported recordings and +existing retained views before adding delivery or caching. Other qlog layouts +and qlog performance remain unverified in the Flutter experiment. Shared-view +integration is checked after rebasing; earlier runtime receipts remain pinned. diff --git a/experiments/analysis-efficiency/measure.mjs b/experiments/analysis-efficiency/measure.mjs index 3e34d935e..160973aa7 100644 --- a/experiments/analysis-efficiency/measure.mjs +++ b/experiments/analysis-efficiency/measure.mjs @@ -28,6 +28,7 @@ const { values } = parseArgs({ "javascript-question": { type: "string", default: "inventory" }, "managed-question": { type: "string", default: "inventory" }, schemas: { type: "string", default: "default" }, + "sqlite-selection": { type: "string", default: "all" }, }, }); if ( @@ -43,6 +44,11 @@ if ( ) || !["inventory", "selected"].includes(values["javascript-question"]) || !["default", "selected"].includes(values.schemas) || + !["all", "columns"].includes(values["sqlite-selection"]) || + (values.artifact !== "qgis-world-map.gpkg" && + values["sqlite-selection"] !== "all") || + (values.artifact === "qgis-world-map.gpkg" && + values.delivery !== "complete") || !["inventory", "identity"].includes(values["managed-question"]) || (!["sharex.dll", "sharex.helpers.dll"].includes(values.artifact) && values["managed-question"] !== "inventory") || @@ -518,6 +524,54 @@ const inspectEvmTarget = async () => { }; const workflows = { + "qgis-world-map.gpkg": async () => { + const columns = ["fid", "NAME", "ISO_A3"]; + const input = { + path: values.path, + table: "countries", + row_limit: 1, + ...(values["sqlite-selection"] === "columns" ? { columns } : {}), + }; + const definition = catalogDefinitions.get("inspect_sqlite_database"); + if ( + definition === undefined || + !new Ajv2020({ strict: false, validateFormats: false }).validate( + definition.inputSchema, + input, + ) + ) + throw new Error( + "Selected SQLite request is not advertised by this runtime", + ); + const inspected = await call("inspect_sqlite_database", input); + const report = normalized(inspected); + if (report.rows === null || report.rows.table !== "countries") + throw new Error("Runtime returned no selected country sample"); + const indexes = columns.map((column) => { + const index = report.rows.columns.indexOf(column); + if (index < 0) + throw new Error(`Missing requested SQLite column ${column}`); + return index; + }); + return { + artifact_sha256: targetSha(inspected), + artifact: report.artifact, + wal: report.wal, + engine: report.engine, + database_encoding: report.database_encoding, + schema: report.schema, + rows: { + ...report.rows, + columns, + values: report.rows.values.map((row) => + indexes.map((index) => row[index]), + ), + }, + producer_limitations: report.limitations, + limitations: inspected.limitations, + evidence_ids: [inspected.evidence_id], + }; + }, "obsidian.asar": async () => { if (values["javascript-question"] === "selected") { const inspected = await call("analyze_javascript_application", { @@ -666,7 +720,40 @@ const workflows = { } }, "newpipe.apk": async () => { - const pkg = await call("inspect_android_package", { path: values.path }); + const packageInput = { + path: values.path, + ...(values.delivery === "summary" ? { detail: "summary" } : {}), + }; + const definition = catalogDefinitions.get("inspect_android_package"); + if ( + definition === undefined || + !new Ajv2020({ strict: false, validateFormats: false }).validate( + definition.inputSchema, + packageInput, + ) + ) + throw new Error( + "Selected Android delivery is not advertised by this runtime", + ); + const pkg = await call("inspect_android_package", packageInput); + const result = normalized(pkg); + const report = values.delivery === "summary" ? result.summary : result; + if ( + values.delivery === "summary" && + (result.kind !== "summary" || + result.parent_operation !== "inspect_android_package") + ) + throw new Error("Runtime returned no retained Android package summary"); + const { manifest, ...declarations } = report; + const manifestObservation = + values.delivery === "summary" + ? manifest + : { + status: manifest.status, + reported_total_bytes: manifest.reported_total_bytes, + text_code_units: manifest.text.length, + text_included: false, + }; const found = await call("search_android_classes", { path: values.path, query: "MainActivity", @@ -677,9 +764,12 @@ const workflows = { }); return { artifact_sha256: targetSha(pkg), - package_name: normalized(pkg).package_name, - version_name: normalized(pkg).version_name, - version_code: normalized(pkg).version_code, + package_name: report.package_name, + version_name: report.version_name, + version_code: report.version_code, + package_declarations: declarations, + manifest_observation: manifestObservation, + package_limitations: pkg.limitations, matches: normalized(found).matches, coverage: normalized(found).coverage, onCreate: normalized(cls).methods.filter( @@ -690,6 +780,54 @@ const workflows = { }, "sharex.dll": inspectManagedTarget, "sharex.helpers.dll": inspectManagedTarget, + "localsend-arm64.apk": async () => { + const input = { + path: values.path, + ...(values.delivery === "summary" ? { detail: "summary" } : {}), + }; + const definition = catalogDefinitions.get("inspect_dart_aot"); + if ( + definition === undefined || + !new Ajv2020({ strict: false, validateFormats: false }).validate( + definition.inputSchema, + input, + ) + ) + throw new Error( + "Selected Dart AOT delivery is not advertised by this runtime", + ); + const inspected = await call("inspect_dart_aot", input); + const result = normalized(inspected); + if ( + values.delivery === "summary" && + (result.kind !== "summary" || + result.parent_operation !== "inspect_dart_aot") + ) + throw new Error("Runtime returned no retained Dart AOT summary"); + const report = values.delivery === "summary" ? result.summary : result; + const { package_uris, dart_uris, class_like_tokens, ...pool } = + report.string_pool; + return { + artifact_sha256: targetSha(inspected), + target: report.target, + abi: report.abi, + libapp: report.libapp, + string_pool: + values.delivery === "summary" + ? pool + : { + ...pool, + returned_counts: { + package_uris: package_uris.length, + dart_uris: dart_uris.length, + class_like_tokens: class_like_tokens.length, + }, + }, + coverage: report.coverage, + limitations: inspected.limitations, + evidence_ids: [inspected.evidence_id], + }; + }, "openwrt.bin": async () => { const info = await call("inspect_firmware_regions", { path: values.path }); return { @@ -818,6 +956,10 @@ const report = { ) ? values["managed-question"] : null, + sqlite_selection: + values.artifact === "qgis-world-map.gpkg" + ? values["sqlite-selection"] + : null, provider_settings_sha256: sha(JSON.stringify(selectedProviders)), provider_search_path_sha256: sha( selectedProviders.PATH ?? process.env.PATH ?? "", diff --git a/experiments/analysis-efficiency/model-context.md b/experiments/analysis-efficiency/model-context.md new file mode 100644 index 000000000..3d878beed --- /dev/null +++ b/experiments/analysis-efficiency/model-context.md @@ -0,0 +1,209 @@ +# Observe the client boundary before claiming token savings + +Continues [#2016](https://github.com/morluto/rea/issues/2016) after the managed +summary [PR #2413](https://github.com/morluto/rea/pull/2413) merged as +`82cfcee19f18b0eeae9a330ba04e0411cdf85225`. That opt-in view has verified smaller +delivery and complete-default migration, while its original real-model cohort +does not establish token savings. This follow-up measures why raw reply bytes +and aggregate model usage cannot be treated as interchangeable observations. + +## Concrete diagnostic observation + +An individual real Codex CLI 0.161.0 control uses frozen runtime +`ae8051302b5834322fa00cfa31c968ae74ab6ed9`, the unchanged ShareX identity question, +requested `gpt-5.6-terra` high and the same two enabled REA tools. A private +diagnostic copy removes the original runner's explicit `--ephemeral` flag. +Authentication/profile cleanup still runs; only selected tool/usage items are +retained after filtering the owned rollout. Its source rollout SHA-256 is +`d4df41d6187880d177f00b7533d85ad032c9c4ec502a39e7d5a566180e10461b` and the retained +filtered-item SHA-256 is +`0d5b4fb67c5674d1ba14ac32ae37e9a72b0368f4d9f5f9f81eb4d13193cda260`. +The original whole-copy is removed; account metadata, world state, messages and +internal passthrough are not retained in the filtered receipt. + +Despite the requested `direct` configuration label, the observed client uses +three JavaScript `exec` calls. First it filters `ALL_TOOLS` with a broad +`/REA|reverse|artifact|managed|assembly|metadata/i` expression and prints matching +metadata. The client reports truncation of a 164,005-token original output. +This is the client's output measurement, not billed input or a complete inventory. +Next it invokes complete managed inspection but selects requested normalized +identity/classification fields before printing. Finally it invokes native-boundary +inspection and prints selected fields. The actual original complete MCP replies +remain available in the separate public-event transcript. + +The persisted custom-tool output values are 41,704 / 2,154 / 13,489 UTF-8 bytes. +These are the serialized recorded output **values**, not raw wire bytes or exact +submitted model requests. The trace reports four per-response usage observations: + +| Response | Input | Cached input | Output | +| -------- | -----: | -----------: | -----: | +| 1 | 10,400 | 0 | 132 | +| 2 | 19,992 | 9,984 | 456 | +| 3 | 21,242 | 19,200 | 251 | +| 4 | 24,799 | 20,224 | 1,535 | + +Their totals match public turn usage: 76,433 input, 49,408 cached, 27,025 uncached +and 2,374 output, with 61.436 seconds observed wall time. Two MCP calls alone do +not describe the client's discovery/execution rounds. This proves the observed +control can project a complete result before printing it; it does not establish +that every earlier control/candidate did the same, or attribute every token +difference to discovery. The earlier `direct` label specifies requested client +configuration, not a verified absence of an executor. + +Initial transcript-capture attempts retained empty source lists because the +original runner intentionally passed `--ephemeral`. A first private flag-removal +edit missed its newline and failed; that candidate remains an unsuccessful +capture attempt. The later corrected control is an individual diagnostic, +not a comparable pair with that candidate. Other exploratory aggregates remain +private and are not silently folded into the original four-trial cohort. + +## Reproducible optional capture + +`agent-trial.py --capture-tool-context` omits `--ephemeral` only for that explicitly +selected temporary trial. Its default is unchanged. The profile still disappears +in `finally`, including when capture fails. The capture reads only its owned +`sessions/*.jsonl` records, rejects symlink sources, and retains: + +- Custom/function tool calls and replies, preserving call IDs and exact values. +- Per-response token counts and cumulative counts, with original response IDs. +- Client token-count events, retaining explicit unknown `info: null`. + +It excludes session/account metadata, world state, user/developer messages, +encrypted reasoning, internal passthrough and unknown nested usage fields. It +does not copy authentication, configuration or the ambient environment. Receipts +record source/retained digests, event counts, malformed-line failures and missing +rollouts as unavailable. Capture is an observation of persisted client items, +not proof of the exact request accepted by a remote model service. + +Run the same frozen runtime, question, tool selection and capture mode on both +sides. Preserve source/settings hashes and separate requested versus observed +behavior. Use the existing resource wrapper with unchanged one CPU, 4 GiB hard +memory, 3 GiB early-stop, no swap and task/host safeguards. Final physical counters +remain unknown when transient cgroups disappear; this instrumentation does not +repair that measurement limitation. + +The focused Python tests run through the existing CI `test:python` gate. +They cover account/ambient exclusion while preserving caller data, malformed and +missing records, foreign symlinks, and capture failure without copied-credential +leakage. The cleanup test simulates a CLI and establishes only cleanup semantics; +it is not real-model/provider evidence. + +## An explicit discovery-guidance experiment + +`--guide-enabled-tools` is another opt-in experiment flag. It requires a nonempty +`--enabled-tools` list and adds the exact corresponding `mcp__rea__...` function +names to the temporary developer instructions, requesting only exact-name +metadata discovery. It preserves the analyst question, operation order, tool +selection and provider inputs. The default instruction is unchanged. Missing or +invalid selected tools fail before creating an output/profile. The test gate +also verifies the new prerequisite without acquiring a profile. + +Compare guided and unguided runs on the **same** frozen REA runtime with matching +capture mode and requested facts. A smaller discovery response or additional +hint is not itself a task/token success: grade answers, count all response usage, +preserve failed/truncated runs and repeat both orders before recommending this +guidance. This is a caller-side experiment, not a new REA tool or provider preset. + +## First committed capture pair + +Checkpoint `9ebdcc458c399b9bdecaaca2ef47422888231181` runs the unchanged question +against frozen control `ae8051302b5834322fa00cfa31c968ae74ab6ed9` and candidate +`8bc1601ca51e417ca472d90ea0367e9418a1a0f2`, both with capture enabled and no tool +guidance. Both captures succeed with 10 retained events, unchanged source bytes, +removed profiles, two successful MCP calls and passing selected factual checks. +Full grader gates remain false because final physical resource counters are +unavailable; factual subsets do not override that limitation. + +| Side | Input | Cached | Uncached | Output | Wall seconds | +| ----------------- | -----: | -----: | -------: | -----: | -----------: | +| Complete control | 52,656 | 27,136 | 25,520 | 2,015 | 57.736 | +| Summary candidate | 56,655 | 29,184 | 27,471 | 1,534 | 55.055 | + +Both clients make two executor calls and three response-usage observations. +First they print broad discovered metadata, with truncation. Then each executor +sequentially performs both MCP operations, preserving selected-target dependency +order. The control prints a 2,086-byte output value; the candidate prints 22,770 +bytes. Their discovery output values are 41,723 and 41,675 bytes. These are +recorded serialized values and remain distinct from raw MCP envelopes, billed +tokens and exact submitted requests. Both requested modes are `direct`; the +actual executor use is separately observed. + +The candidate's smaller raw metadata reply does not result in a smaller printed +client value in this pair. Candidate input/uncached tokens remain higher. The +observed projection and round counts are useful constraints for the next +experiment; this one pair does not attribute all usage differences to either +formatting or discovery, or establish a reliable speedup. + +## Same-runtime guided discovery, repeated in both orders + +Checkpoint `e20bd0e2a905f06bc8c56fe04b0e61f3da88636a` runs four actual Codex trials +in unguided/guided/guided/unguided order. All use the **same** frozen candidate +runtime, artifact, original question, requested model/reasoning, two selected +tools, provider settings and capture mode. Only the explicit discovery-guidance +treatment changes. Every trial selects artifact summary and makes the same two +successful MCP calls in dependency order; source bytes stay unchanged, captures +succeed and profiles are removed. + +| Trial | Input | Cached | Uncached | Output | Seconds | Observed responses | +| ---------- | ------: | -----: | -------: | -----: | ------: | -----------------: | +| Unguided 1 | 77,251 | 50,432 | 26,819 | 1,931 | 62.066 | 4 | +| Guided 1 | 39,175 | 23,040 | 16,135 | 1,763 | 55.658 | 3 | +| Guided 2 | 58,336 | 38,144 | 20,192 | 1,626 | 50.685 | 4 | +| Unguided 2 | 103,301 | 72,704 | 30,597 | 1,983 | 60.336 | 5 | + +Both guided discovery output values repeat at 12,336 bytes without truncation, +versus 41,709 bytes with truncation on both unguided trials. The recorded +executor/output usage explains observable discovery and round differences; it +does not certify exact remote request contents or attribute every token to the +hint. CPU samples are 6.303–6.554 seconds and peak family memory 684,519,424– +712,028,160 bytes, with no guard abort. Final resource counters remain unknown. +These samples do not establish a memory or CPU improvement. + +Unguided 1 omits `classification.container` and fails the selected factual gate; +it is not a fully acceptable comparison answer. Guided 1 and Unguided 2 pass +that gate. Guided 2 initially fails exact coverage-object equality because it +adds `module_ref_count: 0` and `pinvoke_import_count: 0` to the explicitly named +native scope. Both numbers exactly match the producer's returned arrays. The +grader now explicitly verifies only these two known additional counts, including +integer type, while still requiring all original coverage facts. Unknown extra +claims, conflicting aliases, wrong counts, boolean/string counts and omitted +issues continue to fail. Source coverage remains unchanged; returned-row counts +do not establish global absence. Original failure receipts remain preserved; +the regrade separately records its new source hash. Guided 2 then passes selected +facts, but every **full** gate still fails unknown final physical resource checks. + +The second comparison has two factually acceptable answers: observed guided input +falls about 43.5%, uncached input about 34.0%, and wall time about 16.0%. The first +comparison has an incomplete unguided answer and is reported without counting it +as equivalent completed work. Two trials per treatment on one question/application +remain a preliminary signal, not a general default recommendation. The hint stays +opt-in; wider questions/domains, count/coverage representation and client round +behavior need further verification before promoting it into general guidance. + +## Real Android follow-up: the primary outcomes are mixed + +Checkpoint `22834c7d73056e2480b426848f58c31af0c307bc` checks the pinned real +NewPipe 0.29.1 APK using actual configured JADX 0.7.1/Java, the original Android +question and the same frozen candidate runtime. First a fresh SDK workflow +validates three live advertised operations and produces the comparison facts: +package/version identity, every case-sensitive MainActivity match and all +reported onCreate entries, preserving signatures, overload indices and null DEX +descriptors. It takes 26.961 seconds; the owned scope samples 1,234,735,104 bytes. + +Both subsequent actual Codex trials use the same three selected tool names, +capture mode, model/reasoning, question and provider settings. Only discovery +guidance changes. Each makes three successful MCP calls and five observed model +responses, passes selected facts against the fresh actual producer, preserves +source bytes and removes its temporary profile. No APK execution is requested. + +| Trial | Input | Cached | Uncached | Output | Wall seconds | Sampled peak bytes | +| -------- | -----: | -----: | -------: | -----: | -----------: | -----------------: | +| Unguided | 99,913 | 80,640 | 19,273 | 1,527 | 66.797 | 1,405,829,120 | +| Guided | 89,220 | 62,464 | 26,756 | 2,142 | 76.936 | 1,345,576,960 | + +Total input falls about 10.7%, but uncached input increases and wall time is +longer. One pair does not demonstrate improved Android performance or memory. +No guard abort occurs; final counters remain unknown and full resource gates +remain false. This second domain is a concrete counterexample to generalizing +the favorable managed comparison. Keep both flags optional and continue +task-specific experiments before changing installed/default agent guidance. diff --git a/experiments/analysis-efficiency/process-trace-validation.md b/experiments/analysis-efficiency/process-trace-validation.md new file mode 100644 index 000000000..a32848596 --- /dev/null +++ b/experiments/analysis-efficiency/process-trace-validation.md @@ -0,0 +1,113 @@ +# Process trace validation + +A 6,000-event directed cycle previously overflowed the JavaScript stack inside +the schema refinement. Cycle detection now uses iterative topological traversal. +Cyclic inputs retain independent declaration diagnostics without expanding all +event pairs. Unordered declarations retain group membership, with one diagnostic +per overlapping or conflicting group, instead of allocating a pair set and +repeating the same error for every pair. + +A unique topological order proves that every event pair is ordered, allowing +rank comparisons without retaining transitive closure. Other acyclic graphs +retain only one origin's forward and backward reachability sets at a time. +Complete pair validation preserves the missing count and first declaration-order +missing pair. General partial orders still require quadratic pair examination +and repeated graph traversal; they trade CPU time for bounded retained state. + +## Initial cycle fix comparison + +Flameox ran three randomized paired blocks (seed 917), each limited to 20 seconds +and 512 MiB. Node 24.18.0 used a 384-MiB old-space limit on macOS arm64. Each +process validated the same 2,500-event acyclic chain four times, then checked the +known 6,000-event cycle failure with per-event not-before constraints and one +unordered group containing every event. All six executions passed the embedded answer +digest and expected rejection checks. + +The baseline source is from `bb540826d`; the candidate is the initial cycle fix +in `10935b7b1`, which still memoized reachability sets for every queried origin. +Both modules had TypeScript annotations removed with Node's identical built-in +transform and used the same copied runtime dependencies. This isolates schema +validation rather than comparing complete packaged CLI/MCP processes. + +| Median measurement | Baseline | Candidate | +| -------------------------------------------- | -------: | --------: | +| First validation elapsed milliseconds | 335.80 | 177.25 | +| Warm validation elapsed milliseconds | 313.36 | 165.23 | +| First validation CPU milliseconds | 366.85 | 218.39 | +| Warm validation CPU milliseconds | 335.32 | 194.08 | +| Whole-process elapsed milliseconds | 1,344.13 | 787.00 | +| Process CPU milliseconds before final report | 1,457.67 | 941.05 | +| Peak process-family MiB | 328.36 | 395.52 | + +The input is identical: 233,095 JSON bytes, estimated at 77,010 tokens by tokenx +1.3.0. The valid parsed result digest is +`28bd99ce83f0da8e45600ef20f114cb52bb26b5f5e6bfc1601ca3e712eaf3147`. +Actual agent tokens, catalog injection, transport, model reasoning and provider +costs were not measured. This is a component measurement, not an end-to-end +investigation speed claim. + +First validation excludes module import and fixture preparation; warm runs reuse +the process but create fresh per-validation graph state. Whole-process elapsed +includes startup, imports, all four validations, the cyclic-input check, token +estimation and reporting. CPU includes startup through metrics publication; +peak RSS covers the complete single-process workload, with no children. Host +caches were not flushed. Peak memory increased in this cohort. Its retained +valid-order closure still required quadratic memory, prompting the follow-up. +Three pairs describe this fixture only. + +Preserved Flameox evidence: +`d6211639446e8b6ec2e82636913eaf471def96673e28f03e9c7f98bec07f8e13`; +analysis `e663b6bd8f5693975542d5b5e2b18437b3c167a0be939bb7386eb68549936231`. +An earlier cohort lost modules during another checkout build; its three failed +executions and timing results are excluded. The successful cohort uses an +isolated runtime copy. Source-module SHA-256 values are +`a7729faa2183b0e493b9ac4fc55f6feaee5b2e5294be13d1b29b57a44b899788` +(baseline) and `725409ce84902125941251037a8a214ccc3c1eec577e484c164c361ca580d693` +(candidate). + +## Bounded retention follow-up + +Flameox compared `10935b7b1` with the rank/streaming implementation in three +randomized paired blocks (seed 624), under the same host, Node, heap, memory and +20-second execution bounds. Each execution validated the chain above four times, +then a 1,200-event partial order with 600 unordered two-event layers and all four +edges between consecutive layers four times, then the same cyclic failure. +All six executions passed both parsed-answer digests and the cycle diagnostic. +Runtime dependencies were copied and isolated from concurrent checkout builds. + +| Median measurement | Memoized closure | Rank/streaming | +| ---------------------------------------- | ---------------: | -------------: | +| Chain first elapsed milliseconds | 166.11 | 11.37 | +| Chain warm elapsed milliseconds | 154.25 | 5.32 | +| Chain first CPU milliseconds | 210.13 | 24.38 | +| Chain warm CPU milliseconds | 184.76 | 16.84 | +| Partial order first elapsed milliseconds | 49.44 | 116.54 | +| Partial order warm elapsed milliseconds | 50.67 | 110.29 | +| Partial order first CPU milliseconds | 72.47 | 137.69 | +| Partial order warm CPU milliseconds | 70.65 | 121.77 | +| Capture process elapsed milliseconds | 901.24 | 557.30 | +| Process CPU milliseconds before report | 1,101.12 | 665.03 | +| Peak process-family MiB | 391.13 | 127.72 | + +First samples exclude module import and fixture preparation. Partial-order first +samples follow four chain validations, so they are first use of that fixture +within an already running process. Warm medians pool the three subsequent samples +from each of three processes. CPU and peak RSS cover the combined workload; +capture elapsed additionally includes Flameox capture startup and overhead. +Host caches were not flushed. The partial-order fixture is slower after this +change; these results establish a retention tradeoff, not universal acceleration. + +The partial-order input is 165,590 JSON bytes, estimated at 52,783 tokens by tokenx +1.3.0; its parsed-answer SHA-256 is +`41d06e593813e497221c36793bf00d5fece7055081895b5f6c123ba6ad9a8227`. +Chain bytes, token estimate and answer digest remain unchanged. Actual agent +tokens, transport, catalog injection, model reasoning and provider costs remain +unmeasured. Both cohorts are component measurements, not complete investigations. + +Preserved evidence: +`e29086af99afd8e67cbbd92e43d960ea40f73b4d318ea0cbca60f493575462b8`; +analysis `086133516f2acf031032d357a3ddb1ac611ce4f12556a24065a2becd567c5f7b`. +The baseline module SHA-256 is +`725409ce84902125941251037a8a214ccc3c1eec577e484c164c361ca580d693`; +the candidate module SHA-256 is +`2109f1096406e9ecac8bbf4f7ae8abb5113404790a9382487285d2831fcddf26`. diff --git a/experiments/analysis-efficiency/questions/flutter-aot.txt b/experiments/analysis-efficiency/questions/flutter-aot.txt new file mode 100644 index 000000000..c4c3c3897 --- /dev/null +++ b/experiments/analysis-efficiency/questions/flutter-aot.txt @@ -0,0 +1 @@ +Statically inspect the shipped Flutter APK at {{artifact_path}} using only the registered REA inspect_dart_aot tool. Use its default ABI selection. Report target identity, chosen ABI, every libapp ELF/snapshot field exactly as reported including null, original string-pool coverage, all three counts ending in _at_least, printable_run_count, and returned_counts for package_uris, dart_uris and class_like_tokens. Compute returned_counts from the returned arrays if needed. Preserve original overall coverage and producer limitations exactly, including order. Counts ending in _at_least are lower bounds and class-like tokens are byte-pattern observations, not recovered typed classes. Do not return individual strings or infer Dart SDK versions, class semantics, runtime behavior or complete inventory. Final answer must be JSON with artifact_sha256, target, abi, libapp, string_pool, coverage, limitations, evidence_ids. Use actual response Evidence IDs. Do not execute the APK, use shell or host file tools, access the network, or call other agents. Stop when these facts are supported. diff --git a/experiments/analysis-efficiency/questions/sqlite-qgis.txt b/experiments/analysis-efficiency/questions/sqlite-qgis.txt new file mode 100644 index 000000000..636c7a685 --- /dev/null +++ b/experiments/analysis-efficiency/questions/sqlite-qgis.txt @@ -0,0 +1 @@ +Statically inspect the supplied QGIS world-map GeoPackage at {{artifact_path}} using only the registered REA inspect_sqlite_database tool. Select the ordinary countries table with row_limit 1 and its default selected_table schema scope. Report the complete returned schema exactly as reported, including SQL, every declared column, indexes, views, triggers, completeness and explicit nulls. For the one returned sample, report only fid, NAME and ISO_A3 in that order, preserving the original tagged SQLite cells exactly: decimal integer strings, text values with bytes_hex and encoding, and SQL null. Preserve row_limit, returned_rows, truncated and order; row order is unspecified and this is not a complete country inventory. Preserve original artifact identity, wal including null, engine, database_encoding, both normalized-result producer limitations and outer Evidence limitations exactly including order. Do not return geometry blobs or unrequested sample cells, interpret boundaries/political labels as current facts, or infer missing values. Final JSON fields: artifact_sha256, artifact, wal, engine, database_encoding, schema, rows, producer_limitations, limitations, evidence_ids. Include real response Evidence IDs. Do not use shell or host file tools, network, other agents or execute QGIS. Stop once these facts are supported. diff --git a/experiments/analysis-efficiency/resource-counters.md b/experiments/analysis-efficiency/resource-counters.md new file mode 100644 index 000000000..8b21f54df --- /dev/null +++ b/experiments/analysis-efficiency/resource-counters.md @@ -0,0 +1,103 @@ +# Resource counters at payload completion + +Continues [#2016](https://github.com/morluto/rea/issues/2016) from merged main +`4f4f6cd7b5d7a400b90772a138d7b9f942c2a556`. A transient cgroup can disappear +before the existing supervisor reads terminal counters. Earlier reports keep +those counters unknown; sampled zero events are not final no-OOM proof. + +An optional `resource-run.py --observe-payload-exit -- COMMAND...` adds one small +observer inside the same owned scope. It waits for the direct payload, records +kernel `memory.peak`, CPU and memory/task events, and reports remaining processes +before acknowledging completion to the outer supervisor. The observer remains +alive until receipt acknowledgement, bounded by the existing ten-second cleanup +interval. Payload stdio and process exit status remain observable. + +The receipt phase is **payload-exited-observer-alive**. The supervisor validates +the owned-unit token, numeric fields, cgroup identity, live observer membership, +payload exit status and absence of additional processes before marking that +observation verified. Wrong-owner, malformed, missing or inconsistent receipts +stay unknown; lingering actors stay explicit and cannot certify cleanup. +Unexpected metadata is omitted rather than copying an inherited environment. + +This is not a final whole-scope counter: the observer still has to exit. Existing +`resource_events_final` and `resource_counters_verified` retain their original +meaning and unknown state. The grader's existing full resource gate is unchanged. +Earlier runs and source/runtime hashes are not relabeled. Observer CPU/memory and +acknowledgement time are included in this new measurement mode; comparable runs +must use the same mode. Default commands do not start an observer or add fields. + +One CPU, the unchanged 3 GiB early-stop/4 GiB hard ceiling, no swap, task limits +and host-available-memory safeguards remain in force. No resource limit is raised. +The opt-in mode requires at least two task slots for observer plus payload; +smaller caller-selected ceilings fail before process acquisition. Default mode +continues to accept a one-task ceiling. +Cleanup uses the uniquely owned systemd scope, without signaling a process merely +because a recorded PID exists. Failed scope cleanup retains the named owner. + +## Focused verification + +Five semantic Python cases cover acquisition-free capacity rejection, nonzero exit/kernel facts, missing or malformed +receipts, wrong ownership, integer types, contradictory cleanup, lingering actors, +foreign symlinks and exclusion of unrelated metadata. They join the existing +Python gate; simulated receipts do not establish actual cgroup behavior. + +Actual Linux cgroup/systemd probes additionally verify: + +- Default mode keeps its receipt shape and success status. +- Success and exit-code 3 preserve the payload outcome and verify a sole observer. +- A bounded 16 MiB Node allocation yields a kernel peak, including work that the + 100 ms sampler can miss. +- A payload leaving a child reports both actors and refuses verification; the + supervisor retires the owned scope. +- A caller-selected task ceiling of 4 triggers the existing task-limit early stop + with exit 125 and an unverified observation. +- Interrupting a confirmed-live owned controller preserves failure and retires + its scope; missing completion counters are not replaced with zeros. + +These are metering/lifecycle probes, not a new model/provider performance claim. +Actual REA workflows and repeated observer-overhead measurements remain necessary +before relying on the new mode for domain comparisons. Raw receipts remain in +the private experiment lab outside Git. + +## Actual REA and model observations + +Checkpoint `d1f2cfe76df28e6effe973123f2e19313f6d0d4b` repeats real SDK workflows +against the unchanged frozen candidate `8bc1601ca51e417ca472d90ea0367e9418a1a0f2` +(runtime file-table SHA-256 +`9e7380f537301bf0cfe2926f5619011af848af7c220750e75189498e65d825e1`). +The resource supervisor changes; the compiled REA/provider algorithms do not. +Managed pairs use default/observer/observer/default order with the same question, +settings, two public calls and identical selected facts. Raw receipts remain +private and new measurements do not replace historical resource unknowns. + +| Workflow | SDK milliseconds | Scope seconds | Sampled peak bytes | Kernel peak at payload exit | Payload CPU microseconds | +| -------------------- | ---------------: | ------------: | -----------------: | --------------------------: | -----------------------: | +| Managed default 1 | 5,168.485 | 11.814 | 525,873,152 | unknown | unknown | +| Managed observer 1 | 4,156.708 | 5.358 | 527,777,792 | 535,724,032 | 5,195,457 | +| Managed observer 2 | 3,810.362 | 5.056 | 538,742,784 | 539,529,216 | 4,818,497 | +| Managed default 2 | 4,263.993 | 5.360 | 526,032,896 | unknown | unknown | +| SQLite WASM observer | 6,733.216 | 8.087 | 777,199,616 | 777,199,616 | 7,830,130 | +| NewPipe APK observer | 23,162.195 | 24.600 | 1,286,586,368 | 1,287,548,928 | 23,965,627 | + +The WASM and APK runs use actual configured WABT and JADX/Java. Every observer +receipt verifies a sole remaining observer, successful payload exit and the +expected owned group. No guard abort occurs. The initial default scope timing is +an outlier relative to its SDK workflow and later scopes; its cause is not +established. Two managed pairs are insufficient to characterize observer overhead +or establish a speed/memory improvement. Kernel peak and CPU include the observer. + +One actual Codex CLI 0.161.0 trial uses the original managed question, exact-name +guidance, context capture and requested `gpt-5.6-terra` high. It passes selected +facts, preserves source bytes, removes its profile and makes three successful MCP +calls (including an additional artifact inspection). Reported usage is 61,173 +input, 48,128 cached, 13,045 uncached and 2,678 output tokens; wall time is 125.798 +seconds. The payload-exit witness records 812,896,256 kernel peak bytes and +8,566,029 CPU microseconds with only the observer alive and zero recorded +memory/task limit events at that phase. This confirms the completed model/MCP +payload boundary, not a token/time benefit or final whole-scope no-OOM proof. +Its full existing grader remains false for unknown terminal physical counters. + +The subsequent review adds supervisor/helper source SHA-256 to opt-in receipts +before process acquisition, without adding those fields to default receipts. +This distinguishes measurement implementations independently of frozen runtime +identity and keeps the observer's phase explicit. diff --git a/experiments/analysis-efficiency/resource-run.py b/experiments/analysis-efficiency/resource-run.py index 4417b390a..1790cdcca 100644 --- a/experiments/analysis-efficiency/resource-run.py +++ b/experiments/analysis-efficiency/resource-run.py @@ -1,14 +1,18 @@ """Run one owned experiment in a bounded, transient Linux systemd scope.""" import argparse +import hashlib import json import os from pathlib import Path import subprocess import sys +import tempfile import time import uuid +from resource_payload import read_observation + def available_bytes(): for line in Path('/proc/meminfo').read_text().splitlines(): @@ -64,10 +68,14 @@ def stop_owned_scope(unit, process, group): def main(): parser = argparse.ArgumentParser() parser.add_argument('--task-ceiling', type=int, default=192) + parser.add_argument('--observe-payload-exit', action='store_true', + help='Observe payload-exit counters before the cgroup observer exits') parser.add_argument('command', nargs=argparse.REMAINDER) options = parser.parse_args() if options.task_ceiling <= 0: parser.error('--task-ceiling must be positive') + if options.observe_payload_exit and options.task_ceiling < 2: + parser.error('--observe-payload-exit requires capacity for the observer and payload (at least 2 tasks)') args = options.command if args and args[0] == '--': args = args[1:] @@ -78,22 +86,41 @@ def main(): raise SystemExit('Refusing experiment: less than 8 GiB available') unit = 'rea-efficiency-' + uuid.uuid4().hex + '.scope' cpu = max(os.sched_getaffinity(0)) + receipt_root = tempfile.TemporaryDirectory(prefix='rea-payload-counters-') if options.observe_payload_exit else None + receipt_path = Path(receipt_root.name) / 'observation.json' if receipt_root else None + release_path = Path(receipt_root.name) / 'release' if receipt_root else None + payload = args if receipt_root is None else [ + sys.executable, str(Path(__file__).with_name('resource_payload.py')), + str(receipt_path), str(release_path), unit, *args, + ] command = [ 'systemd-run', '--user', '--scope', '--unit=' + unit, '-p', 'MemoryMax=4G', '-p', 'MemoryHigh=3G', '-p', 'MemorySwapMax=0', '-p', 'CPUQuota=100%', '-p', 'TasksMax=' + str(options.task_ceiling), - 'taskset', '-c', str(cpu), *args, + 'taskset', '-c', str(cpu), *payload, ] - process = subprocess.Popen(command) + observer_sources = { + name: hashlib.sha256(Path(__file__).with_name(name).read_bytes()).hexdigest() + for name in ['resource-run.py', 'resource_payload.py'] + } if options.observe_payload_exit else None + try: + process = subprocess.Popen(command) + except BaseException: + if receipt_root is not None: + receipt_root.cleanup() + raise peak = 0 peak_tasks = 0 events = {} cpu_stats = {} abort = None final_events = None + payload_observation = None + payload_group = None + code = None + group = None started = time.monotonic() try: - group = None while process.poll() is None: if group is None: reply = subprocess.run( @@ -104,6 +131,18 @@ def main(): path = reply.stdout.strip() if path: group = Path('/sys/fs/cgroup') / path.lstrip('/') + if receipt_path is not None and payload_observation is None and group is not None: + candidate = read_observation(receipt_path, unit) + if candidate is not None: + payload_observation = candidate + if candidate['control_group'] == str(group.relative_to('/sys/fs/cgroup')): + try: + actors = [int(x) for x in (group / 'cgroup.procs').read_text().splitlines()] + if candidate['observer_pid'] in actors: + payload_group = group + except (OSError, ValueError): + pass + release_path.touch(exist_ok=False) current = group / 'memory.current' if group else None if current and current.exists(): try: @@ -132,6 +171,8 @@ def main(): # Read while the owned group still exists, before wait/cleanup can remove it. final_events = final_resource_events(group) code = process.wait() + if receipt_path is not None and payload_observation is None: + payload_observation = read_observation(receipt_path, unit) except BaseException: stop_owned_scope(unit, process, group) raise @@ -150,7 +191,22 @@ def main(): 'resource_events_final': final_events, 'resource_counters_verified': final_events is not None, 'cpu_stat_last_observed': cpu_stats, + **({ + 'payload_resource_observation': payload_observation, + 'payload_resource_observation_verified': ( + payload_observation is not None + and payload_observation['payload_cleanup_verified'] + and payload_group is not None and abort is None + and code is not None + and (payload_observation['payload_exit_code'] if payload_observation['payload_exit_code'] >= 0 + else 128 - payload_observation['payload_exit_code']) == code + ), + 'payload_observation_scope': 'Counters at payload exit while observer remains alive; not final whole-scope counters.', + 'payload_observer_sources_sha256': observer_sources, + } if options.observe_payload_exit else {}), }), file=sys.stderr) + if receipt_root is not None: + receipt_root.cleanup() raise SystemExit(125 if abort else code) diff --git a/experiments/analysis-efficiency/resource_payload.py b/experiments/analysis-efficiency/resource_payload.py new file mode 100644 index 000000000..700598cbf --- /dev/null +++ b/experiments/analysis-efficiency/resource_payload.py @@ -0,0 +1,114 @@ +"""Observe a finished payload while its owned cgroup observer is still alive.""" + +import json +import os +from pathlib import Path +import subprocess +import sys +import time + + +def pairs(path): + values = {} + for line in path.read_text().splitlines(): + name, value = line.split() + number = int(value) + if number < 0 or name in values: + raise ValueError('Invalid kernel counter') + values[name] = number + return values + + +def snapshot(group, token, code): + actors = [int(line) for line in (group / 'cgroup.procs').read_text().splitlines()] + observer = os.getpid() + return { + 'phase': 'payload-exited-observer-alive', 'ownership_token': token, + 'payload_exit_code': code, 'observer_pid': observer, + 'remaining_processes': actors, 'payload_cleanup_verified': actors == [observer], + 'resource_events': {name: pairs(group / name) + for name in ['memory.events', 'pids.events']}, + 'cpu_stat': pairs(group / 'cpu.stat'), + 'memory_peak_bytes': int((group / 'memory.peak').read_text()), + 'control_group': str(group.relative_to('/sys/fs/cgroup')), + } + + +def read_observation(path, token): + """Validate the observer receipt; missing/malformed witnesses stay unknown.""" + try: + if path.is_symlink(): + return None + value = json.loads(path.read_text()) + if not isinstance(value, dict) or value.get('ownership_token') != token: + return None + if value.get('phase') != 'payload-exited-observer-alive': + return None + if not isinstance(value.get('control_group'), str) or not value['control_group']: + return None + for name in ['payload_exit_code', 'observer_pid', 'memory_peak_bytes']: + if type(value.get(name)) is not int: + return None + if value['observer_pid'] <= 0 or value['memory_peak_bytes'] < 0: + return None + actors = value.get('remaining_processes') + if not isinstance(actors, list) or any(type(x) is not int or x <= 0 for x in actors): + return None + if type(value.get('payload_cleanup_verified')) is not bool: + return None + if value['payload_cleanup_verified'] != (actors == [value['observer_pid']]): + return None + required = {'memory.events': ['high', 'max', 'oom', 'oom_kill'], + 'pids.events': ['max']} + events = value.get('resource_events') + if not isinstance(events, dict): + return None + for name, keys in required.items(): + record = events.get(name) + if not isinstance(record, dict) or any(key not in record for key in keys): + return None + if any(type(x) is not int or x < 0 for x in record.values()): + return None + cpu = value.get('cpu_stat') + if not isinstance(cpu, dict) or 'usage_usec' not in cpu: + return None + if any(type(x) is not int or x < 0 for x in cpu.values()): + return None + names = ['phase', 'ownership_token', 'payload_exit_code', 'observer_pid', + 'remaining_processes', 'payload_cleanup_verified', + 'cpu_stat', 'memory_peak_bytes', 'control_group'] + return {**{name: value[name] for name in names}, + 'resource_events': {name: events[name] for name in required}} + except (OSError, ValueError, TypeError): + return None + + +def main(): + output, release, token = Path(sys.argv[1]), Path(sys.argv[2]), sys.argv[3] + command = sys.argv[4:] + if not command: + raise SystemExit('Missing explicit payload command') + child = subprocess.Popen(command) + code = child.wait() + paths = [line[3:] for line in Path('/proc/self/cgroup').read_text().splitlines() + if line.startswith('0::')] + try: + if len(paths) != 1: + raise ValueError('Expected one unified cgroup') + group = Path('/sys/fs/cgroup') / paths[0].lstrip('/') + observation = snapshot(group, token, code) + with os.fdopen(os.open(output, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600), + 'w') as file: + json.dump(observation, file) + # Keep the owner alive until its supervisor acknowledges the receipt. + # Bound a broken supervisor by the existing ten-second cleanup interval. + deadline = time.monotonic() + 10 + while not release.exists() and time.monotonic() < deadline: + time.sleep(0.02) + except (OSError, ValueError) as error: + print('Payload counter observation unavailable: ' + type(error).__name__, file=sys.stderr) + raise SystemExit(code if code >= 0 else 128 - code) + + +if __name__ == '__main__': + main() diff --git a/experiments/analysis-efficiency/review-model.py b/experiments/analysis-efficiency/review-model.py index 3c56aabb2..0d6e1e8d7 100644 --- a/experiments/analysis-efficiency/review-model.py +++ b/experiments/analysis-efficiency/review-model.py @@ -52,9 +52,24 @@ def named_scope(value, names): return {'conflicting_reported_scopes': selected} +def scope_with_verified_counts(value, expected_scope, returned_counts): + """Validate explicit extra row counts; never erase unknown or conflicting facts.""" + if not isinstance(value, dict): + return value, {} + scope = dict(value) + checks = {} + for name, expected in returned_counts.items(): + if name in scope: + reported = scope[name] + checks[name] = type(reported) is int and reported == expected + if name not in expected_scope: + del scope[name] + return scope, checks + + def main(): parser = argparse.ArgumentParser() - parser.add_argument('--domain', choices=['wasm', 'evm', 'android', 'managed', 'managed-nonempty', 'firmware', 'inventory', 'javascript', 'native', 'browser'], required=True) + parser.add_argument('--domain', choices=['wasm', 'evm', 'android', 'flutter-aot', 'sqlite', 'managed', 'managed-nonempty', 'firmware', 'inventory', 'javascript', 'native', 'browser'], required=True) parser.add_argument('--trial', type=Path, required=True) parser.add_argument('--reference', type=Path) parser.add_argument('--resource-log', type=Path, required=True) @@ -118,6 +133,14 @@ def main(): for key, expected in {'artifact_bytes': n['artifact']['bytes'], 'bytecode_sha256': n['bytecode']['sha256'], 'bytecode_bytes': n['bytecode']['bytes'], 'functions': n['functions'], 'evidence_kind': n['evidence_kind'], 'discovery_completeness': n['discovery_completeness'], 'runtime_execution': n['runtime_execution'], 'bytecode_kind': n['bytecode']['kind'], 'hardfork': n['bytecode']['hardfork'], 'deployment_authenticity': n['bytecode']['deployment_authenticity']}.items(): check(key, answer.get(key), expected) check('evm_original_limitations', answer.get('limitations'), n['limitations']) + elif domain == 'sqlite': + for key in ['artifact', 'wal', 'engine', 'database_encoding', 'schema', 'rows', 'producer_limitations', 'limitations']: + # Missing is not SQL/JSON null; booleans are not numeric counters. + check(key, (key in answer, json.dumps(answer.get(key), sort_keys=True)), + (True, json.dumps(reference[key], sort_keys=True))) + elif domain == 'flutter-aot': + for key in ['target', 'abi', 'libapp', 'string_pool', 'coverage', 'limitations']: + check(key, answer.get(key), reference[key]) elif domain == 'android': for key in ['package_name', 'version_name', 'version_code', 'matches']: check(key, answer.get(key), reference[key]) @@ -134,7 +157,13 @@ def main(): for key in ['module_refs', 'pinvoke_imports']: check(key, answer.get('native_boundaries', {}).get(key), reference['boundaries'][key]) check('artifact_coverage', named_scope(answer.get('coverage'), ['artifact', 'managed_artifact', 'managed_metadata']), n['coverage']) - check('native_boundaries_coverage', named_scope(answer.get('coverage'), ['native_boundaries', 'native_boundary_declarations']), reference['boundaries']['coverage']) + boundary_scope, counts = scope_with_verified_counts( + named_scope(answer.get('coverage'), ['native_boundaries', 'native_boundary_declarations']), + reference['boundaries']['coverage'], + {'module_ref_count': len(reference['boundaries']['module_refs']), + 'pinvoke_import_count': len(reference['boundaries']['pinvoke_imports'])}) + check('native_boundaries_coverage', boundary_scope, reference['boundaries']['coverage']) + checks.update({'native_coverage_' + name: valid for name, valid in counts.items()}) elif domain == 'managed-nonempty': n = reference['boundaries'] check('module_mvid', answer.get('module_mvid'), n['module']['mvid']) diff --git a/experiments/analysis-efficiency/sqlite-existing-controls.md b/experiments/analysis-efficiency/sqlite-existing-controls.md new file mode 100644 index 000000000..9bac9f064 --- /dev/null +++ b/experiments/analysis-efficiency/sqlite-existing-controls.md @@ -0,0 +1,181 @@ +# SQLite existing-control measurements + +Continues [#2016](https://github.com/morluto/rea/issues/2016) after the Flutter +lane. The measured main runtime is pinned to +`172407787f1842dedbcd27b5385177595f786ce4`. Its only post-Flutter +commit repairs Windows transient runtime admission (#2467); this Linux round +does not establish Windows performance. No production/API change is proposed +merely because another summary or cache could be added. + +Before PR integration, main advanced to +`bb540826d65316c164d2de8ba4ef10f81a8ad073`. Its five intervening commits cover +MCP archive contracts/documentation, an advertised-schema inventory test, +pwntools cleanup identity, concurrent Mach-O slice inspection, and transient +DMG verification retries. None changes the SQLite selector. Rebase and current +main verification do not relabel the frozen measurements below. + +The committed post-format driver passes a real SDK smoke against the frozen +runtime. After rebase, a fresh build, real all/selected-column SDK pair and docs +check pass on the updated main. Selected facts match each other and the frozen +runtime; artifact bytes remain unchanged. These are integration checks, not +additional model performance pairs. + +## Real application data and question + +Use QGIS's bundled `world_map.gpkg`, unmodified from official immutable source +commit `e1223b8e9e71fc50ee995ed556f711c54ccc101b`. `corpus.json` pins its URL, +12,914,688-byte size, Git blob `c9ff80228dff0de93c9acdef16a97545ba360244`, and +SHA-256 `01d293159d1b77bd9212b5252587853f61aa9e25b2387135f34afaba8d057190`. +Streaming acquisition matches the upstream blob. The upstream resource install +list includes `data/*`; [its README](https://github.com/qgis/QGIS/blob/e1223b8e9e71fc50ee995ed556f711c54ccc101b/resources/data/README_world_map.md) +records data provenance. This is shipped application data, not a generated REA +fixture. QGIS is neither installed nor executed. + +The source question asks for the complete returned `countries` table schema +and one sample's `fid`, `NAME`, `ISO_A3` tagged cells, in that order. It preserves +database/WAL identity, engine/encoding, exact original SQL and columns, integer +strings, text bytes, nulls, row limit/count, unspecified order, truncation and +both producer/outer limitations. It does not require geometry blobs or a full +country inventory. Neither political labels nor the sampled ordering are +inferred to be current or globally exhaustive. + +SQLite already defaults to compact schema inventory without a table, detailed +selected-table schema with a table, and exposes exact `columns`. Selecting +columns avoids constructing unrelated cells without changing the requested +table schema. Thus compare existing all-visible columns against exact columns +on the same main runtime, rather than changing an old user's default or adding +a new delivery mechanism. Inventory scope cannot substitute for the detailed +schema requested by this question. + +## Public SDK observations + +Frozen runtime: main `172407787f1842dedbcd27b5385177595f786ce4`, compiled +dist/bridge file-table SHA-256 +`72a4ac6c6db491c455f3e4a798f8f52ed5850c08831e7cdc9f25c1525a5a1d11`. +Node 24.18.0, SDK client/server 2.3.1, observed SQLite 3.53.1, WAL null. Driver, +provider settings/search-path fingerprints, artifact and locked dependencies +remain equal. Each workflow starts a fresh server and validates the selected +actual advertised schema. Host page caches are not flushed. + +The initial default inventory returns 26 table entries, including explicit +virtual/shadow classifications, no rows and `not_requested` column details: +27,185 compact client-result JSON bytes. Selecting `countries` reveals eight +columns, including a geometry blob. Its one-row full reply is 485,277 bytes. +The selected request retains every requested declared-schema field and exact +tagged sample values while omitting unrelated sample cells. + +| Trial | Reply bytes | SDK workflow seconds | Payload CPU seconds | Kernel peak bytes | +| ------------- | ----------: | -------------------: | ------------------: | ----------------: | +| sdk-all-1 | 485,277 | 11.820 | 12.755 | 562,884,608 | +| sdk-columns-1 | 18,509 | 14.017 | 13.715 | 557,510,656 | +| sdk-columns-2 | 18,509 | 15.826 | 14.162 | 548,343,808 | +| sdk-all-2 | 485,277 | 5.679 | 7.310 | 561,704,960 | + +Both pairs make one successful call, pass settings/selected-fact comparison, +retain complete original schema and all requested typed cells, and preserve +source bytes. Reply bytes fall about 96.2%. These observations **do not show SDK +speed or CPU improvement**: selected workflows are slower in both pairs and +timing varies substantially. No cause is inferred from these data. Payload CPU +includes runner/catalog work outside the SDK workflow timer. Memory changes +are small and do not establish a general reduction. Raw replies and the exact +pre-format driver source are archived privately. + +Reproduce with `measure.mjs --artifact qgis-world-map.gpkg` and +`--sqlite-selection all|columns`, using the same `--runtime-root`, `--revision`, +artifact path and `--schemas selected`. `--delivery` stays `complete`; this is +an existing request selection, not a new summary API. Original caller arguments +and schemas remain in the private receipts. The source question is +`questions/sqlite-qgis.txt` and the selected factual grader is +`review-model.py --domain sqlite`. + +## Decision and scope + +The initial four actual Codex attempts never executed SQLite: the client rejected +the tool because its private snapshot writes require approval and the isolated +driver lacked this exact tool's approval override. Every factual grade fails; +these are failed client attempts, not completed-task performance comparisons. +All profiles are removed. The existing experiment-only per-tool approval list +now includes `inspect_sqlite_database`; each corrected trial exposes only that +exact enabled tool. REA annotations, target authority and global Codex configuration +are unchanged. The [official configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference) +documents the per-tool override. Corrected cohorts use fresh output directories +and retain the original failures separately. + +Actual repeated Codex comparisons determine the task token/time benefit before +crediting smaller replies. An existing selector that answers the question is +evidence against adding another production mechanism. Keep negative outcomes +and unavailable coverage, including failure/retry costs and profile cleanup. + +Four corrected serial trials use Codex CLI 0.161.0, requested `gpt-5.6-terra` +high, one enabled tool, identical owned context/discovery capture, and the same +frozen main runtime. The requested alias is not a verified server-resolved model. +Equal treatment instructions select the existing all-visible or exact-column +request; the source question and requested schema/sample facts stay fixed. + +| Corrected trial | Input | Cached | Uncached | Output | Seconds | MCP calls | Facts | +| ------------------------ | -----: | -----: | -------: | -----: | ------: | --------: | ----- | +| approved-model-all-1 | 88,131 | 52,480 | 35,651 | 3,369 | 84.007 | 2 | pass | +| approved-model-columns-1 | 37,340 | 20,992 | 16,348 | 3,006 | 87.514 | 1 | pass | +| approved-model-columns-2 | 56,148 | 36,096 | 20,052 | 3,298 | 97.466 | 2 | pass | +| approved-model-all-2 | 88,340 | 52,480 | 35,860 | 3,084 | 113.847 | 2 | pass | + +Both pairs pass every selected producer fact, exact SQL/schema/null/tagged +cells, observed response Evidence IDs, target-byte preservation and profile +cleanup. The grader checks producer observations, not independent geometry +semantics. Actual events contain only the chosen MCP tool and agent messages; +no shell or other agent execution appears. Usage is the final aggregate actually +reported by the CLI, one usage record per trial; cached input remains included +in total input. Output includes 853 / 357 / 523 / 664 reasoning tokens. + +Total input falls **57.63% / 36.44%**, uncached input **54.14% / 44.08%**. +Time is mixed: columns are **4.17% slower** in pair 1 and **14.39% faster** in +pair 2. Output is 10.77% lower / 6.94% higher. Repeated calls remain counted; +pair 1 has two all-column calls versus one selected call, while pair 2 has two +calls on both sides. This supports scoped token savings from using the existing +selector, not a dependable speedup or a new API requirement. Client context and +usage are observed separately from raw SDK reply bytes. + +Model payload CPU seconds / kernel peaks are 7.596 / 763,838,464; +7.772 / 761,143,296; 8.409 / 762,597,376; and 11.759 / 774,025,216. CPU is mixed +and memory differences are small. Payload cleanup/limit observations pass; +missing terminal counters keep every strict whole-resource grade false. + +The original blocked attempts remain separate and never provide comparison +denominators. They each have one failed call, no SQLite result and failed facts: + +| Blocked trial | Input | Cached | Uncached | Output | Seconds | +| --------------- | -----: | -----: | -------: | -----: | ------: | +| model-all-1 | 35,290 | 29,952 | 5,338 | 798 | 59.881 | +| model-columns-1 | 35,356 | 22,016 | 13,340 | 670 | 44.764 | +| model-columns-2 | 35,034 | 20,992 | 14,042 | 639 | 30.007 | +| model-all-2 | 35,104 | 20,992 | 14,112 | 673 | 25.132 | + +**Decision: no production/API change.** Existing column selection materially +reduces unnecessary delivery and actual model input while retaining the complete +requested schema and exact cells. Existing documentation already recommends +table/column selection. No additional summary, schema-scope default change, +automatic field omission, plugin layer or cross-session cache is justified by +these results. Preserve the negative/mixed time, output and CPU findings. + +Real one-shot CLI inventory, all-column sample and exact-column sample match +the corresponding full MCP normalized results, subjects, parameters and IDs; +the source digest remains unchanged. An independent Python binding using SQLite +3.40.1 opens this immutable artifact read-only and agrees with the exact stored +table SQL, eight declared columns and selected tagged sample cells. This is a +second engine/binding observation of this file, not a general row-order or +geometry-semantics guarantee. The six existing context/driver regression tests +pass; Python compilation and JavaScript syntax checks pass. No new product test +or production implementation is added for this measurement-only finding. + +Manual review tightens the SQLite grader to distinguish missing fields from +explicit null and preserve JSON scalar types. Regrading all four stored model +answers still passes every selected fact; deliberate omission of `wal` and a +boolean substituted for numeric `row_limit` both fail. Original transcripts, +usage and previous review receipts stay intact; no model trial is rerun. + +Heavy tasks remain serial under one CPU, unchanged 3 GiB early stop / 4 GiB hard +memory, no swap, owned task scopes and host guards. SDK payload observations +verify cleanup and zero phase limit events; final whole-scope counters remain +unknown. This does not establish live/WAL atomicity, all SQLite applications, +other runtimes/platforms or geospatial geometry semantics. Other packet/signal +and capture lanes remain incremental follow-ups using their existing controls. diff --git a/experiments/analysis-efficiency/test_codex_context.py b/experiments/analysis-efficiency/test_codex_context.py new file mode 100644 index 000000000..37df83a7c --- /dev/null +++ b/experiments/analysis-efficiency/test_codex_context.py @@ -0,0 +1,175 @@ +"""Distinct capture/cleanup failures; simulated CLI is not real-model evidence.""" + +import importlib.util +import io +import json +import os +import runpy +import sys +from pathlib import Path +import tempfile +import unittest +from unittest.mock import Mock, patch + +from codex_context import capture_tool_context, selected_event + + +class ManagedCoverageTests(unittest.TestCase): + def test_verifies_extra_counts_and_preserves_unknown_fields(self): + review = runpy.run_path(str(Path(__file__).with_name('review-model.py'))) + project = review['scope_with_verified_counts'] + expected = {'state': 'partial', 'issues': ['unreturned rows remain unknown']} + original = {**expected, 'module_ref_count': 0, 'pinvoke_import_count': 2} + scope, checks = project(original, expected, {'module_ref_count': 0, 'pinvoke_import_count': 2}) + self.assertEqual(scope, expected) + self.assertTrue(all(checks.values())) + self.assertEqual(original['pinvoke_import_count'], 2) + for count in [3, '2', True]: + scope, checks = project({**expected, 'pinvoke_import_count': count}, expected, {'pinvoke_import_count': 2}) + self.assertFalse(checks['pinvoke_import_count']) + _, checks = project({**expected, 'module_ref_count': False}, {**expected, 'module_ref_count': 0}, {'module_ref_count': 0}) + self.assertFalse(checks['module_ref_count']) + scope, _ = project({**expected, 'unsupported_claim': True}, expected, {}) + self.assertNotEqual(scope, expected) + scope, _ = project({'state': 'partial', 'module_ref_count': 0}, expected, {'module_ref_count': 0}) + self.assertNotEqual(scope, expected) + ambiguous = review['named_scope']({'native_boundaries': expected, 'native_boundary_declarations': {'state': 'complete'}}, ['native_boundaries', 'native_boundary_declarations']) + scope, _ = project(ambiguous, expected, {'module_ref_count': 0}) + self.assertNotEqual(scope, expected) + + +class ContextCaptureTests(unittest.TestCase): + def test_filters_ambient_account_and_nested_usage_state(self): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + home = root / 'home' + sessions = home / 'sessions' + sessions.mkdir(parents=True) + output = root / 'output' + output.mkdir() + events = [ + {'type': 'world_state', 'payload': {'state': {'env': 'ambient-marker'}}}, + {'type': 'session_meta', 'payload': {'creator_account_id': 'account-marker'}}, + {'type': 'response_item', 'payload': { + 'type': 'custom_tool_call_output', 'call_id': 'original-call', + 'output': 'caller-selected evidence and paths', + 'internal_chat_message_metadata_passthrough': 'private-marker'}}, + {'type': 'token_usage_record', 'payload': { + 'response_id': 'original-response', 'usage': { + 'input_tokens': 12, 'cached_input_tokens': 4, + 'environment': 'nested-ambient-marker'}, + 'transport_auth': 'auth-marker'}}, + ] + (sessions / 'rollout.jsonl').write_text(''.join(json.dumps(x) + '\n' for x in events)) + (home / 'auth.json').write_text('copied-credential-marker') + receipt = capture_tool_context(home, output) + text = (output / 'codex-tool-context.jsonl').read_text() + self.assertEqual(receipt['status'], 'captured') + self.assertEqual(receipt['retained_events'], 2) + for marker in ['ambient-marker', 'account-marker', 'private-marker', + 'auth-marker', 'copied-credential-marker']: + self.assertNotIn(marker, text) + self.assertIn('caller-selected evidence and paths', text) + self.assertIn('original-response', text) + self.assertEqual((output / 'codex-tool-context.jsonl').stat().st_mode & 0o777, 0o600) + + def test_missing_rollouts_are_unknown_and_malformed_lines_remain_partial(self): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + output = root / 'missing' + output.mkdir() + self.assertEqual(capture_tool_context(root / 'home', output)['status'], 'unavailable') + sessions = root / 'home' / 'sessions' + sessions.mkdir(parents=True) + (sessions / 'rollout.jsonl').write_text('not-json\n' + json.dumps({ + 'type': 'event_msg', 'payload': {'type': 'token_count', 'info': None}}) + '\n') + partial = root / 'partial' + partial.mkdir() + receipt = capture_tool_context(root / 'home', partial) + self.assertEqual(receipt['status'], 'partial') + self.assertEqual(receipt['errors'][0]['line'], 1) + self.assertEqual(receipt['retained_events'], 1) + with self.assertRaises(ValueError): + selected_event({'type': 'token_usage_record', 'payload': {'usage': {'input_tokens': True}}}) + with self.assertRaises(ValueError): + selected_event({'type': {'environment': 'unexpected'}, 'payload': {}}) + with self.assertRaises(ValueError): + selected_event({'type': 'response_item', 'timestamp': {'environment': 'unexpected'}, 'payload': {}}) + unknown = selected_event({'type': 'event_msg', 'payload': {'type': 'token_count', 'info': {'model_context_window': None}}}) + self.assertIsNone(unknown['payload']['info']['model_context_window']) + + def test_capture_failure_still_removes_trial_credentials_and_profile(self): + spec = importlib.util.spec_from_file_location('agent_trial', Path(__file__).with_name('agent-trial.py')) + agent = importlib.util.module_from_spec(spec) + spec.loader.exec_module(agent) + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + runtime = root / 'runtime' + (runtime / 'scripts').mkdir(parents=True) + (runtime / 'scripts' / 'rea.mjs').write_text('') + (runtime / 'package-lock.json').write_text('{}') + auth_home = root / 'source-auth' + auth_home.mkdir() + (auth_home / 'auth.json').write_text('synthetic-credential') + question = root / 'question.txt' + question.write_text('Observe the declared fixture.') + output = root / 'trial' + child = Mock(stdin=io.StringIO()) + child.wait.return_value = 0 + arguments = ['agent-trial.py', '--runtime-root', str(runtime), '--revision', 'fixture', + '--prompt', str(question), '--output', str(output), '--capture-tool-context'] + with patch.dict(os.environ, {'CODEX_HOME': str(auth_home)}, clear=True), \ + patch.object(sys, 'argv', arguments), \ + patch.object(agent.shutil, 'which', return_value='/fixture/node'), \ + patch.object(agent.subprocess, 'check_output', return_value='v24.18.0\n'), \ + patch.object(agent.subprocess, 'Popen', return_value=child), \ + patch.object(agent, 'capture_tool_context', side_effect=OSError('fixture capture failure')), \ + patch('builtins.print'): + with self.assertRaisesRegex(OSError, 'fixture capture failure'): + agent.main() + self.assertFalse(list(output.glob('profile-*'))) + self.assertTrue(json.loads((output / 'cleanup.json').read_text())['profile_removed']) + self.assertEqual((auth_home / 'auth.json').read_text(), 'synthetic-credential') + + def test_refuses_foreign_session_directory_and_symlink_records(self): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + home = root / 'home' + home.mkdir() + foreign = root / 'foreign' + foreign.mkdir() + (foreign / 'rollout.jsonl').write_text('private marker') + (home / 'sessions').symlink_to(foreign, target_is_directory=True) + output = root / 'directory-result' + output.mkdir() + receipt = capture_tool_context(home, output) + self.assertEqual(receipt['status'], 'partial') + self.assertEqual(receipt['retained_events'], 0) + (home / 'sessions').unlink() + (home / 'sessions').mkdir() + (home / 'sessions' / 'linked.jsonl').symlink_to(foreign / 'rollout.jsonl') + output = root / 'file-result' + output.mkdir() + receipt = capture_tool_context(home, output) + self.assertEqual(receipt['status'], 'partial') + self.assertEqual(receipt['errors'][0]['reason'], 'not_an_owned_regular_file') + self.assertEqual((foreign / 'rollout.jsonl').read_text(), 'private marker') + + def test_guidance_requires_selected_tools_before_acquiring_a_profile(self): + spec = importlib.util.spec_from_file_location('agent_trial', Path(__file__).with_name('agent-trial.py')) + agent = importlib.util.module_from_spec(spec) + spec.loader.exec_module(agent) + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + output = root / 'trial' + arguments = ['agent-trial.py', '--runtime-root', str(root), '--revision', 'fixture', + '--prompt', str(root / 'question'), '--output', str(output), '--guide-enabled-tools'] + with patch.object(sys, 'argv', arguments), patch.object(sys, 'stderr', io.StringIO()): + with self.assertRaises(SystemExit) as raised: + agent.main() + self.assertEqual(raised.exception.code, 2) + self.assertFalse(output.exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/experiments/analysis-efficiency/test_resource_payload.py b/experiments/analysis-efficiency/test_resource_payload.py new file mode 100644 index 000000000..3f091efb9 --- /dev/null +++ b/experiments/analysis-efficiency/test_resource_payload.py @@ -0,0 +1,103 @@ +"""Receipt semantics; real systemd/cgroup workflows are verified separately.""" + +import json +import importlib.util +import io +from pathlib import Path +import sys +import tempfile +import unittest +from unittest.mock import patch + +from resource_payload import read_observation + + +def receipt(): + return { + 'phase': 'payload-exited-observer-alive', 'ownership_token': 'own-unit', + 'payload_exit_code': 3, 'observer_pid': 100, 'remaining_processes': [100], + 'payload_cleanup_verified': True, 'memory_peak_bytes': 123, + 'control_group': 'user.slice/own-unit.scope', + 'resource_events': {'memory.events': {'high': 0, 'max': 0, 'oom': 0, 'oom_kill': 0}, + 'pids.events': {'max': 0}}, + 'cpu_stat': {'usage_usec': 1000}, + } + + +class PayloadObservationTests(unittest.TestCase): + def test_observer_capacity_failure_precedes_any_process_acquisition(self): + spec = importlib.util.spec_from_file_location('resource_run', Path(__file__).with_name('resource-run.py')) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + arguments = ['resource-run.py', '--observe-payload-exit', '--task-ceiling', '1', '--', 'payload'] + with patch.object(sys, 'argv', arguments), patch.object(sys, 'stderr', io.StringIO()), \ + patch.object(module.subprocess, 'Popen') as spawn: + with self.assertRaises(SystemExit) as failure: + module.main() + self.assertEqual(failure.exception.code, 2) + spawn.assert_not_called() + + def test_preserves_nonzero_status_kernel_peak_and_nonzero_events(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / 'receipt.json' + value = receipt() + value['resource_events']['memory.events']['oom'] = 1 + path.write_text(json.dumps(value)) + observed = read_observation(path, 'own-unit') + self.assertEqual(observed['payload_exit_code'], 3) + self.assertEqual(observed['memory_peak_bytes'], 123) + self.assertEqual(observed['resource_events']['memory.events']['oom'], 1) + + def test_rejects_missing_malformed_wrong_owner_and_inconsistent_cleanup(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / 'receipt.json' + self.assertIsNone(read_observation(path, 'own-unit')) + path.write_text('incomplete-json') + self.assertIsNone(read_observation(path, 'own-unit')) + cases = [] + for key, invalid in [('ownership_token', 'other-unit'), ('observer_pid', True), + ('memory_peak_bytes', -1), ('remaining_processes', [100, 101]), + ('payload_cleanup_verified', 'true'), ('phase', 'scope-exited')]: + value = receipt() + value[key] = invalid + cases.append(value) + value = receipt() + del value['resource_events']['memory.events']['oom'] + cases.append(value) + value = receipt() + value['cpu_stat']['usage_usec'] = False + cases.append(value) + for value in cases: + with self.subTest(value=value): + path.write_text(json.dumps(value)) + self.assertIsNone(read_observation(path, 'own-unit')) + + def test_retains_lingering_actor_facts_without_certifying_cleanup(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / 'receipt.json' + value = receipt() + value['remaining_processes'].append(101) + value['payload_cleanup_verified'] = False + path.write_text(json.dumps(value)) + observed = read_observation(path, 'own-unit') + self.assertEqual(observed['remaining_processes'], [100, 101]) + self.assertFalse(observed['payload_cleanup_verified']) + + def test_excludes_unrelated_metadata_and_foreign_symlinks(self): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / 'receipt.json' + value = receipt() + value['environment'] = {'ambient': 'excluded'} + value['resource_events']['unrelated'] = {'ambient': 'excluded'} + path.write_text(json.dumps(value)) + observed = read_observation(path, 'own-unit') + self.assertNotIn('environment', observed) + self.assertNotIn('unrelated', observed['resource_events']) + link = Path(directory) / 'linked.json' + link.symlink_to(path) + self.assertIsNone(read_observation(link, 'own-unit')) + self.assertEqual(json.loads(path.read_text()), value) + + +if __name__ == '__main__': + unittest.main() diff --git a/experiments/analysis-efficiency/windows-empty-profile.md b/experiments/analysis-efficiency/windows-empty-profile.md new file mode 100644 index 000000000..f8e5558e0 --- /dev/null +++ b/experiments/analysis-efficiency/windows-empty-profile.md @@ -0,0 +1,69 @@ +# Windows empty-profile startup verification + +Follow-up to [#2345](https://github.com/morluto/rea/pull/2345), including +@gefrezim's diagnosis of the import-time Windows home lookup. + +## Source and boundary + +Baseline: main `172407787f1842dedbcd27b5385177595f786ce4`. Verification used +the real Windows 11 10.0.22631.0 host, official Windows x64 Node 24.18.0, +locked production dependencies and REA's compiled public CLI / SDK 2.3.1 MCP +server. No IDA or Ghidra engine was used. Runtime copies and compact receipts +live outside the checkout; no account profile path or ambient environment is +recorded here. + +The tested dispatcher SHA-256 is +`526105418604cc6e5a202a6275b700814e27450bfaffd45e7510530ba669de8d`. +Only the dispatcher changed in the deployed runtime. It treats an empty Windows +`USERPROFILE` as unset before dependency imports. Nonempty selections continue +to reach the existing home resolver; no additional lookup or fallback owner is +introduced. + +## Real Windows observations + +With `HOME` empty in each case, the baseline produced: + +| USERPROFILE selection | `--version` | `--help` | MCP discovery | +| --------------------------- | ----------------------- | ----------------------- | ------------- | +| Unset | Exit 0 | Exit 0 | Healthy | +| Empty | Exit 1, `uv_os_homedir` | Exit 1, `uv_os_homedir` | Healthy | +| Nonempty test-owned profile | Exit 0 | Exit 0 | Healthy | + +The corrected CLI passed all six invocations with no stderr. Version output +remained 6 bytes and help output 15,497 bytes. Real setup dry runs with empty +and nonempty profile selections both exited 0, planned their configuration +under the expected home, preserved existing configuration bytes and created no +configuration under the working directory. No installation was performed. + +MCP was already healthy in the baseline; this change does not claim to repair +an MCP startup failure. Complete baseline discovery was 187 tools and 2,545,790 +serialized bytes, SHA-256 +`1e6bbca7f62852134eb703ea098f5a302d1fe333b8433475429f6fc1b1aba18f`. +All three corrected MCP controls also passed with no stderr and the same +catalogue bytes and digest. + +The existing `homeDirectoryFallback` acceptance test exercises the import-time +failure through the public setup dry run. Adding it to the Windows curated lane +makes that regression execute on the affected platform. No duplicate startup +test was retained. Nine related tests passed, including the existing MCP doctor +and curated-lane path checks; Linux passing alone does not prove Windows behavior. +Review caught a missing package-scope registration for the newly listed test; +the original CI shard failed that ownership invariant. The path is now also +registered in `scripts/ci/scopes.mjs`, and all 84 scope checks plus the two +curated-path checks pass. Runtime source and its tested digest are unchanged. + +## Efficiency and resource limits + +Heavy host probes ran serially at BelowNormal priority, with one CPU and a +512 MiB CLI/server heap setting (256 MiB for the probe parent). Heap settings do +not bound total process memory. An exit-time `process.resourceUsage()` observer +recorded individual corrected CLI invocations: CPU time ranged from 7.968 to +9.874 seconds and peak working set from 299,956 to 301,852 KiB. These figures +exclude the probe parent and any observer overhead outside the CLI process. +The six observed wall times ranged from 8.656 to 10.961 seconds. + +The baseline did not use that resource observer, and cold/warm caches were not +normalized. These observations establish functional behavior and bounded probe +scope; no CPU, memory or latency improvement is claimed. The fix adds one +constant-time environment check, no filesystem lookup, engine call, retry or +cache. Output bytes are not model tokens; actual model usage was not measured. diff --git a/experiments/analysis-efficiency/windows-runtime-retry.md b/experiments/analysis-efficiency/windows-runtime-retry.md new file mode 100644 index 000000000..2286727e8 --- /dev/null +++ b/experiments/analysis-efficiency/windows-runtime-retry.md @@ -0,0 +1,107 @@ +# Windows runtime admission retry verification + +Scope: [#2257](https://github.com/morluto/rea/issues/2257). Related initial +diagnosis: [#2266](https://github.com/morluto/rea/pull/2266). + +## Revisions and real input + +The baseline is `4f4f6cd7b5d7a400b90772a138d7b9f942c2a556`. +The candidate was developed from +`4773c152bc5f299fa682575bb8d1efea7587c7bc`; relevant runtime, native and +dependency-lock sources are identical between those two revisions. +These measurements precede integration of subsequent main changes. + +The host ran Windows 11 10.0.22631.0, official Windows x64 Node 24.18.0, +and locked production dependencies. The real application input was the official +npm 11.16.0 launcher distribution's `bin` directory. REA inspected that source; +it did not execute the application as an analysis target. Runtime copies, +raw replies and test executables remain outside the checkout. No IDA or Ghidra +engine was involved in this native-runtime verification. + +## Correctness and recovery + +A test-owned directory handle requesting `FILE_ADD_FILE` produced an actual +kernel sharing violation (Win32 32) during native runtime-parent admission. +Releasing that handle restored admission. Before the fix, public CLI analysis +reported a permanent `unsupported_provider` failure with `retryable: false`. +The corrected CLI preserves `capability_unavailable` and the reason, with +`category: unavailable` and `retryable: true`. + +Normal CLI analysis and post-conflict recovery produced the same canonical +normalized result before and after the correction: 535,733 compact JSON bytes, +SHA-256 `a24d3c2d9897cccc5ba70e9ee4dce03da88f033a939fe87457136fc5b3a3e2db`. +The complete successful CLI reply remained 537,124 bytes. + +A single real SDK 2.3.1 stdio MCP connection first completed analysis, then +encountered the same kernel conflict after native authority caching, then +recovered successfully when the handle was released. Its final receipt passed +and found no residual runtime directories. The native producer supplies +`runtimeAllocation: "not-started"` only when parent admission failed before +directory creation. The adapter requires that fact and exact numeric codes +32/33; permission failures, opaque error text and unknown allocation state +remain nonretryable. Incomplete cleanup also prevents retry. + +The native verifier additionally reproduces a real sharing conflict using an +owned runtime's DELETE lease, verifies the original error and allocation fact, +and confirms no child directory was allocated. This case runs unconditionally +in the Windows native verifier, without the optional process-boundary fixture. +The full verifier passed with 20 positive controls. Its optional independently +built process-boundary fixture was not supplied in this run. + +The related focused suite passed 99 tests across seven files, including worker +ownership, cancellation, cleanup, error projection, loader behavior and adapter +boundaries. Source-map and WABT acquisition-failure tests use injected failures; +they establish disposition propagation, not real engine execution. + +Thirty baseline native self-tests passed with no residual directories. +Win32 5 from #1701/#2196 was not reproduced on this host; these results do not +establish its cause or resolution. + +## Delivery and resource measurements + +One final same-connection MCP trial used one CPU per Node process, BelowNormal +priority, a 512 MiB client heap setting and a 768 MiB server heap setting. +Heap settings do not bound total process or family memory. + +| Stage | Observed wall time | Serialized reply bytes | +| ---------------------------------- | -----------------: | ---------------------: | +| Connect | 11,351 ms | Not recorded | +| Complete tool discovery, 187 tools | 744 ms | 2,498,686 | +| Normal analysis | 12,887 ms | 1,126,797 | +| Sharing failure | 265 ms | 878 | +| Recovery on the same connection | 5,578 ms | 1,126,797 | + +The earlier warm failure reply was 1,218 bytes. Successful reply sizes and the +catalogue digest were unchanged within the tested source comparison: +`7bdadddc909f4b2b093f0b3da9f79fafdac879c9d3c147938b8fbce1b52cd726`. +These are delivery bytes, not model tokens. Model-visible discovery handling, +actual model token usage and total model task cost were not measured. + +A targeted process-generation sampler collected 343 observations over +35,630 ms. Its aggregate observed CPU time was a **lower bound** of 26,766 ms: +process exits can hide the final CPU tail. Its peak sampled working-set sum was +727,244,800 bytes (about 694 MiB). This is a sampled sum, can double-count shared +pages and is not an exact physical-memory peak. Only the test-owned Node and +directory-holder processes were included; the observer itself was excluded. + +This is one controlled functional trial, with no paired CPU/memory baseline. +Cold/warm filesystem caches and host noise were not normalized. No speedup, +CPU reduction, memory reduction or model-token savings are claimed. The change +adds no analysis retry loop or cache and performs no additional engine calls. +Existing successful native authority caching remains intact; failed readiness +is retried by a later caller attempt. Retry becomes useful advice only after +the transient condition clears and cleanup permits another attempt. + +## Integration replay + +After rebasing onto main `a2d8b94dd`, runtime candidate +`2c7a09eaf3ffe26667b40081f1cf0fd2ce44a146` again passed the 99 related tests, +static and documentation gates, real Windows CLI and same-connection MCP +normal/conflict/recovery sequence. Both workflows found no residual directories; +the CLI normalized-result digest above still matched. The MCP success and error +reply sizes remained 1,126,797 and 878 bytes respectively. Upstream Android/SAZ +contract changes increased complete discovery to 2,517,904 bytes, digest +`d14588eab7404ad129907eb34a45a0db0d43233c4de829f76babd59723bed199`. +This later catalogue is not evidence of a delivery-size change caused by the +runtime-admission fix. Resource sampling above belongs to the earlier pinned +candidate; aggregate resources were not resampled for this integration replay. diff --git a/install.sh b/install.sh index 46260fe71..c18726611 100755 --- a/install.sh +++ b/install.sh @@ -167,7 +167,7 @@ main() { [ "$installed_version" = "$version" ] || fail "installed version $installed_version does not match $version. Reinstall the requested version, then retry." printf 'REA %s is installed.\n' "$version" - if [ "$start_setup" = true ] && [ -r /dev/tty ] && [ -w /dev/tty ] && [ -t 1 ]; then + if [ "$start_setup" = true ] && [ -r /dev/tty ] && [ -w /dev/tty ] && [ -t 1 ] && [ -t 2 ]; then printf 'Starting REA setup...\n' "$install_bin" setup /dev/tty else diff --git a/licenses/LGPL-2.0.txt b/licenses/LGPL-2.0.txt new file mode 100644 index 000000000..ede5d5441 --- /dev/null +++ b/licenses/LGPL-2.0.txt @@ -0,0 +1,480 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see . + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Moe Ghoul, President of Vice + +That's all there is to it! diff --git a/licenses/README.md b/licenses/README.md index db0c9d05e..c811a4f76 100644 --- a/licenses/README.md +++ b/licenses/README.md @@ -4,19 +4,20 @@ Start with [THIRD_PARTY_NOTICES.md](../THIRD_PARTY_NOTICES.md) for the distincti between distributed material and separately obtained tools. These files retain upstream texts; they do not change [REA's MIT license](../LICENSE). -| Files | Provenance and scope | -| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `npm-dependencies.txt` | Every package path in the root lockfile, with its exact version, declared license, scope, download URL, and integrity. Includes development and optional platform entries. | -| `npm-runtime-notices.txt` | Original license, copyright, and NOTICE texts collected from integrity-verified locked runtime npm archives across all platforms; also the license of Rolldown's generated runtime helpers. The archive manifest's name and version are checked. | -| `nativeaot-parser-MIT.txt` | Original Washi notice for derived NativeAOT parser code; source revision is recorded in the parser and the root notices. | -| `dotnet-runtime-MIT.txt` | Original .NET Foundation MIT text from the NativeAOT reference revision `a3b2d40328be0be3f8dd43f0e5cc925b8827b044`. | -| `ghidra-12.1.4-{LICENSE,NOTICE,DISCLAIMER}.txt` | Unchanged top-level documents from `Ghidra_12.1.4_build`. Ghidra is not bundled; these reference copies do not replace its component and GPL support-program notices. The US-government-specific disclaimer applies to Ghidra, not to REA. | -| `cfworker-MIT.txt`, `xterm-MIT.txt` | Original notices missing from their published runtime npm archives, recovered from the releases' upstream Git revisions. They are included in the corresponding runtime entries. | -| `Apache-2.0.txt`, `MIT-template.txt` | Standard license texts for explicitly documented upstream notice gaps. The MIT placeholders are not an attribution to an inferred author or year. | -| `MinGW-w64-runtime.txt` | Upstream's combined runtime copyright and license notices, snapshot from v12.0.0, for the statically linked Windows addon. This is a notice snapshot, not a pin of the compiler used in release CI. | -| `GPL-3.0.txt`, `GCC-Runtime-Library-Exception-3.1.txt` | Unchanged GPLv3 and GCC runtime exception texts from GCC 14.2.0. The exception permits eligible compiled combinations under its conditions; the runtime keeps its own license. This snapshot does not assert that every release uses GCC 14.2.0. | -| `Node-22.19.0-LICENSE.txt` | The original Node 22.19.0 license and third-party notices. The Windows addon uses Node-API headers from that release; the complete Node runtime and all components listed in this reference document are not bundled. | -| `upstream-sources.json` | Source URLs and SHA-256 digests for the new unchanged reference and supplemental texts. These digests identify the preserved local texts. | +| Files | Provenance and scope | +| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `npm-dependencies.txt` | Every package path in the root lockfile, with its exact version, declared license, scope, download URL, and integrity. Includes development and optional platform entries. | +| `npm-runtime-notices.txt` | Original license, copyright, and NOTICE texts collected from integrity-verified locked runtime npm archives across all platforms; also the license of Rolldown's generated runtime helpers. The archive manifest's name and version are checked. | +| `nativeaot-parser-MIT.txt` | Original Washi notice for derived NativeAOT parser code; source revision is recorded in the parser and the root notices. | +| `dotnet-runtime-MIT.txt` | Original .NET Foundation MIT text from the NativeAOT reference revision `a3b2d40328be0be3f8dd43f0e5cc925b8827b044`. | +| `ghidra-12.1.4-{LICENSE,NOTICE,DISCLAIMER}.txt` | Unchanged top-level documents from `Ghidra_12.1.4_build`. Ghidra is not bundled; these reference copies do not replace its component and GPL support-program notices. The US-government-specific disclaimer applies to Ghidra, not to REA. | +| `cfworker-MIT.txt`, `xterm-MIT.txt` | Original notices missing from their published runtime npm archives, recovered from the releases' upstream Git revisions. They are included in the corresponding runtime entries. | +| `Apache-2.0.txt`, `MIT-template.txt` | Standard license texts for explicitly documented upstream notice gaps. The MIT placeholders are not an attribution to an inferred author or year. | +| `frida-17.23.2-COPYING.txt`, `LGPL-2.0.txt` | Unchanged licensing supplements for the optional Frida dependency: tagged Frida wxWindows notice and GNU Library GPL v2 text. The npm archive and tagged Node binding omit a standalone license/copyright document; these texts do not recover binding or prebuild-component attribution. | +| `MinGW-w64-runtime.txt` | Upstream's combined runtime copyright and license notices, snapshot from v12.0.0, for the statically linked Windows addon. This is a notice snapshot, not a pin of the compiler used in release CI. | +| `GPL-3.0.txt`, `GCC-Runtime-Library-Exception-3.1.txt` | Unchanged GPLv3 and GCC runtime exception texts from GCC 14.2.0. The exception permits eligible compiled combinations under its conditions; the runtime keeps its own license. This snapshot does not assert that every release uses GCC 14.2.0. | +| `Node-22.19.0-LICENSE.txt` | The original Node 22.19.0 license and third-party notices. The Windows addon uses Node-API headers from that release; the complete Node runtime and all components listed in this reference document are not bundled. | +| `upstream-sources.json` | Source URLs and SHA-256 digests for the new unchanged reference and supplemental texts. These digests identify the preserved local texts. | Additional preserved originals live at [evmole/LICENSE](../third_party/evmole/LICENSE), @@ -40,6 +41,10 @@ only license and author metadata: their missing original copyright documents remain explicitly identified in the runtime texts. Do not describe those entries as complete recovered attribution. +`frida@17.23.2` also lacks an original standalone notice in its npm archive and +tagged Node source. Its declared license and the preserved licensing supplements +are recorded explicitly without inferring a copyright holder or year. + These records do not establish the legal accuracy of upstream metadata or prove that every upstream source-file attribution has been supplied in an archive. Review and refresh them when dependencies change; compare reference @@ -52,3 +57,12 @@ runtime/component notices with the retained snapshots and update them if they differ. Do not assume that a compiler change leaves redistribution requirements unchanged. Preserve applicable originals with any additionally bundled engine; top-level reference copies alone may not cover its entire distribution. + +Generate the exact locked inventory with `npm run licenses:generate`. After +refreshing verified runtime notices, update their header fingerprint to the +generator's reported `runtime_dependency_fingerprint`, then run +`npm run licenses:check`; `docs:check` also runs this check. It compares the +inventory, runtime package identities, +license declarations, archive URLs/integrity, runtime dependency fingerprint, +and preserved reference digests. It does not verify legal completeness or +replace inspection of original upstream notices. diff --git a/licenses/frida-17.23.2-COPYING.txt b/licenses/frida-17.23.2-COPYING.txt new file mode 100644 index 000000000..b01d49c67 --- /dev/null +++ b/licenses/frida-17.23.2-COPYING.txt @@ -0,0 +1,50 @@ + wxWindows Library Licence, Version 3.1 + ====================================== + +Copyright (c) 1998-2005 Julian Smart, Robert Roebling et al + +Everyone is permitted to copy and distribute verbatim copies +of this licence document, but changing it is not allowed. + + WXWINDOWS LIBRARY LICENCE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Library General Public Licence as published by +the Free Software Foundation; either version 2 of the Licence, or (at your +option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +Licence for more details. + +You should have received a copy of the GNU Library General Public Licence +along with this software, usually in a file named COPYING.LIB. If not, +write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth +Floor, Boston, MA 02110-1301 USA. + +EXCEPTION NOTICE + +1. As a special exception, the copyright holders of this library give +permission for additional uses of the text contained in this release of the +library as licenced under the wxWindows Library Licence, applying either +version 3.1 of the Licence, or (at your option) any later version of the +Licence as published by the copyright holders of version 3.1 of the Licence +document. + +2. The exception is that you may use, copy, link, modify and distribute +under your own terms, binary object code versions of works based on the +Library. + +3. If you copy code from files distributed under the terms of the GNU +General Public Licence or the GNU Library General Public Licence into a +copy of this library, as this licence permits, the exception does not apply +to the code that you add in this way. To avoid misleading anyone as to the +status of such modified files, you must delete this exception notice from +such code and/or adjust the licensing conditions notice accordingly. + +4. If you write modifications of your own for this library, it is your +choice whether to permit this exception to apply to your modifications. If +you do not wish that, you must delete the exception notice from such code +and/or adjust the licensing conditions notice accordingly. diff --git a/licenses/npm-dependencies.txt b/licenses/npm-dependencies.txt index 7ae0aa0ad..ce45f7459 100644 --- a/licenses/npm-dependencies.txt +++ b/licenses/npm-dependencies.txt @@ -2,7 +2,7 @@ REA npm dependency inventory Prepared from the root package-lock.json; refresh this inventory when locked dependencies change. License identifiers are upstream lockfile declarations, not a legal assessment. Runtime includes transitive and optional platform packages; development includes build, test and website tooling. -Locked package entries: 561; runtime: 148. +Locked package entries: 586; runtime: 174. Full runtime copyright/license/NOTICE texts: npm-runtime-notices.txt. @algolia/abtesting@1.25.0 | development | MIT @@ -1375,11 +1375,31 @@ base64-js@1.5.1 | runtime | MIT Package: https://www.npmjs.com/package/base64-js/v/1.5.1 Archive: https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz Integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bindings@1.5.0 | runtime, optional | MIT + Lockfile path: node_modules/bindings + Package: https://www.npmjs.com/package/bindings/v/1.5.0 + Archive: https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz + Integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== birpc@2.9.0 | development | MIT Lockfile path: node_modules/birpc Package: https://www.npmjs.com/package/birpc/v/2.9.0 Archive: https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz Integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw== +bl@4.1.0 | runtime, optional | MIT + Lockfile path: node_modules/bl + Package: https://www.npmjs.com/package/bl/v/4.1.0 + Archive: https://registry.npmjs.org/bl/-/bl-4.1.0.tgz + Integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== +buffer@5.7.1 | runtime, optional | MIT + Lockfile path: node_modules/bl/node_modules/buffer + Package: https://www.npmjs.com/package/buffer/v/5.7.1 + Archive: https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz + Integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== +readable-stream@3.6.2 | runtime, optional | MIT + Lockfile path: node_modules/bl/node_modules/readable-stream + Package: https://www.npmjs.com/package/readable-stream/v/3.6.2 + Archive: https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz + Integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== brace-expansion@5.0.12 | runtime | MIT Lockfile path: node_modules/brace-expansion Package: https://www.npmjs.com/package/brace-expansion/v/5.0.12 @@ -1430,6 +1450,11 @@ character-entities-legacy@3.0.0 | development | MIT Package: https://www.npmjs.com/package/character-entities-legacy/v/3.0.0 Archive: https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz Integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== +chownr@1.1.4 | runtime, optional | ISC + Lockfile path: node_modules/chownr + Package: https://www.npmjs.com/package/chownr/v/1.1.4 + Archive: https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz + Integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== clean-git-ref@2.0.1 | runtime | Apache-2.0 Lockfile path: node_modules/clean-git-ref Package: https://www.npmjs.com/package/clean-git-ref/v/2.0.1 @@ -1485,6 +1510,11 @@ decompress-response@6.0.0 | runtime | MIT Package: https://www.npmjs.com/package/decompress-response/v/6.0.0 Archive: https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz Integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== +deep-extend@0.6.0 | runtime, optional | MIT + Lockfile path: node_modules/deep-extend + Package: https://www.npmjs.com/package/deep-extend/v/0.6.0 + Archive: https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz + Integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== define-data-property@1.1.4 | runtime | MIT Lockfile path: node_modules/define-data-property Package: https://www.npmjs.com/package/define-data-property/v/1.1.4 @@ -1495,7 +1525,7 @@ dequal@2.0.3 | development | MIT Package: https://www.npmjs.com/package/dequal/v/2.0.3 Archive: https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz Integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== -detect-libc@2.1.2 | development | Apache-2.0 +detect-libc@2.1.2 | runtime | Apache-2.0 Lockfile path: node_modules/detect-libc Package: https://www.npmjs.com/package/detect-libc/v/2.1.2 Archive: https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz @@ -1530,6 +1560,11 @@ emoji-regex-xs@1.0.0 | development | MIT Package: https://www.npmjs.com/package/emoji-regex-xs/v/1.0.0 Archive: https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz Integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg== +end-of-stream@1.4.5 | runtime, optional | MIT + Lockfile path: node_modules/end-of-stream + Package: https://www.npmjs.com/package/end-of-stream/v/1.4.5 + Archive: https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz + Integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== entities@7.0.1 | development | BSD-2-Clause Lockfile path: node_modules/entities Package: https://www.npmjs.com/package/entities/v/7.0.1 @@ -1595,6 +1630,11 @@ evmole@0.9.3 | runtime | MIT Package: https://www.npmjs.com/package/evmole/v/0.9.3 Archive: https://registry.npmjs.org/evmole/-/evmole-0.9.3.tgz Integrity: sha512-UhO5HMAoEPCupSxvBJPlm/L0Qk/KVJ/OJo3r4EyhXADIEHqU5aTkAzsBfzk4lXGjqxVnaYbh1GPSmZtmSHFnQQ== +expand-template@2.0.3 | runtime, optional | (MIT OR WTFPL) + Lockfile path: node_modules/expand-template + Package: https://www.npmjs.com/package/expand-template/v/2.0.3 + Archive: https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz + Integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== expect-type@1.4.0 | development | Apache-2.0 Lockfile path: node_modules/expect-type Package: https://www.npmjs.com/package/expect-type/v/1.4.0 @@ -1640,6 +1680,11 @@ fdir@6.5.0 | development | MIT Package: https://www.npmjs.com/package/fdir/v/6.5.0 Archive: https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz Integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== +file-uri-to-path@1.0.0 | runtime, optional | MIT + Lockfile path: node_modules/file-uri-to-path + Package: https://www.npmjs.com/package/file-uri-to-path/v/1.0.0 + Archive: https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz + Integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== focus-trap@7.8.0 | development | MIT Lockfile path: node_modules/focus-trap Package: https://www.npmjs.com/package/focus-trap/v/7.8.0 @@ -1655,6 +1700,16 @@ formatly@0.7.1 | development | MIT Package: https://www.npmjs.com/package/formatly/v/0.7.1 Archive: https://registry.npmjs.org/formatly/-/formatly-0.7.1.tgz Integrity: sha512-ESuCEJE0SGgabl9q+zABI8LhJDmF+8nhpuqDzuM48HfJ9QTD5o6PqFJDFZY7w6f8xsh5lixuj5nJsQNvYOWvKQ== +frida@17.23.2 | runtime, optional | LGPL-2.0 WITH WxWindows-exception-3.1 + Lockfile path: node_modules/frida + Package: https://www.npmjs.com/package/frida/v/17.23.2 + Archive: https://registry.npmjs.org/frida/-/frida-17.23.2.tgz + Integrity: sha512-gRCmmTUFdEILyHRN1b66erRoXafwsfWTqXyoBBqkSCFX0Ue7Jhvs/KhA3JO0XrgITNlPd91QAGsFvWzh0mhVgg== +fs-constants@1.0.0 | runtime, optional | MIT + Lockfile path: node_modules/fs-constants + Package: https://www.npmjs.com/package/fs-constants/v/1.0.0 + Archive: https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz + Integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fsevents@2.3.3 | development, optional | MIT Lockfile path: node_modules/fsevents Package: https://www.npmjs.com/package/fsevents/v/2.3.3 @@ -1685,6 +1740,11 @@ get-tsconfig@4.14.3 | development | MIT Package: https://www.npmjs.com/package/get-tsconfig/v/4.14.3 Archive: https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz Integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA== +github-from-package@0.0.0 | runtime, optional | MIT + Lockfile path: node_modules/github-from-package + Package: https://www.npmjs.com/package/github-from-package/v/0.0.0 + Archive: https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz + Integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== glob@13.0.6 | runtime | BlueOak-1.0.0 Lockfile path: node_modules/glob Package: https://www.npmjs.com/package/glob/v/13.0.6 @@ -1775,6 +1835,11 @@ inherits@2.0.4 | runtime | ISC Package: https://www.npmjs.com/package/inherits/v/2.0.4 Archive: https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz Integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@1.3.8 | runtime, optional | ISC + Lockfile path: node_modules/ini + Package: https://www.npmjs.com/package/ini/v/1.3.8 + Archive: https://registry.npmjs.org/ini/-/ini-1.3.8.tgz + Integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== is-callable@1.2.7 | runtime | MIT Lockfile path: node_modules/is-callable Package: https://www.npmjs.com/package/is-callable/v/1.2.7 @@ -2080,11 +2145,26 @@ mitt@3.0.1 | development | MIT Package: https://www.npmjs.com/package/mitt/v/3.0.1 Archive: https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz Integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== +mkdirp-classic@0.5.3 | runtime, optional | MIT + Lockfile path: node_modules/mkdirp-classic + Package: https://www.npmjs.com/package/mkdirp-classic/v/0.5.3 + Archive: https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz + Integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== nanoid@3.3.20 | development | MIT Lockfile path: node_modules/nanoid Package: https://www.npmjs.com/package/nanoid/v/3.3.20 Archive: https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz Integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ== +napi-build-utils@2.0.0 | runtime, optional | MIT + Lockfile path: node_modules/napi-build-utils + Package: https://www.npmjs.com/package/napi-build-utils/v/2.0.0 + Archive: https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz + Integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== +node-abi@3.98.0 | runtime, optional | MIT + Lockfile path: node_modules/node-abi + Package: https://www.npmjs.com/package/node-abi/v/3.98.0 + Archive: https://registry.npmjs.org/node-abi/-/node-abi-3.98.0.tgz + Integrity: sha512-Llh8noNw7s15m+rmIrZnZQbe4gLyasL9loT74rC92PkmwWKeEedKvc7o6pjp8B3MhrYT/Cl846NOYZbz1wmddw== obug@2.2.1 | development | MIT Lockfile path: node_modules/obug Package: https://www.npmjs.com/package/obug/v/2.2.1 @@ -2230,6 +2310,11 @@ preact@10.29.8 | development | MIT Package: https://www.npmjs.com/package/preact/v/10.29.8 Archive: https://registry.npmjs.org/preact/-/preact-10.29.8.tgz Integrity: sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q== +prebuild-install@7.1.3 | runtime, optional | MIT + Lockfile path: node_modules/prebuild-install + Package: https://www.npmjs.com/package/prebuild-install/v/7.1.3 + Archive: https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz + Integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== process@0.11.10 | runtime | MIT Lockfile path: node_modules/process Package: https://www.npmjs.com/package/process/v/0.11.10 @@ -2245,6 +2330,11 @@ property-information@7.2.0 | development | MIT Package: https://www.npmjs.com/package/property-information/v/7.2.0 Archive: https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz Integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg== +pump@3.0.4 | runtime, optional | MIT + Lockfile path: node_modules/pump + Package: https://www.npmjs.com/package/pump/v/3.0.4 + Archive: https://registry.npmjs.org/pump/-/pump-3.0.4.tgz + Integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== pure-rand@8.4.2 | development | MIT Lockfile path: node_modules/pure-rand Package: https://www.npmjs.com/package/pure-rand/v/8.4.2 @@ -2255,6 +2345,16 @@ quick-format-unescaped@4.0.4 | runtime | MIT Package: https://www.npmjs.com/package/quick-format-unescaped/v/4.0.4 Archive: https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz Integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== +rc@1.2.8 | runtime, optional | (BSD-2-Clause OR MIT OR Apache-2.0) + Lockfile path: node_modules/rc + Package: https://www.npmjs.com/package/rc/v/1.2.8 + Archive: https://registry.npmjs.org/rc/-/rc-1.2.8.tgz + Integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== +strip-json-comments@2.0.1 | runtime, optional | MIT + Lockfile path: node_modules/rc/node_modules/strip-json-comments + Package: https://www.npmjs.com/package/strip-json-comments/v/2.0.1 + Archive: https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz + Integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== readable-stream@4.7.0 | runtime | MIT Lockfile path: node_modules/readable-stream Package: https://www.npmjs.com/package/readable-stream/v/4.7.0 @@ -2465,6 +2565,21 @@ tabbable@6.5.0 | development | MIT Package: https://www.npmjs.com/package/tabbable/v/6.5.0 Archive: https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz Integrity: sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA== +tar-fs@2.1.5 | runtime, optional | MIT + Lockfile path: node_modules/tar-fs + Package: https://www.npmjs.com/package/tar-fs/v/2.1.5 + Archive: https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz + Integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw== +tar-stream@2.2.0 | runtime, optional | MIT + Lockfile path: node_modules/tar-stream + Package: https://www.npmjs.com/package/tar-stream/v/2.2.0 + Archive: https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz + Integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== +readable-stream@3.6.2 | runtime, optional | MIT + Lockfile path: node_modules/tar-stream/node_modules/readable-stream + Package: https://www.npmjs.com/package/readable-stream/v/3.6.2 + Archive: https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz + Integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== thread-stream@4.2.0 | runtime | MIT Lockfile path: node_modules/thread-stream Package: https://www.npmjs.com/package/thread-stream/v/4.2.0 @@ -2515,6 +2630,11 @@ tslib@2.8.1 | development, optional | 0BSD Package: https://www.npmjs.com/package/tslib/v/2.8.1 Archive: https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz Integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== +tunnel-agent@0.6.0 | runtime, optional | Apache-2.0 + Lockfile path: node_modules/tunnel-agent + Package: https://www.npmjs.com/package/tunnel-agent/v/0.6.0 + Archive: https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz + Integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== turbo@2.11.7 | development | MIT Lockfile path: node_modules/turbo Package: https://www.npmjs.com/package/turbo/v/2.11.7 @@ -2570,6 +2690,11 @@ unist-util-visit-parents@6.0.2 | development | MIT Package: https://www.npmjs.com/package/unist-util-visit-parents/v/6.0.2 Archive: https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz Integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ== +util-deprecate@1.0.2 | runtime, optional | MIT + Lockfile path: node_modules/util-deprecate + Package: https://www.npmjs.com/package/util-deprecate/v/1.0.2 + Archive: https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz + Integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== vfile@6.0.3 | development | MIT Lockfile path: node_modules/vfile Package: https://www.npmjs.com/package/vfile/v/6.0.3 diff --git a/licenses/npm-runtime-notices.txt b/licenses/npm-runtime-notices.txt index f34cd8ee4..d981aa68a 100644 --- a/licenses/npm-runtime-notices.txt +++ b/licenses/npm-runtime-notices.txt @@ -1,7 +1,7 @@ REA third-party npm runtime copyright, license and NOTICE texts Collected from integrity-verified locked npm archives. Release-specific supplements and upstream notice gaps are identified in their entries. External engines are separately obtained; see THIRD_PARTY_NOTICES.md. -Dependency fingerprint: 0b00d9530d00182e3f2b163bf27feea056c24bb6600806cab74061756ffdc36a +Runtime dependency fingerprint (SHA-256): 5de9cf97e7c327da1892efeff30b40507e4c7f8e496b5d305b8016c162bc15e3 ===== @babel/helper-string-parser@8.0.0 ===== Declared license: MIT @@ -6630,3 +6630,1590 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +===== bindings@1.5.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz +Integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE.md --- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +===== bl@4.1.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/bl/-/bl-4.1.0.tgz +Integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE.md --- + +The MIT License (MIT) +===================== + +Copyright (c) 2013-2019 bl contributors +---------------------------------- + +*bl contributors listed at * + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +===== buffer@5.7.1 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz +Integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh, and other contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + +===== chownr@1.1.4 ===== +Declared license: ISC +Archive: https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz +Integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + + +===== deep-extend@0.6.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz +Integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2013-2018, Viacheslav Lotsmanov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +===== detect-libc@2.1.2 ===== +Declared license: Apache-2.0 +Archive: https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz +Integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +===== end-of-stream@1.4.5 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz +Integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +===== expand-template@2.0.3 ===== +Declared license: (MIT OR WTFPL) +Archive: https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz +Integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2018 Lars-Magnus Skog + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +===== file-uri-to-path@1.0.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz +Integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +===== frida@17.23.2 ===== +Declared license: LGPL-2.0 WITH WxWindows-exception-3.1 +Archive: https://registry.npmjs.org/frida/-/frida-17.23.2.tgz +Integrity: sha512-gRCmmTUFdEILyHRN1b66erRoXafwsfWTqXyoBBqkSCFX0Ue7Jhvs/KhA3JO0XrgITNlPd91QAGsFvWzh0mhVgg== +Scope: npm runtime dependency, including optional platform packages. + +--- Declared metadata and supplemental licensing texts --- + +The integrity-verified npm archive and tagged frida-node source omit a standalone license/copyright document. The package declares LGPL-2.0 WITH WxWindows-exception-3.1. No Frida copyright holder or year is inferred. +The following unchanged Frida 17.23.2 COPYING and GNU Library GPL v2 texts are licensing supplements. The copyright in COPYING belongs to that license document; it is not recovered attribution for the Node binding or every component in its downloaded prebuild. + +Authors as declared by upstream package metadata: ["Frida Developers"] +Frida Node source: https://github.com/frida/frida-node/tree/11d56293686c5494f538247ccf89f08ab57912ef +License text provenance and SHA-256: licenses/upstream-sources.json + +--- licenses/frida-17.23.2-COPYING.txt --- + + wxWindows Library Licence, Version 3.1 + ====================================== + +Copyright (c) 1998-2005 Julian Smart, Robert Roebling et al + +Everyone is permitted to copy and distribute verbatim copies +of this licence document, but changing it is not allowed. + + WXWINDOWS LIBRARY LICENCE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Library General Public Licence as published by +the Free Software Foundation; either version 2 of the Licence, or (at your +option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +Licence for more details. + +You should have received a copy of the GNU Library General Public Licence +along with this software, usually in a file named COPYING.LIB. If not, +write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth +Floor, Boston, MA 02110-1301 USA. + +EXCEPTION NOTICE + +1. As a special exception, the copyright holders of this library give +permission for additional uses of the text contained in this release of the +library as licenced under the wxWindows Library Licence, applying either +version 3.1 of the Licence, or (at your option) any later version of the +Licence as published by the copyright holders of version 3.1 of the Licence +document. + +2. The exception is that you may use, copy, link, modify and distribute +under your own terms, binary object code versions of works based on the +Library. + +3. If you copy code from files distributed under the terms of the GNU +General Public Licence or the GNU Library General Public Licence into a +copy of this library, as this licence permits, the exception does not apply +to the code that you add in this way. To avoid misleading anyone as to the +status of such modified files, you must delete this exception notice from +such code and/or adjust the licensing conditions notice accordingly. + +4. If you write modifications of your own for this library, it is your +choice whether to permit this exception to apply to your modifications. If +you do not wish that, you must delete the exception notice from such code +and/or adjust the licensing conditions notice accordingly. + + +--- licenses/LGPL-2.0.txt --- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see . + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Moe Ghoul, President of Vice + +That's all there is to it! + + + +===== fs-constants@1.0.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz +Integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2018 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + +===== github-from-package@0.0.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz +Integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +===== ini@1.3.8 ===== +Declared license: ISC +Archive: https://registry.npmjs.org/ini/-/ini-1.3.8.tgz +Integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + + +===== mkdirp-classic@0.5.3 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz +Integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2020 James Halliday (mail@substack.net) and Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + +===== napi-build-utils@2.0.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz +Integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +MIT License + +Copyright (c) 2018 inspiredware + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +===== node-abi@3.98.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/node-abi/-/node-abi-3.98.0.tgz +Integrity: sha512-Llh8noNw7s15m+rmIrZnZQbe4gLyasL9loT74rC92PkmwWKeEedKvc7o6pjp8B3MhrYT/Cl846NOYZbz1wmddw== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +MIT License + +Copyright (c) 2016 Lukas Geiger + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +===== prebuild-install@7.1.3 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz +Integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2015 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + +===== pump@3.0.4 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/pump/-/pump-3.0.4.tgz +Integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +===== rc@1.2.8 ===== +Declared license: (BSD-2-Clause OR MIT OR Apache-2.0) +Archive: https://registry.npmjs.org/rc/-/rc-1.2.8.tgz +Integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE.APACHE2 --- + +Apache License, Version 2.0 + +Copyright (c) 2011 Dominic Tarr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +--- package/LICENSE.BSD --- + +Copyright (c) 2013, Dominic Tarr +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. + + +--- package/LICENSE.MIT --- + +The MIT License + +Copyright (c) 2011 Dominic Tarr + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +===== readable-stream@3.6.2 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz +Integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + + + +===== strip-json-comments@2.0.1 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz +Integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +Scope: npm runtime dependency, including optional platform packages. + +--- package/license --- + +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + +===== tar-fs@2.1.5 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz +Integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +===== tar-stream@2.2.0 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz +Integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +===== tunnel-agent@0.6.0 ===== +Declared license: Apache-2.0 +Archive: https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz +Integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + + +===== util-deprecate@1.0.2 ===== +Declared license: MIT +Archive: https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz +Integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +Scope: npm runtime dependency, including optional platform packages. + +--- package/LICENSE --- + +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + diff --git a/licenses/upstream-sources.json b/licenses/upstream-sources.json index 5853460b2..fb1dad975 100644 --- a/licenses/upstream-sources.json +++ b/licenses/upstream-sources.json @@ -58,5 +58,15 @@ "file": "licenses/Node-22.19.0-LICENSE.txt", "source": "https://raw.githubusercontent.com/nodejs/node/v22.19.0/LICENSE", "sha256": "e991d81497a85bb24fc6bffae0a3637a6accd6c6bc5ce1f2c5698bd555cf9d49" + }, + { + "file": "licenses/frida-17.23.2-COPYING.txt", + "source": "https://raw.githubusercontent.com/frida/frida/9adf8ed33ab6f1122b17399ee96dcbe101b941c9/COPYING", + "sha256": "5ea1544b51a28bc823b03159190d4108f9fb4f4ef912389f5137c6d295e175b2" + }, + { + "file": "licenses/LGPL-2.0.txt", + "source": "https://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt", + "sha256": "cc535c21133c895b56b374c8a1dc1eb948d99003ed2b47372069456b62f42b24" } ] diff --git a/native/windows/README.md b/native/windows/README.md index 82dd5526b..e2543260f 100644 --- a/native/windows/README.md +++ b/native/windows/README.md @@ -69,10 +69,22 @@ without this lane reports Windows native controls as unavailable. limits only for its JavaScript helpers when running on Bun, which ignores their V8 heap flags; Node.js launches are unchanged. - Only the suspended child's default file owner is normalized. Caller token - privileges and ownership remain unchanged. Caller CPU affinity and process - priority are preserved in the child. Environment names are sorted and - deduplicated using Windows ordinal comparison, preserving their native Unicode - semantics and caller-selected values. + privileges and ownership remain unchanged. Caller process priority is + preserved in the child, and caller CPU affinity whenever both occupy the same + processor group. Windows chooses a new process's group itself and rejects a + mask belonging to another group, so a child placed elsewhere keeps that + group's default when the caller asked for no bound of its own. A caller + deliberately pinned to fewer processors than its group holds is a constraint + such a child cannot express, and is refused rather than widened to that + group's default. A mask covering its group's whole active set does not + distinguish a caller Windows placed in that group from one that selected the + group deliberately, so such a child can still be placed elsewhere: its + processor count stays bounded, its group placement is not preserved, and + neither that case nor the refusal above has a verification lane, because both + need a host whose processors span more than one group. + Environment names are sorted and deduplicated using Windows + ordinal comparison, preserving their native Unicode semantics and + caller-selected values. - Cleanup walks locked directory objects, removes files by handle, and unlinks reparse entries without traversing their targets. Failed removal retains the root and ancestor leases for retry; a partially removed runtime accepts only @@ -85,6 +97,17 @@ Windows failures retain their constraint, requested coordinate, Win32 code, and system message. Unsupported filesystems and reparse paths are distinct from OS access denial and missing packaged controls. +A failed runtime-parent admission additionally reports +`runtimeAllocation: "not-started"`: no runtime directory was created. The +Windows adapter uses that fact with numeric sharing/lock codes 32/33 to retain +a retryable private-runtime failure, including after successful native +authority caching. Missing allocation evidence, other codes, and opaque error +text do not establish a safe retry. Analysis errors propagate the producer's +retry disposition through JavaScript, source-map and WABT workflows; transient +failures report `category: unavailable` and retain the original reason. +Incomplete cleanup blocks an operation retry until its owned resources settle. +REA adds no automatic retry loop or new analysis cache for this behavior. + Ordinary drive-absolute paths accept backslashes, forward slashes, or mixed separators. File identity retains the original requested spelling. Separator translation does not resolve dot components, repeated separators, or extend diff --git a/native/windows/src/addon.cc b/native/windows/src/addon.cc index 0e39b84c0..bffd4cbd4 100644 --- a/native/windows/src/addon.cc +++ b/native/windows/src/addon.cc @@ -87,6 +87,8 @@ napi_value failureValue(napi_env env, const Failure& failure) { set(env, error, "requestedPath", string(env, failure.path)); set(env, error, "win32Code", number(env, failure.win32)); set(env, error, "win32Message", string(env, detail)); + if (failure.runtimeDirectoryUnallocated) + set(env, error, "runtimeAllocation", string(env, std::string("not-started"))); return error; } diff --git a/native/windows/src/authority.hpp b/native/windows/src/authority.hpp index cc713ce0b..13d7e4d60 100644 --- a/native/windows/src/authority.hpp +++ b/native/windows/src/authority.hpp @@ -33,6 +33,8 @@ struct Failure : std::runtime_error { DWORD win32; std::wstring path; std::string constraint; + // Affirmative proof for a failed runtime-parent admission; omission is unknown. + bool runtimeDirectoryUnallocated = false; Failure(std::string constraint, std::wstring path = L"", DWORD code = GetLastError()) : std::runtime_error(constraint), win32(code), path(std::move(path)), constraint(std::move(constraint)) {} diff --git a/native/windows/src/filesystem.cc b/native/windows/src/filesystem.cc index 6cfbc8e97..c8f66e5c1 100644 --- a/native/windows/src/filesystem.cc +++ b/native/windows/src/filesystem.cc @@ -212,7 +212,12 @@ static void verifyPrivate(HANDLE handle, const std::wstring& path, bool root) { } std::unique_ptr createRuntime(const std::wstring& parentPath, const std::wstring& prefix) { - auto parent = openFile(parentPath, 0, true); + std::unique_ptr parent; + try { parent = openFile(parentPath, 0, true); } + catch (Failure& failure) { + failure.runtimeDirectoryUnallocated = true; + throw; + } require(!prefix.empty() && prefix.find_first_of(L"\\/:\"<>|?*") == std::wstring::npos, "Runtime prefix must be one filename component", parentPath, ERROR_INVALID_PARAMETER); std::array random; diff --git a/native/windows/src/process.cc b/native/windows/src/process.cc index ede2b5622..80a4d0ac5 100644 --- a/native/windows/src/process.cc +++ b/native/windows/src/process.cc @@ -68,6 +68,18 @@ static ULONGLONG jobMemoryLimit(napi_env env, napi_value value) { return limit; } +// An affinity mask is meaningful only inside one processor group, so only a +// process occupying exactly one group has a group a child can inherit. A +// process whose threads span groups, or whose membership cannot be read, has no +// single group. +static bool singleProcessorGroup(HANDLE process, USHORT& group) { + USHORT count = 1; + std::array groups{}; + if (!GetProcessGroupAffinity(process, &count, groups.data()) || count != 1) return false; + group = groups[0]; + return true; +} + static void pipe(Handle& read, Handle& write, bool parentReads = true) { SECURITY_ATTRIBUTES attributes{sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; HANDLE rawRead, rawWrite; @@ -168,11 +180,27 @@ std::unique_ptr spawnProcess(const std::wstring& command, const std::ws TOKEN_OWNER owner{reinterpret_cast(tokenUser.data())->User.Sid}; require(SetTokenInformation(token.get(), TokenOwner, &owner, sizeof(owner)), "Set suspended process file owner failed", command); + // A mask names processors inside one processor group, and Windows assigns a + // new process to a group of its own choosing, so a mask belonging to another + // group is rejected (ERROR_INVALID_PARAMETER). An unconstrained caller, whose + // mask is its group's whole active set, asks for no bound the child's own + // group cannot give, so such a child keeps that group's default and the spawn + // proceeds. A narrower mask is a deliberate CPU constraint that a child in + // another group cannot express, and silently widening it would hand the + // provider tree the whole group, so that spawn fails naming the constraint. DWORD_PTR affinity = 0, systemAffinity = 0; require(GetProcessAffinityMask(GetCurrentProcess(), &affinity, &systemAffinity), "Read caller process affinity failed", command); - if (affinity != 0) + USHORT callerGroup = 0, childGroup = 0; + const bool sharedGroup = singleProcessorGroup(GetCurrentProcess(), callerGroup) && + singleProcessorGroup(result->process.get(), childGroup) && + callerGroup == childGroup; + if (affinity != 0 && sharedGroup) require(SetProcessAffinityMask(result->process.get(), affinity), "Preserve caller process affinity failed", command); + else + require(affinity == 0 || affinity == systemAffinity, + "Caller CPU affinity cannot bound an owned process in another processor group", command, + ERROR_INVALID_PARAMETER); const DWORD priority = GetPriorityClass(GetCurrentProcess()); require(priority != 0 && SetPriorityClass(result->process.get(), priority), "Preserve caller process priority failed", command); diff --git a/package.json b/package.json index b26714542..fb783aa64 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "test": "npm run test:with-build", "test:with-build": "npm run test:prepare && vitest run", "test:run": "vitest run", - "test:python": "python3 -m unittest bridge/native/test_rea_lldb_tracer.py -v", + "test:python": "python3 -m unittest bridge/native/test_rea_lldb_tracer.py -v && python3 -m unittest discover -s experiments/analysis-efficiency -p 'test_*.py' -v", "test:local": "node scripts/run-development-tests.mjs local", "test:fast": "vitest run --project domain --project services --project adapters --project composition --project conformance --project evaluation", "pretest:boundary": "npm run test:prepare", @@ -167,6 +167,7 @@ "verify:legacy-simulator": "npm run build:cached && node scripts/verify/apple/legacy-simulator.mjs", "verify:architecture-guards": "node scripts/verify/architecture-guards.mjs", "verify:apktool": "npm run build:cached && node scripts/verify-apktool.mjs", + "verify:pcap": "npm run build:cached && node scripts/verify-pcap.mjs", "verify:flutter": "npm run build:cached && node scripts/verify-flutter.mjs", "verify:adb": "npm run build:cached && node scripts/verify-adb.mjs", "verify:ghidra": "npm run build:cached && node scripts/verify-real-ghidra.mjs", @@ -181,6 +182,7 @@ "verify:ghidra:dos": "npm run build:cached && node scripts/verify-real-ghidra-dos.mjs", "verify:ghidra:com": "npm run build:cached && node scripts/verify-real-ghidra-com.mjs", "verify:ghidra:raw": "npm run build:cached && node scripts/verify-real-ghidra-raw.mjs", + "verify:ghidra:address-context": "npm run build:cached && node scripts/verify-real-ghidra-address-context.mjs", "verify:ghidra:aarch64-jump-table": "npm run build:cached && node scripts/verify-real-ghidra.mjs --aarch64-jump-table", "verify:interface-builder": "npm run build:cached && node scripts/verify/apple/interface-builder.mjs", "verify:ghidra:cross-format": "npm run build:cached && node scripts/verify-real-ghidra.mjs --cross-format", @@ -206,7 +208,7 @@ "fixtures:harmony": "node scripts/fixtures/harmony/fetch.mjs", "verify:agent": "npm run build:cached && node scripts/verify-agent-experience.mjs", "verify:hopper:linux": "npm run verify:fixtures && npm run build:cached && node scripts/verify-real-hopper-linux.mjs", - "verify:setup:linux": "npm run build:cached && node scripts/verify-linux-setup-e2e.mjs", + "verify:setup:linux": "npm run verify:fixtures && npm run build:cached && node scripts/verify-linux-setup-e2e.mjs", "build:fixtures": "node scripts/build-conformance-fixtures.mjs", "build:ghidra-windows-fixture": "node scripts/create-ghidra-windows-fixture.mjs", "verify:fixtures": "npm run build:fixtures && node scripts/verify-conformance-fixtures.mjs", @@ -237,7 +239,7 @@ "docs:preview": "vitepress preview docs", "docs:generate": "node scripts/check-dependency-install.mjs && node scripts/run-exclusive.mjs artifacts npm run docs:prepare", "docs:check": "node scripts/check-dependency-install.mjs && node scripts/run-exclusive.mjs artifacts turbo run docs:check:built && npm run test:local -- tests/conformance/readmeConsistency.test.ts", - "docs:check:built": "node scripts/generate-package-metadata.mjs --check && node scripts/generate-skill-metadata.mjs --check && node scripts/generate-product-catalog.mjs --check && node scripts/generate-completion-ledger.mjs --check && node scripts/check-doc-facts.mjs && node scripts/generate-error-schema.mjs --check", + "docs:check:built": "node scripts/generate-package-metadata.mjs --check && node scripts/generate-skill-metadata.mjs --check && node scripts/generate-product-catalog.mjs --check && node scripts/generate-completion-ledger.mjs --check && node scripts/check-doc-facts.mjs && node scripts/generate-error-schema.mjs --check && npm run licenses:check", "docs:error-schema": "node scripts/check-dependency-install.mjs && node scripts/run-exclusive.mjs artifacts turbo run artifacts:error-schema", "prepack": "node scripts/prepack.mjs", "prepare": "node scripts/prepare.mjs", @@ -279,7 +281,10 @@ "artifacts:error-schema": "node scripts/generate-error-schema.mjs", "test:prepare": "node scripts/check-dependency-install.mjs && node scripts/run-exclusive.mjs artifacts turbo run artifacts:mcp-catalog artifacts:product-catalog artifacts:managed-evidence", "evidence:check:built": "node scripts/generate-completion-ledger.mjs --check", - "docs:prepare": "node scripts/generate-package-metadata.mjs && turbo run artifacts:product-catalog artifacts:managed-evidence artifacts:error-schema" + "docs:prepare": "node scripts/generate-package-metadata.mjs && turbo run artifacts:product-catalog artifacts:managed-evidence artifacts:error-schema", + "verify:web:qlog": "npm run build:cached && node scripts/verify-qlog-captures.mjs", + "licenses:generate": "node scripts/generate-third-party-inventory.mjs", + "licenses:check": "node scripts/generate-third-party-inventory.mjs --check" }, "lint-staged": { "*.{cjs,cts,js,jsx,mjs,mts,ts,tsx}": [ diff --git a/scripts/ci/baseline.mjs b/scripts/ci/baseline.mjs new file mode 100644 index 000000000..171bd7dd3 --- /dev/null +++ b/scripts/ci/baseline.mjs @@ -0,0 +1,76 @@ +import { execFileSync } from "node:child_process"; +import { appendFileSync } from "node:fs"; + +const repository = process.env.CI_REPOSITORY; +const branch = process.env.CI_DEFAULT_BRANCH; +const head = process.env.HEAD_SHA; +const shaPattern = /^[0-9a-f]{40}$/i; + +function ancestor(base) { + try { + execFileSync("git", ["merge-base", "--is-ancestor", base, head], { + stdio: "ignore", + }); + return true; + } catch { + return false; + } +} + +function write(base, reason) { + const output = { base, reason }; + if (process.env.GITHUB_OUTPUT) { + appendFileSync( + process.env.GITHUB_OUTPUT, + `base=${base}\nreason=${reason.replace(/[\r\n]/g, " ")}\n`, + ); + } + console.log(JSON.stringify(output)); +} + +if (!repository || !branch || !head || !shaPattern.test(head)) { + write("", "Repository, default branch, or checked-out head is invalid"); +} else { + try { + const response = execFileSync( + "gh", + [ + "api", + "--method", + "GET", + `repos/${repository}/actions/workflows/ci.yml/runs`, + "-f", + `branch=${branch}`, + "-f", + "event=push", + "-f", + "status=success", + "-F", + "per_page=100", + ], + { encoding: "utf8", timeout: 15_000, maxBuffer: 4 * 1024 * 1024 }, + ); + const runs = JSON.parse(response).workflow_runs; + if (!Array.isArray(runs)) + throw new Error("GitHub returned no workflow run list"); + const base = runs.find( + (run) => + run?.event === "push" && + run?.conclusion === "success" && + run?.head_branch === branch && + run?.head_repository?.full_name === repository && + typeof run?.head_sha === "string" && + shaPattern.test(run.head_sha) && + run.head_sha.toLowerCase() !== head.toLowerCase() && + ancestor(run.head_sha), + )?.head_sha; + if (base) write(base, ""); + else + write( + "", + "No trusted successful CI push baseline is an ancestor of this head", + ); + } catch { + write("", "Could not read a successful CI push baseline from GitHub"); + } +} diff --git a/scripts/ci/job-timings-batch.mjs b/scripts/ci/job-timings-batch.mjs new file mode 100644 index 000000000..842e884f0 --- /dev/null +++ b/scripts/ci/job-timings-batch.mjs @@ -0,0 +1,268 @@ +import { execFile } from "node:child_process"; +import { appendFile, mkdir, writeFile } from "node:fs/promises"; +import { join, resolve } from "node:path"; +import { promisify } from "node:util"; +import { fileURLToPath } from "node:url"; + +import { collectJobTimings } from "./job-timings.mjs"; + +const execFileAsync = promisify(execFile); +const OUTPUT_DIRECTORY = join(".cache", "ci-job-timings"); +const MAX_BUFFER = 16 * 1024 * 1024; +const API_TIMEOUT_MS = 30_000; +const WORKFLOWS = [ + { id: "ci.yml", name: "CI" }, + { id: "release.yml", name: "Release" }, +]; +const LOOKBACK_MS = 24 * 60 * 60 * 1_000; +const MAX_RUNS_PER_WORKFLOW = 100; +const TIME_BUDGET_MS = 240_000; + +/** Collect a bounded recent sample of completed CI and Release attempts. */ +export async function collectJobTimingsBatch({ + repository, + outputDirectory = OUTPUT_DIRECTORY, + observedAt = new Date().toISOString(), + env = process.env, + now = Date.now, + collect = collectJobTimings, +} = {}) { + const identity = validateRepository(repository); + const started = now(); + const cutoff = new Date(started - LOOKBACK_MS).toISOString(); + const manifest = { + schemaVersion: 1, + observedAt, + repository: identity, + selection: { + workflows: WORKFLOWS, + status: "completed", + createdAfter: cutoff, + lookbackHours: 24, + overlap: "Each hourly run re-reads the preceding 24 hours.", + pagination: + "Run listings use the first 100; jobs are paginated within the remaining time and 16 MiB response limits.", + maxRunsPerWorkflow: MAX_RUNS_PER_WORKFLOW, + timeBudgetMs: TIME_BUDGET_MS, + exhaustive: false, + }, + coverage: { + workflowsQueried: [], + runsListed: 0, + selectedRuns: 0, + collectedRuns: 0, + }, + truncation: [], + errors: [], + runs: [], + elapsedMs: 0, + }; + const budgetExpired = () => now() - started >= TIME_BUDGET_MS; + + const selected = []; + for (const workflow of WORKFLOWS) { + if (budgetExpired()) { + manifest.truncation.push("Time budget reached while listing workflows."); + break; + } + try { + const response = await apiJson( + `repos/${identity}/actions/workflows/${workflow.id}/runs?status=completed&created=%3E%3D${encodeURIComponent(cutoff)}&per_page=${String(MAX_RUNS_PER_WORKFLOW)}&page=1`, + env, + started, + now, + ); + if (!Array.isArray(response.workflow_runs)) + throw new Error("run listing must contain a workflow_runs array"); + manifest.coverage.workflowsQueried.push(workflow.name); + manifest.coverage.runsListed += response.workflow_runs.length; + if (response.workflow_runs.length >= MAX_RUNS_PER_WORKFLOW) + manifest.truncation.push( + `${workflow.name} run listing reached the 100-run first-page limit.`, + ); + for (const run of response.workflow_runs.slice( + 0, + MAX_RUNS_PER_WORKFLOW, + )) { + if ( + run.status !== "completed" || + !Number.isSafeInteger(run.id) || + !Number.isSafeInteger(run.run_attempt) + ) { + manifest.errors.push({ + scope: `workflow:${workflow.name}`, + runId: run.id ?? null, + message: + "Run record missing completed status, numeric id, or numeric latest attempt.", + }); + continue; + } + if (run.created_at && Date.parse(run.created_at) < Date.parse(cutoff)) + continue; + selected.push({ + id: run.id, + runAttempt: run.run_attempt, + workflow: workflow.name, + conclusion: run.conclusion ?? null, + createdAt: run.created_at ?? null, + }); + } + } catch (cause) { + manifest.errors.push({ + scope: `workflow:${workflow.name}`, + message: errorMessage(cause), + }); + } + } + + selected.sort( + (left, right) => + (Date.parse(right.createdAt ?? "") || 0) - + (Date.parse(left.createdAt ?? "") || 0), + ); + manifest.coverage.selectedRuns = selected.length; + for (const run of selected) { + if (budgetExpired()) { + manifest.truncation.push( + "Time budget reached before all selected runs were collected.", + ); + break; + } + const runRecord = { + ...run, + status: "pending", + rawPath: null, + reportPath: null, + error: null, + }; + manifest.runs.push(runRecord); + const runDirectory = join( + outputDirectory, + "runs", + `${String(run.id)}-${String(run.runAttempt)}`, + ); + try { + const result = await collect({ + repository: identity, + runId: String(run.id), + runAttempt: String(run.runAttempt), + outputDirectory: runDirectory, + env, + timeoutMs: Math.max( + 1, + Math.min(API_TIMEOUT_MS, TIME_BUDGET_MS - (now() - started)), + ), + }); + runRecord.status = "collected"; + runRecord.rawPath = result.rawPath; + runRecord.reportPath = result.reportPath; + manifest.coverage.collectedRuns += 1; + } catch (cause) { + runRecord.status = "error"; + runRecord.error = errorMessage(cause); + manifest.errors.push({ + scope: "run", + runId: run.id, + runAttempt: run.runAttempt, + message: runRecord.error, + }); + } + } + if (budgetExpired() && manifest.runs.length < manifest.coverage.selectedRuns) + manifest.truncation.push( + "Time budget reached; selected runs remain unattempted.", + ); + return await writeManifest(outputDirectory, manifest, started, now, env); +} + +function validateRepository(repository) { + if ( + typeof repository !== "string" || + !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/u.test(repository) + ) + throw new Error( + "CI_REPOSITORY must be an owner/name repository identifier", + ); + return repository; +} + +async function apiJson(endpoint, env, started, now) { + const timeout = Math.max( + 1, + Math.min(API_TIMEOUT_MS, TIME_BUDGET_MS - (now() - started)), + ); + const { stdout } = await execFileAsync("gh", ["api", endpoint], { + env, + encoding: "utf8", + maxBuffer: MAX_BUFFER, + timeout, + }); + try { + return JSON.parse(stdout); + } catch (cause) { + throw new Error("GitHub Actions API returned malformed JSON", { cause }); + } +} + +async function writeManifest(outputDirectory, manifest, started, now, env) { + manifest.elapsedMs = Math.max(0, now() - started); + if ( + manifest.elapsedMs >= TIME_BUDGET_MS && + !manifest.truncation.some((item) => item.includes("Time budget")) + ) + manifest.truncation.push("Time budget reached."); + await mkdir(outputDirectory, { recursive: true }); + const manifestPath = join(outputDirectory, "batch-manifest.json"); + await writeFile( + manifestPath, + `${JSON.stringify(manifest, null, 2)}\n`, + "utf8", + ); + if (env.GITHUB_STEP_SUMMARY) + await appendBatchSummary(env.GITHUB_STEP_SUMMARY, manifest, manifestPath); + return { manifestPath, manifest }; +} + +async function appendBatchSummary(summaryPath, manifest, manifestPath) { + const collected = manifest.runs.filter( + ({ status }) => status === "collected", + ).length; + const failed = manifest.runs.filter( + ({ status }) => status === "error", + ).length; + const lines = [ + "### Batched CI timing snapshot", + "", + `Observed ${manifest.observedAt}; collected ${String(collected)} of ${String(manifest.coverage.selectedRuns)} selected recent completed runs (${String(failed)} run errors).`, + `Coverage uses the first ${String(MAX_RUNS_PER_WORKFLOW)} runs per workflow created in the preceding 24 hours and a ${String(TIME_BUDGET_MS / 1_000)} second total budget. This sample is bounded and is not exhaustive.`, + `Manifest: \`${manifestPath}\`.`, + ...manifest.truncation.map((message) => `- Truncated: ${message}`), + ...manifest.errors.map( + ({ scope, message }) => `- Error (${scope}): ${message}`, + ), + "", + ]; + await appendFile(summaryPath, lines.join("\n"), "utf8"); +} + +function errorMessage(cause) { + return cause instanceof Error ? cause.message : String(cause); +} + +if ( + process.argv[1] !== undefined && + resolve(process.argv[1]) === fileURLToPath(import.meta.url) +) { + try { + const result = await collectJobTimingsBatch({ + repository: process.env.CI_REPOSITORY, + outputDirectory: process.env.CI_JOB_TIMINGS_DIRECTORY ?? OUTPUT_DIRECTORY, + }); + process.stdout.write( + `Wrote batch manifest for ${String(result.manifest.coverage.collectedRuns)} collected runs to ${result.manifestPath}\n`, + ); + } catch (cause) { + process.stderr.write(`CI timing batch failed: ${errorMessage(cause)}\n`); + process.exitCode = 1; + } +} diff --git a/scripts/ci/job-timings.mjs b/scripts/ci/job-timings.mjs new file mode 100644 index 000000000..4d96f91b0 --- /dev/null +++ b/scripts/ci/job-timings.mjs @@ -0,0 +1,354 @@ +import { execFile } from "node:child_process"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { dirname, join, resolve } from "node:path"; +import { promisify } from "node:util"; +import { fileURLToPath } from "node:url"; + +const execFileAsync = promisify(execFile); +const MAX_BUFFER = 16 * 1024 * 1024; +const TIMEOUT_MS = 30_000; +const OUTPUT_DIRECTORY = join(".cache", "ci-job-timings"); +const STEP_COSTS = [ + { key: "npmCi", pattern: /\bnpm ci\b/iu }, + { key: "artifactUpload", pattern: /upload.*artifact/iu }, + { key: "artifactDownload", pattern: /download.*artifact/iu }, +]; + +/** Fetch and summarize one workflow attempt without turning telemetry into a gate. */ +export async function collectJobTimings({ + repository, + runId, + runAttempt, + outputDirectory = OUTPUT_DIRECTORY, + summaryPath, + observedAt = new Date().toISOString(), + env = process.env, + timeoutMs = TIMEOUT_MS, +}) { + const identity = validateIdentity({ repository, runId, runAttempt }); + const endpoint = `repos/${identity.repository}/actions/runs/${identity.runId}/attempts/${identity.runAttempt}/jobs?per_page=100`; + const { stdout } = await execFileAsync( + "gh", + ["api", "--paginate", "--slurp", endpoint], + { env, encoding: "utf8", maxBuffer: MAX_BUFFER, timeout: timeoutMs }, + ); + const rawPath = join(outputDirectory, "jobs.json"); + const reportPath = join(outputDirectory, "report.json"); + await mkdir(outputDirectory, { recursive: true }); + await writeFile(rawPath, stdout, "utf8"); + const pages = parsePages(stdout); + const jobs = pages.flatMap(({ jobs: pageJobs }, index) => + validateJobs(pageJobs, index), + ); + const report = normalizeReport({ identity, jobs, observedAt }); + + await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8"); + if (summaryPath !== undefined) + await appendSummary(summaryPath, report, rawPath, reportPath); + return { rawPath, reportPath, report }; +} + +function validateIdentity({ repository, runId, runAttempt }) { + if ( + typeof repository !== "string" || + !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/u.test(repository) + ) + throw new Error( + "CI_REPOSITORY must be an owner/name repository identifier", + ); + return { + repository, + runId: parsePositiveInteger(runId, "CI_TIMING_RUN_ID"), + runAttempt: parsePositiveInteger(runAttempt, "CI_TIMING_RUN_ATTEMPT"), + }; +} + +function parsePositiveInteger(value, name) { + if (typeof value === "string" && /^[1-9]\d*$/u.test(value)) { + const parsed = Number(value); + if (Number.isSafeInteger(parsed)) return parsed; + } + throw new Error(`${name} must be a positive safe integer`); +} + +function parsePages(stdout) { + let pages; + try { + pages = JSON.parse(stdout); + } catch (cause) { + throw new Error("GitHub jobs API returned malformed JSON", { cause }); + } + if (!Array.isArray(pages) || pages.length === 0) + throw new Error("GitHub jobs API slurp must contain a nonempty page array"); + for (const page of pages) + if ( + typeof page !== "object" || + page === null || + Array.isArray(page) || + !Array.isArray(page.jobs) + ) + throw new Error("GitHub jobs API page must contain a jobs array"); + return pages; +} + +function validateJobs(jobs, pageIndex) { + return jobs.map((job, jobIndex) => { + if ( + typeof job !== "object" || + job === null || + Array.isArray(job) || + typeof job.name !== "string" || + job.name.length === 0 || + typeof job.status !== "string" + ) + throw new Error( + `GitHub jobs API page ${String(pageIndex + 1)} job ${String(jobIndex + 1)} is malformed`, + ); + return job; + }); +} + +function normalizeReport({ identity, jobs, observedAt }) { + const normalizedJobs = jobs.map(normalizeJob); + const queues = normalizedJobs + .map(({ queue }) => queue.seconds) + .filter((value) => value !== null); + const completedExecutions = normalizedJobs + .filter( + ({ status, conclusion }) => + status === "completed" && conclusion !== "skipped", + ) + .map(({ execution }) => execution.seconds) + .filter((value) => value !== null); + const completedDurationSumSeconds = completedExecutions.reduce( + (sum, seconds) => sum + seconds, + 0, + ); + const completedExecutionUnknown = normalizedJobs.filter( + ({ status, conclusion, execution }) => + status === "completed" && + conclusion !== "skipped" && + execution.seconds === null, + ).length; + const skipped = normalizedJobs.filter( + ({ conclusion }) => conclusion === "skipped", + ).length; + const costs = Object.fromEntries(STEP_COSTS.map(({ key }) => [key, []])); + for (const job of normalizedJobs) + for (const step of job.steps) + if (step.costKey !== null) + costs[step.costKey].push({ job: job.name, ...step }); + + return { + schemaVersion: 1, + run: { + ...identity, + observedAt, + snapshot: + normalizedJobs.length > 0 && + normalizedJobs.every(({ status }) => status === "completed") + ? "completed job status snapshot; unknown timestamps remain unmeasured" + : "partial; job statuses may still be queued or in progress", + }, + counts: { + jobs: normalizedJobs.length, + completed: normalizedJobs.filter(({ status }) => status === "completed") + .length, + skipped, + queueUnknown: normalizedJobs.filter(({ queue }) => queue.seconds === null) + .length, + executionUnknown: normalizedJobs.filter( + ({ execution }) => execution.seconds === null, + ).length, + completedExecutionUnknown, + }, + aggregates: { + queueSeconds: percentileSummary(queues), + completedExecutionSeconds: percentileSummary(completedExecutions), + summedCompletedJobElapsedSeconds: { + value: + completedExecutions.length === 0 + ? null + : round(completedDurationSumSeconds), + knownCount: completedExecutions.length, + unknownCount: completedExecutionUnknown, + label: + "sum of known completed job elapsed durations; incomplete when timestamps are unknown; not CPU time, billing, or workflow wall time", + }, + }, + jobs: normalizedJobs, + stepCostInterpretation: + "Matched install/artifact steps by step name; these are not total artifact transfer costs.", + stepCosts: costs, + }; +} + +function normalizeJob(job) { + const skipped = job.conclusion === "skipped"; + const hasStarted = ["in_progress", "completed"].includes(job.status); + const queue = skipped + ? unknownDuration("job was skipped") + : !hasStarted + ? unknownDuration("job start is not established by its status") + : duration(job.created_at, job.started_at); + const execution = skipped + ? unknownDuration("job was skipped") + : job.status === "completed" + ? duration(job.started_at, job.completed_at) + : unknownDuration("job is not completed"); + const steps = Array.isArray(job.steps) ? job.steps.map(normalizeStep) : []; + return { + id: Number.isSafeInteger(job.id) && job.id > 0 ? job.id : null, + url: stringOrNull(job.html_url), + name: job.name, + workflowName: stringOrNull(job.workflow_name), + status: job.status, + conclusion: stringOrNull(job.conclusion), + createdAt: stringOrNull(job.created_at), + startedAt: stringOrNull(job.started_at), + completedAt: stringOrNull(job.completed_at), + queue, + execution, + steps, + }; +} + +function normalizeStep(step) { + if ( + typeof step !== "object" || + step === null || + Array.isArray(step) || + typeof step.name !== "string" + ) + throw new Error("GitHub jobs API contains a malformed job step"); + const cost = STEP_COSTS.find(({ pattern }) => pattern.test(step.name)); + return { + name: step.name, + costKey: cost?.key ?? null, + duration: duration(step.started_at, step.completed_at), + }; +} + +function duration(startValue, endValue) { + if (typeof startValue !== "string" || typeof endValue !== "string") + return unknownDuration("timestamp unavailable"); + const start = Date.parse(startValue); + const end = Date.parse(endValue); + if (!Number.isFinite(start) || !Number.isFinite(end)) + return unknownDuration("invalid timestamp"); + const milliseconds = end - start; + if (!Number.isFinite(milliseconds) || milliseconds < 0) + return unknownDuration("timestamps out of order"); + return { seconds: round(milliseconds / 1_000), reason: null }; +} + +function unknownDuration(reason) { + return { seconds: null, reason }; +} + +function percentileSummary(values) { + return { + count: values.length, + p50: nearestRank(values, 0.5), + p95: nearestRank(values, 0.95), + unit: "seconds", + }; +} + +function nearestRank(values, percentile) { + if (values.length === 0) return null; + const sorted = [...values].sort((left, right) => left - right); + return round(sorted[Math.ceil(percentile * sorted.length) - 1]); +} + +function round(value) { + return Math.round(value * 1_000) / 1_000; +} + +function stringOrNull(value) { + return typeof value === "string" ? value : null; +} + +async function appendSummary(summaryPath, report, rawPath, reportPath) { + await mkdir(dirname(summaryPath), { recursive: true }); + const rows = [ + ["Queue", report.aggregates.queueSeconds], + ["Completed execution", report.aggregates.completedExecutionSeconds], + ] + .map( + ([label, item]) => + `| ${label} | ${display(item.p50)} | ${display(item.p95)} | ${String(item.count)} |`, + ) + .join("\n"); + const jobRows = report.jobs + .map( + (job) => + `| ${escapeCell(job.name)} | ${job.status} | ${job.conclusion ?? "unknown"} | ${display(job.queue.seconds)} | ${job.queue.seconds === null ? job.queue.reason : ""} | ${display(job.execution.seconds)} | ${job.execution.seconds === null ? job.execution.reason : ""} |`, + ) + .join("\n"); + const costRows = STEP_COSTS.map(({ key }) => { + const samples = report.stepCosts[key]; + const values = samples + .map(({ duration: item }) => item.seconds) + .filter((value) => value !== null); + return `| ${key} | ${String(samples.length)} | ${display(nearestRank(values, 0.5))} | ${samples.filter(({ duration: item }) => item.seconds === null).length} |`; + }).join("\n"); + const text = [ + "### CI job timing snapshot", + "", + `Observed at ${report.run.observedAt} for run ${String(report.run.runId)}, attempt ${String(report.run.runAttempt)}. This is a point-in-time snapshot of fetched jobs. Queue starts at job creation and excludes preceding dependency waiting. Missing, queued, in-progress, invalid, or out-of-order timestamps are reported as unknown. Elapsed durations are not CPU time or billing data.`, + "", + `Fetched ${String(report.counts.jobs)} jobs; ${String(report.counts.completed)} are completed (${String(report.counts.skipped)} skipped); ${String(report.counts.queueUnknown)} queue durations and ${String(report.counts.executionUnknown)} execution durations (${String(report.counts.completedExecutionUnknown)} for non-skipped completed jobs) are unknown.`, + "", + "| Metric | p50 (s) | p95 (s) | Samples |", + "| --- | ---: | ---: | ---: |", + rows, + "", + "| Job | Status | Conclusion | Queue (s) | Queue detail | Execution (s) | Execution detail |", + "| --- | --- | --- | ---: | --- | ---: | --- |", + jobRows, + "", + `Sum of known completed job elapsed durations: **${display(report.aggregates.summedCompletedJobElapsedSeconds.value)} s** across ${String(report.aggregates.summedCompletedJobElapsedSeconds.knownCount)} known and ${String(report.aggregates.summedCompletedJobElapsedSeconds.unknownCount)} unknown jobs; this is not CPU time, billing, or workflow wall time.`, + "", + "Matched install/artifact steps by name; these are not total artifact transfer costs.", + "", + "| Matched step group | Samples | p50 (s) | Unknown |", + "| --- | ---: | ---: | ---: |", + costRows, + "", + `Reports: \`${rawPath}\`, \`${reportPath}\`.`, + "", + ].join("\n"); + await writeFile(summaryPath, text, { encoding: "utf8", flag: "a" }); +} + +function display(value) { + return value === null ? "unknown" : String(value); +} + +function escapeCell(value) { + return value.replaceAll("|", "\\|").replaceAll("\n", " "); +} + +if ( + process.argv[1] !== undefined && + resolve(process.argv[1]) === fileURLToPath(import.meta.url) +) { + try { + const result = await collectJobTimings({ + repository: process.env.CI_REPOSITORY, + runId: process.env.CI_TIMING_RUN_ID, + runAttempt: process.env.CI_TIMING_RUN_ATTEMPT, + outputDirectory: process.env.CI_JOB_TIMINGS_DIRECTORY ?? OUTPUT_DIRECTORY, + summaryPath: process.env.GITHUB_STEP_SUMMARY, + }); + process.stdout.write( + `Wrote ${result.report.jobs.length} job timing records to ${result.reportPath}\n`, + ); + } catch (cause) { + process.stderr.write( + `CI timing telemetry failed: ${cause instanceof Error ? cause.message : String(cause)}\n`, + ); + process.exitCode = 1; + } +} diff --git a/scripts/ci/plan.mjs b/scripts/ci/plan.mjs index e71fb913c..457be57c7 100644 --- a/scripts/ci/plan.mjs +++ b/scripts/ci/plan.mjs @@ -1,30 +1,20 @@ import { execFileSync } from "node:child_process"; import { appendFileSync } from "node:fs"; import { matchesGlob } from "node:path"; -import { MANUAL_VERIFIERS, SCOPES } from "./scopes.mjs"; +import { CI_FLAGS as flags, MANUAL_VERIFIERS, SCOPES } from "./scopes.mjs"; +import { planTestSelection } from "./test-selection.mjs"; -const flags = [ - ...new Set([ - "code", - "runtime", - "package", - "apple", - "fixtures", - "readiness", - "docs", - "workflows", - ...Object.keys(SCOPES), - ]), -]; -// Test files select the native-host lanes that run them explicitly. Provider -// scopes remain implementation-owned, so test-only edits stay off those lanes. -const NATIVE_TEST_OWNERS = ["apple", "package"]; +// Test files select the host/runtime lanes that execute their focused suites. +const HOST_TEST_OWNERS = ["apple", "package", "sqlite"]; // Actionlint validates workflow syntax only. The semantic suite asserts these // workflows' release, publication and self-hosted runner safeguards. const GUARDED_WORKFLOWS = new Set([ + ".github/workflows/pr-title.yml", + ".github/workflows/ci-full-pr.yml", ".github/workflows/release.yml", ".github/workflows/real-ghidra-windows.yml", ".github/workflows/sqlite-runtime.yml", + ".github/workflows/ci-timings.yml", ]); // Sources compiled by build-conformance-fixtures.mjs. The readiness journey // analyzes the built C fixture as well as its own applications. @@ -36,6 +26,15 @@ const FIXTURE_SOURCES = [ "tests/conformance/versions/**", ]; const READINESS_SOURCES = ["tests/conformance/readiness/**"]; +// These reporters affect CI output only; they do not select a host or provider +// verification lane when changed on their own. +const PORTABLE_CI_REPORTERS = new Set([ + "scripts/ci/job-timings.mjs", + "scripts/ci/job-timings-batch.mjs", + "scripts/ci/test-report.mjs", + "scripts/ci/test-timing-reporter.mjs", + "scripts/ci/test-history.mjs", +]); const matchesAny = (file, patterns) => patterns.some((pattern) => matchesGlob(file, pattern)); const selected = Object.fromEntries(flags.map((flag) => [flag, false])); @@ -63,6 +62,10 @@ function classifyPackage(base, head) { ]), ].filter((key) => beforeScripts?.[key] !== afterScripts?.[key]); for (const script of changed) { + if (script === "test:sqlite" || script === "test:sqlite:run") { + selected.sqlite = true; + continue; + } if ( /^(test(?::|$)|check(?::|$)|lint(?::|$)|format(?::|$)|knip$|jscpd$)/.test( script, @@ -108,99 +111,135 @@ function classifyPackage(base, head) { } const event = process.env.GITHUB_EVENT_NAME; -let files = []; -if ( - event === "push" || +if (!["pull_request", "push", "schedule", "workflow_dispatch"].includes(event)) + throw new Error(`Unsupported CI event: ${event}`); +const requestedFull = event === "schedule" || event === "workflow_dispatch" || - process.env.CI_FULL === "true" -) { + process.env.CI_FULL === "true"; +const tier = + event === "schedule" && + process.env.CI_SKIP_FULL === "true" && + process.env.CI_FULL !== "true" + ? "reused" + : requestedFull + ? "full" + : "fast"; +let files = []; +if (tier === "reused") { + reasons.push( + "Recent exact-SHA full qualification reused; no fresh provider observation", + ); +} else if (tier === "full") { full("Full baseline requested by event or ci:full label"); -} else if (event === "pull_request") { - const base = git("merge-base", process.env.BASE_SHA, process.env.HEAD_SHA); +} else if (event === "pull_request" || event === "push") { const head = process.env.HEAD_SHA; - // Disable rename detection so both the removed and added paths participate. - files = git("diff", "--name-only", "--no-renames", "-z", base, head) - .split("\0") - .filter(Boolean); - for (const file of files) { - if ( - /^(README(?:_[^/]+)?\.md|AGENTS\.md|CONTRIBUTING\.md|CHANGELOG\.md|SECURITY\.md|native\/windows\/README\.md|\.github\/pull_request_template\.md)$/.test( - file, - ) || - file.startsWith("docs/") || - file === "scripts/verify-documentation-routes.mjs" || - file.startsWith(".github/ISSUE_TEMPLATE/") - ) { - selected.docs = true; - selected.website ||= matchesAny(file, SCOPES.website); - continue; - } - if (/^(src|tests)\/.*\.(?:test|spec)\.[cm]?[jt]sx?$/.test(file)) { - selected.code = true; - for (const owner of NATIVE_TEST_OWNERS) - selected[owner] ||= matchesAny(file, SCOPES[owner]); - continue; - } - if (matchesAny(file, MANUAL_VERIFIERS)) { - selected.code = true; - continue; - } - const owners = Object.entries(SCOPES) - .filter(([, patterns]) => - patterns.some((pattern) => matchesGlob(file, pattern)), - ) - .map(([owner]) => owner); - for (const owner of owners) selected[owner] = true; - if ( - file.startsWith(".github/workflows/") || - file === ".github/actionlint.yaml" - ) { - selected.workflows = true; - if (GUARDED_WORKFLOWS.has(file)) selected.code = true; - if (file !== ".github/workflows/ci.yml") continue; - } - if (owners.length === 1 && owners[0] === "website") continue; - if (/^src\/(contracts|domain)\//.test(file)) selected.docs = true; - if (file === "package.json") { - classifyPackage(base, head); - continue; - } - selected.code = true; - if (matchesAny(file, FIXTURE_SOURCES)) { - selected.fixtures = true; - selected.readiness = true; - } - if (matchesAny(file, READINESS_SOURCES)) selected.readiness = true; - if (file.startsWith("tests/")) continue; - if ( - /^(src\/process\/|src\/filesystem\/|src\/contracts\/tool|src\/server\/createServer|src\/cli\.ts|scripts\/ci\/)/.test( - file, - ) - ) { - full(`Shared boundary: ${file}`); - } else if (owners.length) { - if (file.startsWith("src/") || file.startsWith("bridge/")) - selected.runtime = true; - } else if (/^(src|bridge)\//.test(file)) { - // Unowned runtime sources keep the Linux x64 installed-package baseline; - // ci:full, main pushes and manual dispatch retain every native host. - selected.runtime = true; - reasons.push(`Unowned runtime source: ${file}`); - } else if (file.startsWith(".agents/skills/")) { - selected.runtime = true; - selected.docs = true; - } else { - full(`Unclassified input: ${file}`); + let base; + if (event === "pull_request") { + base = git("merge-base", process.env.BASE_SHA, head); + } else { + const candidate = process.env.BASE_SHA; + const baselineReason = process.env.BASELINE_REASON; + try { + if (!candidate || !/^[0-9a-f]{40}$/i.test(candidate)) + throw new Error( + baselineReason || "No valid successful push baseline was found", + ); + execFileSync("git", ["merge-base", "--is-ancestor", candidate, head], { + stdio: "ignore", + }); + base = candidate; + } catch { + full( + baselineReason || + "No valid successful push baseline ancestor; selecting all lanes", + ); } } -} else throw new Error(`Unsupported CI event: ${event}`); + if (base) { + // Disable rename detection so both the removed and added paths participate. + files = git("diff", "--name-only", "--no-renames", "-z", base, head) + .split("\0") + .filter(Boolean); + for (const file of files) { + if ( + /^(README(?:_[^/]+)?\.md|AGENTS\.md|CONTRIBUTING\.md|CHANGELOG\.md|SECURITY\.md|native\/windows\/README\.md|\.github\/pull_request_template\.md)$/.test( + file, + ) || + file.startsWith("docs/") || + file === "scripts/verify-documentation-routes.mjs" || + file.startsWith(".github/ISSUE_TEMPLATE/") + ) { + selected.docs = true; + selected.website ||= matchesAny(file, SCOPES.website); + continue; + } + if (/^(src|tests)\/.*\.(?:test|spec)\.[cm]?[jt]sx?$/.test(file)) { + selected.code = true; + for (const owner of HOST_TEST_OWNERS) + selected[owner] ||= matchesAny(file, SCOPES[owner]); + continue; + } + if (matchesAny(file, MANUAL_VERIFIERS)) { + selected.code = true; + continue; + } + const owners = Object.entries(SCOPES) + .filter(([, patterns]) => + patterns.some((pattern) => matchesGlob(file, pattern)), + ) + .map(([owner]) => owner); + for (const owner of owners) selected[owner] = true; + if ( + file.startsWith(".github/workflows/") || + file === ".github/actionlint.yaml" + ) { + selected.workflows = true; + if (GUARDED_WORKFLOWS.has(file)) selected.code = true; + if (file !== ".github/workflows/ci.yml") continue; + } + if (owners.length === 1 && owners[0] === "website") continue; + if (/^src\/(contracts|domain)\//.test(file)) selected.docs = true; + if (file === "package.json") { + classifyPackage(base, head); + continue; + } + selected.code = true; + if (matchesAny(file, FIXTURE_SOURCES)) { + selected.fixtures = true; + selected.readiness = true; + } + if (matchesAny(file, READINESS_SOURCES)) selected.readiness = true; + if (file.startsWith("tests/")) continue; + if (PORTABLE_CI_REPORTERS.has(file)) continue; + if ( + /^(src\/process\/|src\/filesystem\/|src\/contracts\/tool|src\/server\/createServer|src\/cli\.ts|scripts\/ci\/)/.test( + file, + ) + ) { + full(`Shared boundary: ${file}`); + } else if (owners.length) { + if (file.startsWith("src/") || file.startsWith("bridge/")) + selected.runtime = true; + } else if (/^(src|bridge)\//.test(file)) { + // Unowned runtime sources keep the Linux x64 installed-package baseline; + // full qualification retains every native host. + selected.runtime = true; + reasons.push(`Unowned runtime source: ${file}`); + } else if (file.startsWith(".agents/skills/")) { + selected.runtime = true; + selected.docs = true; + } else { + full(`Unclassified input: ${file}`); + } + } + } +} selected.runtime ||= selected.package; const linux = { os: "ubuntu-latest", platform: "linux", architecture: "x64" }; -// macOS x64 is the slowest package host. Pull requests run it only with ci:full; -// main pushes, schedules and manual dispatch always include it. +// macOS x64 is the slowest package host. Fast qualification omits it. const intel = - event !== "pull_request" || process.env.CI_FULL === "true" + tier === "full" ? [{ os: "macos-15-intel", platform: "darwin", architecture: "x64" }] : []; const matrix = { @@ -213,17 +252,23 @@ const matrix = { ] : [linux], }; -const plan = { ...selected, matrix, files, reasons }; +const testSelection = planTestSelection(files, event, tier); +const plan = { ...selected, tier, matrix, files, reasons, testSelection }; if (process.env.GITHUB_OUTPUT) appendFileSync( process.env.GITHUB_OUTPUT, - Object.entries({ ...selected, matrix: JSON.stringify(matrix) }) + Object.entries({ + ...selected, + tier, + matrix: JSON.stringify(matrix), + test_selection: JSON.stringify(testSelection), + }) .map(([key, value]) => `${key}=${value}\n`) .join(""), ); if (process.env.GITHUB_STEP_SUMMARY) appendFileSync( process.env.GITHUB_STEP_SUMMARY, - `### Selected CI lanes\n\n${flags.filter((flag) => selected[flag]).join(", ") || "Formatting only"}\n\n${reasons.join("\n\n")}\n`, + `### Selected CI lanes (${tier})\n\n${flags.filter((flag) => selected[flag]).join(", ") || "Formatting only"}\n\n${reasons.join("\n\n")}\n`, ); console.log(JSON.stringify(plan)); diff --git a/scripts/ci/qualification.mjs b/scripts/ci/qualification.mjs new file mode 100644 index 000000000..ab47c168f --- /dev/null +++ b/scripts/ci/qualification.mjs @@ -0,0 +1,176 @@ +import { execFileSync } from "node:child_process"; +import { appendFileSync, mkdirSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ARTIFACT_NAME = "ci-full-qualification-v1"; +const MAX_AGE_MS = 24 * 60 * 60 * 1000; +const positiveId = (value) => + (typeof value === "string" || typeof value === "number") && + /^[1-9]\d*$/.test(String(value)) && + Number.isSafeInteger(Number(value)); +const commitSha = (value) => + typeof value === "string" && /^[0-9a-f]{40}$/.test(value); + +/** Record only after the required gate has verified every full-tier obligation. */ +export function recordQualification(directory) { + const sourceSha = process.env.GITHUB_SHA; + const runId = process.env.GITHUB_RUN_ID; + const runAttempt = process.env.GITHUB_RUN_ATTEMPT; + const repository = process.env.GITHUB_REPOSITORY; + if ( + !commitSha(sourceSha) || + !positiveId(runId) || + !positiveId(runAttempt) || + !repository + ) + throw new Error( + "Full qualification receipt requires source and workflow identity", + ); + const checkoutSha = execFileSync("git", ["rev-parse", "HEAD"], { + encoding: "utf8", + }).trim(); + if (checkoutSha !== sourceSha) + throw new Error("Qualification checkout differs from workflow source"); + mkdirSync(directory, { recursive: true }); + const path = resolve(directory, "receipt.json"); + writeFileSync( + path, + `${JSON.stringify( + { + schemaVersion: 1, + tier: "full", + sourceSha, + repository, + runId: Number(runId), + runAttempt: Number(runAttempt), + qualifiedAt: new Date().toISOString(), + }, + null, + 2, + )}\n`, + ); + if (process.env.GITHUB_OUTPUT) + appendFileSync( + process.env.GITHUB_OUTPUT, + `receipt_name=${ARTIFACT_NAME}\nreceipt_path=${path}\n`, + ); +} + +function admit() { + if (process.env.CI_FORCE_FULL === "true") + return { + run_full: true, + reason: "Forced daily runner and dependency refresh", + }; + const repository = process.env.CI_REPOSITORY; + const repositoryId = Number(process.env.CI_REPOSITORY_ID); + const branch = process.env.CI_DEFAULT_BRANCH; + const head = process.env.HEAD_SHA; + if (!repository || !positiveId(repositoryId) || !branch || !commitSha(head)) + return { + run_full: true, + reason: "Qualification lookup identity is incomplete", + }; + + const now = Date.now(); + const deadline = now + 20_000; + const api = (...arguments_) => { + const remaining = deadline - Date.now(); + if (remaining <= 0) + throw new Error("Qualification lookup budget exhausted"); + return JSON.parse( + execFileSync("gh", ["api", "--method", "GET", ...arguments_], { + encoding: "utf8", + timeout: Math.min(15_000, remaining), + maxBuffer: 8 * 1024 * 1024, + stdio: ["ignore", "pipe", "pipe"], + }), + ); + }; + try { + const { artifacts } = api( + `repos/${repository}/actions/artifacts`, + "-f", + `name=${ARTIFACT_NAME}`, + "-F", + "per_page=100", + ); + if (!Array.isArray(artifacts)) + throw new Error("Missing qualification artifact inventory"); + const candidates = artifacts.filter((artifact) => { + const lineage = artifact?.workflow_run; + const age = now - Date.parse(artifact?.created_at); + return ( + artifact?.name === ARTIFACT_NAME && + artifact?.expired === false && + typeof artifact?.created_at === "string" && + Number.isFinite(age) && + age >= 0 && + age < MAX_AGE_MS && + positiveId(lineage?.id) && + String(lineage.id) !== process.env.GITHUB_RUN_ID && + lineage?.repository_id === repositoryId && + lineage?.head_repository_id === repositoryId && + lineage?.head_branch === branch && + lineage?.head_sha === head + ); + }); + // Artifact metadata narrows the search before run lookups. Never scan an + // unbounded history or treat a missing receipt as a successful qualification. + for (const artifact of candidates.slice(0, 3)) { + const run = api( + `repos/${repository}/actions/runs/${artifact.workflow_run.id}`, + ); + // An old run can upload a new artifact when only its gate is rerun. + // Bound the original run age as well so retries cannot renew stale proof. + const runAge = Date.now() - Date.parse(run.created_at); + if ( + typeof run.created_at === "string" && + Number.isFinite(runAge) && + runAge >= 0 && + runAge < MAX_AGE_MS && + run.id === artifact.workflow_run.id && + run.status === "completed" && + run.conclusion === "success" && + run.path === ".github/workflows/ci.yml" && + ["schedule", "workflow_dispatch"].includes(run.event) && + run.head_sha === head && + run.head_branch === branch && + run.head_repository?.full_name === repository + ) { + return { + run_full: false, + run_id: run.id, + reason: `Reusing full qualification from run ${run.id}; no fresh provider observation`, + }; + } + } + return { + run_full: true, + reason: "No trusted full qualification for this SHA within 24 hours", + }; + } catch { + return { + run_full: true, + reason: "Qualification lookup unavailable; running full validation", + }; + } +} + +if (resolve(process.argv[1] ?? "") === fileURLToPath(import.meta.url)) { + const decision = admit(); + if (process.env.GITHUB_OUTPUT) + appendFileSync( + process.env.GITHUB_OUTPUT, + Object.entries(decision) + .map(([key, value]) => `${key}=${value}\n`) + .join(""), + ); + if (process.env.GITHUB_STEP_SUMMARY) + appendFileSync( + process.env.GITHUB_STEP_SUMMARY, + `### Scheduled qualification\n\n${decision.reason}.\n`, + ); + console.log(JSON.stringify(decision)); +} diff --git a/scripts/ci/required.mjs b/scripts/ci/required.mjs index 4f6586737..01907de37 100644 --- a/scripts/ci/required.mjs +++ b/scripts/ci/required.mjs @@ -1,18 +1,46 @@ +import { CI_FLAGS } from "./scopes.mjs"; +import { recordQualification } from "./qualification.mjs"; + const jobs = JSON.parse(process.env.CI_JOBS); -const outputs = jobs.changes.outputs; -const required = ["changes", "static", "test"]; +const outputs = jobs?.changes?.outputs; +if (!["fast", "full", "reused"].includes(outputs?.tier)) + throw new Error( + "CI classification requires a valid tier: fast, full, or reused", + ); +const invalidFlags = CI_FLAGS.filter( + (flag) => outputs[flag] !== "true" && outputs[flag] !== "false", +); +if (invalidFlags.length) + throw new Error( + `CI classification requires explicit true/false scope outputs: ${invalidFlags.join(", ")}`, + ); +const selectedScopes = CI_FLAGS.filter((flag) => outputs[flag] === "true"); +const reused = outputs.tier === "reused"; +if ( + reused && + (process.env.GITHUB_EVENT_NAME !== "schedule" || + !/^[1-9]\d*$/.test(outputs.qualification_run_id ?? "") || + !Number.isSafeInteger(Number(outputs.qualification_run_id)) || + selectedScopes.length !== 0) +) + throw new Error( + "Reused qualification requires a scheduled admission receipt and no selected lanes", + ); +if (outputs.tier === "full" && selectedScopes.length !== CI_FLAGS.length) + throw new Error("Full qualification requires every canonical CI scope"); +const required = reused ? ["changes"] : ["changes", "static", "test"]; const lanes = { - code: ["build", "test-shard", "sqlite-runtime"], + code: ["build", "test-shard"], runtime: ["windows-native-build", "package-e2e"], package: ["windows-curated"], + sqlite: ["sqlite-runtime"], apple: ["apple-artifacts"], fixtures: ["conformance-fixtures"], readiness: ["reconstruction-readiness"], docs: ["docs"], + workflows: ["static"], }; -for (const [scope, value] of Object.entries(outputs)) { - if (value === "true") required.push(...(lanes[scope] ?? [scope])); -} +for (const scope of selectedScopes) required.push(...(lanes[scope] ?? [scope])); const failed = [...new Set(required)].filter( (name) => jobs[name]?.result !== "success", ); @@ -23,3 +51,9 @@ for (const [name, job] of Object.entries(jobs)) { if (failed.length) throw new Error(`CI lanes did not pass: ${failed.join(", ")}`); console.log("Every selected CI lane passed"); +if (reused) + console.log( + `Qualification reused from run ${outputs.qualification_run_id}; no fresh provider observation`, + ); +if (outputs.tier === "full" && process.env.CI_QUALIFICATION_DIRECTORY) + recordQualification(process.env.CI_QUALIFICATION_DIRECTORY); diff --git a/scripts/ci/scopes.mjs b/scripts/ci/scopes.mjs index 497dfeed0..a8679726c 100644 --- a/scripts/ci/scopes.mjs +++ b/scripts/ci/scopes.mjs @@ -55,6 +55,7 @@ export const SCOPES = { "tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts", "tests/boundary/filesystem/setupUnavailableProvider.test.ts", "tests/boundary/filesystem/windowsNpxRegistration.test.ts", + "tests/acceptance/setup/homeDirectoryFallback.test.ts", "tests/boundary/filesystem/webScriptManifestPaths.test.ts", "tests/boundary/process/ProcessEvidence.host.test.ts", "tests/acceptance/webModuleCli.test.ts", @@ -84,6 +85,55 @@ export const SCOPES = { "tests/boundary/filesystem/javascriptArtifactContentIdentity.test.ts", "tests/boundary/process/sourceMapUncHosts.test.ts", ], + // Native SQLite runtime compatibility for the producer, public adapters, + // fixtures, shared lifecycle, and the package script that defines its suite. + sqlite: [ + "src/sqlite/**", + "src/domain/sqlite/**", + "src/contracts/sqlite/**", + "src/application/sqlite/**", + "src/composition/sqlite.ts", + "src/cli/sqliteCommands.ts", + "src/server/registerSqliteTools.ts", + "src/application/DirectAnalysisStatus*.ts", + "src/application/CapabilityInventory*.ts", + "src/application/AnalysisProvider*.ts", + "src/contracts/toolContracts.ts", + "src/contracts/toolContractTypes.ts", + "src/contracts/toolEffects*.ts", + "src/contracts/toolOutputSchemaPrimitives.ts", + "src/domain/analysisError*.ts", + "src/domain/evidence*.ts", + "src/domain/inputIssueProjection*.ts", + "src/domain/jsonSerialization*.ts", + "src/domain/jsonValue*.ts", + "src/domain/localPath*.ts", + "src/domain/providerAdapterError*.ts", + "src/domain/providerCleanupError*.ts", + "src/domain/result*.ts", + "src/process/OwnedCommand*.ts", + "src/process/ProviderProcess*.ts", + "src/process/PrivateRuntimeRoot*.ts", + "src/artifacts/ArtifactReader*.ts", + "src/artifacts/ArtifactResourceScope*.ts", + "src/artifacts/ArtifactPaths*.ts", + "src/artifacts/readStableArtifact*.ts", + "src/filesystem/OwnedFileHandle*.ts", + "src/server/EvidenceMcpServer*.ts", + "src/server/analysisAdmission*.ts", + "src/server/contractToolHandler*.ts", + "src/server/toolRegistrationOptions*.ts", + "src/server/createServer*.ts", + "src/cli.ts", + "src/cliCommandNames.ts", + "src/cliLogging.ts", + "src/cli/commandCancellation.ts", + "tests/boundary/sqlite/**", + "tests/fixtures/sqlite/**", + "tests/acceptance/sqliteDatabaseCli.test.ts", + "tests/boundary/mcp/serverLifecycleMcp.test.ts", + ".github/workflows/sqlite-runtime.yml", + ], browser: [ ".github/workflows/real-browser.yml", "scripts/verify-real-browser.mjs", @@ -299,6 +349,7 @@ export const SCOPES = { nativeaot: [ "bridge/nativeaot/**", "scripts/generate-nativeaot-fixtures.mjs", + "scripts/lib/nativeaot-build.*", "tests/fixtures/nativeaot/**", ".github/workflows/nativeaot-fixtures.yml", ], @@ -311,6 +362,20 @@ export const SCOPES = { ], }; +export const CI_FLAGS = [ + ...new Set([ + "code", + "runtime", + "package", + "apple", + "fixtures", + "readiness", + "docs", + "workflows", + ...Object.keys(SCOPES), + ]), +]; + // Verifier entrypoints that only manual, licensed, or self-hosted workflows // run. No selected CI lane executes them, so their edits need only the static // checks and the source-test suite. Shared helpers under scripts/lib remain diff --git a/scripts/ci/test-history.mjs b/scripts/ci/test-history.mjs new file mode 100644 index 000000000..4386f48af --- /dev/null +++ b/scripts/ci/test-history.mjs @@ -0,0 +1,114 @@ +import { execFileSync } from "node:child_process"; +import { appendFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ARTIFACT_NAME = "test-timings"; +const MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000; +const MAX_CANDIDATES = 5; +const positiveId = (value) => + (typeof value === "string" || typeof value === "number") && + /^[1-9]\d*$/.test(String(value)) && + Number.isSafeInteger(Number(value)); + +function findTimingRun({ repository, branch, repositoryId, now = Date.now() }) { + if ( + !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository ?? "") || + !branch || + !positiveId(repositoryId) + ) + return ""; + const deadline = Date.now() + 20_000; + const api = (...arguments_) => { + const remaining = deadline - Date.now(); + if (remaining <= 0) + throw new Error("Timing history lookup budget exhausted"); + return JSON.parse( + execFileSync("gh", ["api", "--method", "GET", ...arguments_], { + encoding: "utf8", + timeout: Math.min(10_000, remaining), + maxBuffer: 4 * 1024 * 1024, + stdio: ["ignore", "pipe", "pipe"], + }), + ); + }; + + const { artifacts } = api( + `repos/${repository}/actions/artifacts`, + "-f", + `name=${ARTIFACT_NAME}`, + "-F", + "per_page=100", + ); + if (!Array.isArray(artifacts)) + throw new Error("Missing timing artifact inventory"); + const candidates = artifacts + .filter((artifact) => { + const lineage = artifact?.workflow_run; + const age = now - Date.parse(artifact?.created_at); + return ( + artifact?.name === ARTIFACT_NAME && + artifact?.expired === false && + typeof artifact?.created_at === "string" && + Number.isFinite(age) && + age >= 0 && + age < MAX_AGE_MS && + positiveId(lineage?.id) && + positiveId(lineage?.repository_id) && + positiveId(lineage?.head_repository_id) && + lineage.repository_id === lineage.head_repository_id && + lineage.repository_id === Number(repositoryId) && + lineage.head_branch === branch + ); + }) + .sort( + (left, right) => + Date.parse(right.created_at) - Date.parse(left.created_at), + ) + .slice(0, MAX_CANDIDATES); + + for (const artifact of candidates) { + const run = api( + `repos/${repository}/actions/runs/${artifact.workflow_run.id}`, + ); + const runAge = now - Date.parse(run?.created_at); + if ( + typeof run?.created_at === "string" && + Number.isFinite(runAge) && + runAge >= 0 && + runAge < MAX_AGE_MS && + run.id === artifact.workflow_run.id && + run.status === "completed" && + run.conclusion === "success" && + run.path === ".github/workflows/ci.yml" && + ["schedule", "workflow_dispatch"].includes(run.event) && + run.head_branch === branch && + run.head_repository?.full_name === repository + ) + return String(run.id); + } + return ""; +} + +function write(runId) { + if (process.env.GITHUB_OUTPUT) + appendFileSync(process.env.GITHUB_OUTPUT, `run-id=${runId}\n`); + console.log(JSON.stringify({ run_id: runId })); +} + +if ( + process.argv[1] && + fileURLToPath(import.meta.url) === resolve(process.argv[1]) +) { + let runId = ""; + try { + runId = findTimingRun({ + repository: process.env.CI_REPOSITORY, + branch: process.env.CI_DEFAULT_BRANCH, + repositoryId: process.env.CI_REPOSITORY_ID, + }); + } catch { + // History improves shard ordering but must never block CI. + } + write(runId); +} diff --git a/scripts/ci/test-report.mjs b/scripts/ci/test-report.mjs index a3686d6ed..035a01990 100644 --- a/scripts/ci/test-report.mjs +++ b/scripts/ci/test-report.mjs @@ -1,28 +1,36 @@ +import { execFileSync } from "node:child_process"; import { appendFile, mkdir, readFile, rm, writeFile } from "node:fs/promises"; import { isAbsolute, join, relative, resolve, sep } from "node:path"; import { z } from "zod"; +import { compareTestSelection } from "./test-selection.mjs"; + const root = process.cwd(); const historyDirectory = join(root, ".cache/ci-test-history"); const historyPath = join(historyDirectory, "test-results.json"); +const selectionDirectory = join(root, ".cache/ci-test-selection"); +const selectionPath = join(selectionDirectory, "report.json"); // Never let a failed or partial rerun leave a previous successful history file. await rm(historyPath, { force: true }); +await rm(selectionPath, { force: true }); const report = z .object({ + version: z.literal(1), success: z.boolean(), - numFailedTests: z.number().int().nonnegative(), - testResults: z.array( + reason: z.string().optional(), + unhandledErrors: z.number().int().nonnegative().optional(), + files: z.array( z.object({ name: z.string().min(1), - startTime: z.number().finite(), - endTime: z.number().finite(), + durationMs: z.number().finite().nonnegative(), + state: z.string().optional(), }), ), }) - .parse(JSON.parse(await readFile("test-results.json", "utf8"))); + .parse(JSON.parse(await readFile("test-timings.json", "utf8"))); -const files = report.testResults.map(({ name, startTime, endTime }) => { +const files = report.files.map(({ name, durationMs, state }) => { const path = relative(root, resolve(root, name)); if ( path === "" || @@ -31,32 +39,85 @@ const files = report.testResults.map(({ name, startTime, endTime }) => { isAbsolute(path) ) throw new Error(`Test report path is outside the checkout: ${name}`); - const duration = endTime - startTime; - if (!Number.isFinite(duration) || duration < 0) - throw new Error(`Test report has an invalid duration: ${name}`); - return { name: path.split(sep).join("/"), startTime: 0, endTime: duration }; + return { name: path.split(sep).join("/"), durationMs, state }; }); const complete = process.env.SHARD_RESULT === "success"; const passed = - complete && - process.env.MERGE_RESULT === "success" && - report.success && - report.numFailedTests === 0; + complete && process.env.MERGE_RESULT === "success" && report.success; +// Successful shards and merged reports must account for the complete portable +// inventory. Coverage thresholds alone cannot prove that every file ran. +const verifyInventory = process.env.CI_VERIFY_TEST_INVENTORY === "true"; +const expected = + verifyInventory || process.env.CI_TEST_SELECTION + ? execFileSync("git", ["ls-files", "-z", "--", "src", "tests"], { + encoding: "utf8", + maxBuffer: 8 * 1024 * 1024, + }) + .split("\0") + .filter((path) => path.endsWith(".test.ts")) + : []; +let selection; +if (process.env.CI_TEST_SELECTION) { + const comparison = compareTestSelection( + JSON.parse(process.env.CI_TEST_SELECTION), + expected, + files, + ); + selection = { + ...comparison, + complete: + comparison.complete && + report.unhandledErrors === 0 && + ["passed", "failed"].includes(report.reason) && + ["success", "failure"].includes(process.env.SHARD_RESULT) && + ["success", "failure"].includes(process.env.MERGE_RESULT), + executionSha: process.env.GITHUB_SHA ?? null, + prHeadSha: process.env.CI_PR_HEAD_SHA ?? null, + runId: process.env.GITHUB_RUN_ID ?? null, + runAttempt: process.env.GITHUB_RUN_ATTEMPT ?? null, + }; + await mkdir(selectionDirectory, { recursive: true }); + await writeFile(selectionPath, JSON.stringify(selection)); +} +if (passed && verifyInventory) { + const actual = files.map(({ name }) => name); + const expectedSet = new Set(expected); + const actualSet = new Set(actual); + const missing = expected.filter((path) => !actualSet.has(path)); + const unexpected = actual.filter((path) => !expectedSet.has(path)); + if (missing.length || unexpected.length || actualSet.size !== actual.length) + throw new Error( + `Incomplete portable test inventory: ${JSON.stringify({ missing, unexpected, duplicateFiles: actual.length - actualSet.size })}`, + ); +} const summary = [ complete ? "## Merged test diagnostics" : "## Partial test diagnostics", "", + ...(selection + ? [ + "### Observational PR test selection", + "", + `Plan: ${selection.plan.mode}. Proposed files: ${selection.selected.length}; omitted: ${selection.omitted.length}.`, + `Full-run comparison: ${selection.complete ? "complete" : "incomplete"}; failures outside proposed selection: ${selection.missedFailures.length}.`, + "The complete suite still ran. This report cannot enable omissions or qualify a revision. Skipped, missing, and interrupted observations do not establish parity.", + "", + ] + : []), `Shard result: ${process.env.SHARD_RESULT ?? "unknown"}; merge result: ${process.env.MERGE_RESULT ?? "unknown"}.`, passed ? "Successful timing history is available." : "This report is diagnostic only and is not a successful timing baseline.", "", + "Durations include tests and hooks, worker preparation, environment, imports, and setup. They are scheduling weights, not summed workflow wall time.", + "", "| Slowest file | Duration (ms) |", "| --- | ---: |", ...files - .toSorted((left, right) => right.endTime - left.endTime) + .toSorted((left, right) => right.durationMs - left.durationMs) .slice(0, 20) .map( - ({ name, endTime }) => `| ${name.replaceAll("|", "\\|")} | ${endTime} |`, + ({ name, durationMs }) => + `| ${name.replaceAll("|", "\\|")} | ${durationMs} |`, ), "", ].join("\n"); @@ -68,6 +129,10 @@ if (passed) { await mkdir(historyDirectory, { recursive: true }); await writeFile( historyPath, - JSON.stringify({ success: true, numFailedTests: 0, testResults: files }), + JSON.stringify({ + version: 1, + success: true, + files: files.map(({ name, durationMs }) => ({ name, durationMs })), + }), ); } diff --git a/scripts/ci/test-selection.d.mts b/scripts/ci/test-selection.d.mts new file mode 100644 index 000000000..c19414398 --- /dev/null +++ b/scripts/ci/test-selection.d.mts @@ -0,0 +1,35 @@ +export interface TestSelectionPlan { + readonly version: 1; + readonly mode: "full" | "candidate"; + readonly owners: readonly string[]; + readonly changedTests: readonly string[]; + readonly changedPaths: readonly string[]; + readonly reason: string; +} +export function planTestSelection( + files: readonly string[], + event: string, + tier: string, +): TestSelectionPlan; +export function compareTestSelection( + plan: unknown, + inventory: readonly string[], + results: readonly { + readonly name: string; + readonly durationMs: number; + readonly state?: string; + }[], +): { + readonly version: 1; + readonly observational: true; + readonly plan: TestSelectionPlan; + readonly selected: readonly string[]; + readonly omitted: readonly string[]; + readonly missing: readonly string[]; + readonly unexpected: readonly string[]; + readonly duplicateFiles: number; + readonly unobserved: readonly string[]; + readonly missedFailures: readonly string[]; + readonly complete: boolean; + readonly omittedDurationMs: number; +}; diff --git a/scripts/ci/test-selection.mjs b/scripts/ci/test-selection.mjs new file mode 100644 index 000000000..8165e3658 --- /dev/null +++ b/scripts/ci/test-selection.mjs @@ -0,0 +1,151 @@ +import { matchesGlob } from "node:path"; + +// Candidate ownership only: these leaf adapters and their producer tests can be +// compared with full-suite outcomes. This table never changes test execution. +// Shared application/domain code and dynamic CLI/MCP consumers are not leaf owners. +const OWNERS = { + adb: ["src/adb/**", "tests/boundary/providers/adb/**"], + apktool: ["src/apktool/**"], + dotnet: ["src/dotnet/**"], + evm: ["src/evm/**", "tests/boundary/evm/**"], + firmware: ["src/firmware/**", "tests/boundary/firmware/**"], + flutter: ["src/flutter/**"], + ghidra: ["src/ghidra/**", "tests/boundary/providers/ghidra/**"], + hopper: ["src/hopper/**", "tests/boundary/providers/hopper/**"], + ida: ["src/ida/**", "tests/boundary/providers/ida/**"], + jeb: ["src/jeb/**"], + pcap: ["src/pcap/**", "tests/boundary/pcap/**"], + sqlite: ["src/sqlite/**", "tests/boundary/sqlite/**"], + wasm: ["src/wasm/**"], +}; +const ownersOf = (path) => + Object.entries(OWNERS) + .filter(([, patterns]) => patterns.some((glob) => matchesGlob(path, glob))) + .map(([owner]) => owner); +const validPath = (path) => + typeof path === "string" && + /^(src|tests)\//.test(path) && + !/[\\\0\r\n]/.test(path) && + !path.split("/").some((part) => ["", ".", ".."].includes(part)); +const full = (reason, changedPaths = []) => ({ + version: 1, + mode: "full", + owners: [], + changedTests: [], + changedPaths, + reason, +}); + +/** Plan an observational PR subset from the classifier's existing Git diff. */ +export function planTestSelection(files, event, tier) { + if (event !== "pull_request" || tier !== "fast") + return full("Only ordinary PRs are candidates", files); + if (!files.length) return full("No changed paths available"); + const owners = new Set(); + const changedTests = []; + for (const path of files) { + if (!validPath(path)) + return full(`Shared or unknown input: ${path}`, files); + const matches = ownersOf(path); + if (!matches.length) return full(`Shared or unknown input: ${path}`, files); + for (const owner of matches) owners.add(owner); + if (path.endsWith(".test.ts")) changedTests.push(path); + } + return { + version: 1, + mode: "candidate", + owners: [...owners].sort(), + changedTests: [...new Set(changedTests)].sort(), + changedPaths: files, + reason: + "Observe affected leaf owners; retain integration and unowned tests", + }; +} + +/** Compare a proposal with the full run; missing observations never prove parity. */ +export function compareTestSelection(plan, inventory, results) { + if ( + plan?.version !== 1 || + !["full", "candidate"].includes(plan.mode) || + !Array.isArray(plan.owners) || + plan.owners.some((owner) => !Object.hasOwn(OWNERS, owner)) || + !Array.isArray(plan.changedTests) || + !Array.isArray(plan.changedPaths) || + plan.changedPaths.some((path) => typeof path !== "string") || + plan.changedTests.some( + (path) => !validPath(path) || !path.endsWith(".test.ts"), + ) || + typeof plan.reason !== "string" || + (plan.mode === "candidate" && !plan.owners.length) || + (plan.mode === "full" && (plan.owners.length || plan.changedTests.length)) + ) + throw new Error("Invalid observational test selection plan"); + const expected = new Set(inventory); + if (!expected.size || expected.size !== inventory.length) + throw new Error("Test selection requires a nonempty unique inventory"); + const ownersByFile = new Map( + plan.mode === "candidate" + ? inventory.map((path) => [path, ownersOf(path)]) + : [], + ); + // Removed/renamed tests have no current executable identity. Keep all tests. + const removed = plan.changedTests.filter((path) => !expected.has(path)); + const missingOwners = plan.owners.filter( + (owner) => + ![...ownersByFile.values()].some((owners) => owners.includes(owner)), + ); + const effective = removed.length + ? full( + `Changed tests absent from current inventory: ${removed.join(", ")}`, + plan.changedPaths, + ) + : missingOwners.length + ? full( + `Owners without executable tests: ${missingOwners.join(", ")}`, + plan.changedPaths, + ) + : plan; + const selected = []; + const omitted = []; + for (const path of inventory.toSorted()) { + const owners = ownersByFile.get(path) ?? []; + const keep = + effective.mode === "full" || + !owners.length || + effective.changedTests.includes(path) || + owners.some((owner) => effective.owners.includes(owner)); + (keep ? selected : omitted).push(path); + } + const actual = new Set(results.map((file) => file.name)); + const missing = inventory.filter((path) => !actual.has(path)); + const unexpected = [...actual].filter((path) => !expected.has(path)); + const duplicateFiles = results.length - actual.size; + const unobserved = results + .filter((file) => !["passed", "failed"].includes(file.state)) + .map((file) => file.name); + const omittedSet = new Set(omitted); + const missedFailures = results + .filter((file) => omittedSet.has(file.name) && file.state === "failed") + .map((file) => file.name); + return { + version: 1, + observational: true, + plan: effective, + selected, + omitted, + missing, + unexpected, + duplicateFiles, + unobserved, + missedFailures, + complete: + !missing.length && + !unexpected.length && + !duplicateFiles && + !unobserved.length, + // Phase totals are scheduling weights, not an estimate of wall-time savings. + omittedDurationMs: results + .filter((file) => omittedSet.has(file.name)) + .reduce((sum, file) => sum + file.durationMs, 0), + }; +} diff --git a/scripts/ci/test-timing-reporter.mjs b/scripts/ci/test-timing-reporter.mjs new file mode 100644 index 000000000..ce0b1c5dc --- /dev/null +++ b/scripts/ci/test-timing-reporter.mjs @@ -0,0 +1,43 @@ +import { writeFile } from "node:fs/promises"; + +/** @implements {import("vitest/node").Reporter} */ +export default class TestTimingReporter { + /** + * @param {ReadonlyArray} modules + * @param {ReadonlyArray} errors + * @param {import("vitest/node").TestRunEndReason} reason + */ + async onTestRunEnd(modules, errors, reason) { + const files = modules.map((module) => { + const diagnostic = module.diagnostic(); + // These disjoint phases match Vitest's per-file wall-time accounting. + // Import timings already include transform waits; do not add them again. + const phases = { + execution: diagnostic.duration, + preparation: diagnostic.prepareDuration, + environment: diagnostic.environmentSetupDuration, + imports: diagnostic.collectDuration, + setup: diagnostic.setupDuration, + }; + return { + name: module.moduleId, + state: module.state(), + durationMs: Object.values(phases).reduce( + (total, value) => total + value, + 0, + ), + phases, + }; + }); + await writeFile( + "test-timings.json", + JSON.stringify({ + version: 1, + success: reason === "passed" && errors.length === 0, + reason, + unhandledErrors: errors.length, + files, + }), + ); + } +} diff --git a/scripts/ci/verified-package.mjs b/scripts/ci/verified-package.mjs new file mode 100644 index 000000000..1053760b2 --- /dev/null +++ b/scripts/ci/verified-package.mjs @@ -0,0 +1,235 @@ +import { createHash } from "node:crypto"; +import { createReadStream } from "node:fs"; +import { execFile } from "node:child_process"; +import { copyFile, readFile, writeFile } from "node:fs/promises"; +import { join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; + +const MANIFEST_NAME = "manifest.json"; +const TARBALL_NAME = "package.tgz"; +const MANIFEST_KEYS = [ + "schemaVersion", + "sourceSha", + "runId", + "runAttempt", + "platform", + "architecture", + "packageVersion", + "nodeVersion", + "sha256", +].sort(); +const execFileAsync = promisify(execFile); + +/** Normalize workflow identity and host facts into the manifest-owned fields. */ +export function createVerifiedPackageMetadata({ + sourceSha, + runId, + runAttempt, + platform, + architecture, + packageVersion, + nodeVersion, +}) { + if (!/^[a-f0-9]{40}$/u.test(sourceSha)) + throw new Error("Source SHA must be a full commit SHA"); + return { + sourceSha, + runId: parsePositiveInteger(runId, "GITHUB_RUN_ID"), + runAttempt: parsePositiveInteger(runAttempt, "GITHUB_RUN_ATTEMPT"), + platform, + architecture, + packageVersion, + nodeVersion, + }; +} + +/** Build the single supported manifest representation for a verified tarball. */ +function createVerifiedPackageManifest(metadata) { + const manifest = { schemaVersion: 1, ...metadata }; + validateManifestShape(manifest); + return manifest; +} + +/** Write a manifest after the caller has completed qualification and cleanup. */ +export async function writeVerifiedPackageManifest(directory, metadata) { + const manifest = createVerifiedPackageManifest(metadata); + await writeFile( + join(directory, MANIFEST_NAME), + `${JSON.stringify(manifest, null, 2)}\n`, + { encoding: "utf8" }, + ); + return manifest; +} + +/** Copy the qualified archive under its fixed name and prepare its manifest. */ +export async function retainVerifiedPackage({ + sourceTarball, + directory, + metadata, +}) { + const tarball = join(directory, TARBALL_NAME); + await copyFile(sourceTarball, tarball); + const sha256 = await sha256File(tarball); + return { + directory, + metadata: createVerifiedPackageManifest({ ...metadata, sha256 }), + }; +} + +/** Validate a retained package against the current checkout and workflow attempt. */ +async function validateVerifiedPackage({ + directory, + sourceSha, + runId, + runAttempt, + packageVersion, + nodeVersion, +}) { + if (!/^[a-f0-9]{40}$/u.test(sourceSha)) + throw new Error("Expected source SHA must be a full commit SHA"); + if (!Number.isSafeInteger(runId) || runId <= 0) + throw new Error("Expected workflow run ID must be a positive integer"); + if (!Number.isSafeInteger(runAttempt) || runAttempt <= 0) + throw new Error("Expected workflow run attempt must be a positive integer"); + const manifestPath = join(directory, MANIFEST_NAME); + let manifest; + try { + manifest = JSON.parse(await readFile(manifestPath, "utf8")); + } catch (cause) { + throw new Error(`Could not read verified package manifest: ${cause}`, { + cause, + }); + } + validateManifestShape(manifest); + assertEqual(manifest.sourceSha, sourceSha, "source SHA"); + assertEqual(manifest.runId, runId, "workflow run ID"); + // A successful producer may belong to an earlier attempt when only failed + // publisher jobs are rerun. The workflow still requires same-run qualification. + if (manifest.runAttempt > runAttempt) + throw new Error("Verified package workflow run attempt is from the future"); + assertEqual(manifest.platform, "linux", "verifier platform"); + assertEqual(manifest.architecture, "x64", "verifier architecture"); + assertEqual(manifest.packageVersion, packageVersion, "package version"); + assertEqual(manifest.nodeVersion, nodeVersion, "Node.js version"); + + // The artifact format deliberately fixes the name; no manifest value can + // redirect validation to another path. + const tarball = resolve(directory, TARBALL_NAME); + const digest = await sha256File(tarball); + assertEqual(manifest.sha256, digest, "tarball SHA-256"); + return tarball; +} + +function validateManifestShape(manifest) { + if ( + typeof manifest !== "object" || + manifest === null || + Array.isArray(manifest) + ) + throw new Error("Verified package manifest must be a JSON object"); + const keys = Object.keys(manifest).sort(); + if ( + keys.length !== MANIFEST_KEYS.length || + keys.some((key, index) => key !== MANIFEST_KEYS[index]) + ) + throw new Error("Verified package manifest has missing or unknown fields"); + if (manifest.schemaVersion !== 1) + throw new Error("Unsupported verified package manifest schema version"); + if ( + typeof manifest.sourceSha !== "string" || + !/^[a-f0-9]{40}$/u.test(manifest.sourceSha) + ) + throw new Error("Verified package manifest has an invalid source SHA"); + if (!Number.isSafeInteger(manifest.runId) || manifest.runId <= 0) + throw new Error("Verified package manifest has an invalid workflow run ID"); + if (!Number.isSafeInteger(manifest.runAttempt) || manifest.runAttempt <= 0) + throw new Error( + "Verified package manifest has an invalid workflow run attempt", + ); + for (const key of [ + "platform", + "architecture", + "packageVersion", + "nodeVersion", + ]) + if (typeof manifest[key] !== "string" || manifest[key].length === 0) + throw new Error(`Verified package manifest has an invalid ${key}`); + if ( + typeof manifest.sha256 !== "string" || + !/^[a-f0-9]{64}$/u.test(manifest.sha256) + ) + throw new Error("Verified package manifest has an invalid tarball SHA-256"); +} + +function assertEqual(actual, expected, label) { + if (actual !== expected) + throw new Error(`Verified package ${label} mismatch`); +} + +async function sha256File(path) { + const hash = createHash("sha256"); + for await (const chunk of createReadStream(path)) hash.update(chunk); + return hash.digest("hex"); +} + +async function validateFromCli(directory) { + const sourceSha = process.env.GITHUB_SHA; + const runId = parsePositiveInteger( + process.env.GITHUB_RUN_ID, + "GITHUB_RUN_ID", + ); + const runAttempt = parsePositiveInteger( + process.env.GITHUB_RUN_ATTEMPT, + "GITHUB_RUN_ATTEMPT", + ); + if (sourceSha === undefined || !/^[a-f0-9]{40}$/u.test(sourceSha)) + throw new Error("GITHUB_SHA must be a full commit SHA"); + const checkoutSha = ( + await execFileAsync("git", ["rev-parse", "HEAD"]) + ).stdout.trim(); + assertEqual(checkoutSha, sourceSha, "checked out source SHA"); + const packageJson = JSON.parse(await readFile("package.json", "utf8")); + const tarball = await validateVerifiedPackage({ + directory, + sourceSha, + runId, + runAttempt, + packageVersion: packageJson.version, + nodeVersion: process.version, + }); + if (process.env.GITHUB_OUTPUT === undefined) + throw new Error( + "GITHUB_OUTPUT is required to publish the validated tarball path", + ); + await writeFile(process.env.GITHUB_OUTPUT, `tarball=${tarball}\n`, { + encoding: "utf8", + flag: "a", + }); + process.stdout.write(`${tarball}\n`); +} + +function parsePositiveInteger(value, name) { + if (value === undefined || !/^[1-9]\d*$/u.test(value)) + throw new Error(`${name} must be a positive integer`); + const parsed = Number(value); + if (!Number.isSafeInteger(parsed)) + throw new Error(`${name} must be a safe positive integer`); + return parsed; +} + +const invokedPath = process.argv[1]; +if ( + invokedPath !== undefined && + resolve(invokedPath) === fileURLToPath(import.meta.url) +) { + const [command, directory, ...extra] = process.argv.slice(2); + if (command !== "validate" || directory === undefined || extra.length > 0) { + process.stderr.write( + "Usage: node scripts/ci/verified-package.mjs validate \n", + ); + process.exitCode = 2; + } else { + await validateFromCli(directory); + } +} diff --git a/scripts/fixtures/generate-mitmproxy-capture.py b/scripts/fixtures/generate-mitmproxy-capture.py index 4be3dd4a7..880c5e690 100644 --- a/scripts/fixtures/generate-mitmproxy-capture.py +++ b/scripts/fixtures/generate-mitmproxy-capture.py @@ -45,6 +45,20 @@ class Generator: assert "ows-secret" not in json.dumps(projected), projected if isinstance(value, bytes): assert projected["binary_fields"][-1]["state"] == "redacted", projected + body = b"A" * 12345 + state = {"response": {"content": body}} + control = adapter.project_record(state, []) + field = control["binary_fields"][0] + assert field["state"] == "retained" and field["bytes"] == len(body), control + for literal in ["12345", "2345"]: + # Only the generated byte count matches this exclusion. + assert literal not in control["reported"]["response"]["content"] + assert literal not in field["content_base64"] and literal not in field["sha256"] + projected = adapter.project_record(state, [literal]) + assert projected["reported"]["response"]["content"] is None, projected + assert projected["binary_fields"] == [{"pointer": "/response/content", "representation": "producer-bytes", "state": "redacted", "content_base64": None, "bytes": None, "sha256": None}], projected + assert {"pointer": "/response/content", "reason": "explicit-sensitive-value"} in projected["redactions"], projected + assert literal not in json.dumps(projected), projected (root / "native-error-classifications.json").write_text(json.dumps({"passed": len(classifications) + 2})) first = http.HTTPFlow(connection.Client(peername=("127.0.0.1", 1), sockname=("127.0.0.1", 2)), connection.Server(address=("example.test", 80))) first.id = "original-producer-id" diff --git a/scripts/generate-nativeaot-fixtures.mjs b/scripts/generate-nativeaot-fixtures.mjs index 84a8ac533..fa9127cf3 100644 --- a/scripts/generate-nativeaot-fixtures.mjs +++ b/scripts/generate-nativeaot-fixtures.mjs @@ -4,9 +4,14 @@ import { createHash } from "node:crypto"; import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; +import { + buildNativeAotFixture, + nativeAotCommandError, + supportsNativeAotFixtureHost, +} from "./lib/nativeaot-build.mjs"; const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); -if (process.arch !== "x64" || !["linux", "win32"].includes(process.platform)) +if (!supportsNativeAotFixtureHost(process.platform, process.arch)) throw new Error( "NativeAOT fixture lane requires Linux or Windows x64; it does not cross-compile NativeAOT.", ); @@ -40,9 +45,7 @@ const run = (command, args) => { maxBuffer: 8 * 1024 * 1024, }); if (result.error || result.status !== 0) - throw new Error( - `NativeAOT fixture lane requires/action failed ${command}: ${result.error?.message ?? ""}\n${result.stdout ?? ""}${result.stderr ?? ""}`, - ); + throw nativeAotCommandError(command, args[0], result); return result.stdout; }; const dotnet = process.env.REA_NATIVEAOT_DOTNET ?? "dotnet"; @@ -57,20 +60,12 @@ if (process.platform === "linux") { run("clang", ["--version"]); } const map = join(output, "NativeAotFixture.map"); -run(dotnet, [ - "publish", - join(root, "tests/fixtures/nativeaot/NativeAotFixture.csproj"), - "-r", +await buildNativeAotFixture(run, { + dotnet, + project: join(root, "tests/fixtures/nativeaot/NativeAotFixture.csproj"), runtime, - "-c", - "Release", - "-o", - join(output, "symbols"), - "--maxcpucount:1", - `-p:BaseIntermediateOutputPath=${join(output, "obj")}/`, - `-p:BaseOutputPath=${join(output, "bin")}/`, - `-p:NativeAotMapPath=${map}`, -]); + output, +}); const name = process.platform === "win32" ? "NativeAotFixture.exe" : "NativeAotFixture"; const binary = join(output, "symbols", name); diff --git a/scripts/generate-third-party-inventory.mjs b/scripts/generate-third-party-inventory.mjs new file mode 100644 index 000000000..57934ebda --- /dev/null +++ b/scripts/generate-third-party-inventory.mjs @@ -0,0 +1,120 @@ +import { createHash } from "node:crypto"; +import { readFile } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { ensureGeneratedFile } from "./lib/generated-file.mjs"; + +const arguments_ = new Set(process.argv.slice(2)); +for (const argument of arguments_) + if (argument !== "--check") + throw new Error(`Unknown inventory option: ${argument}`); +const root = join(dirname(fileURLToPath(import.meta.url)), ".."); +const lock = JSON.parse( + await readFile(join(root, "package-lock.json"), "utf8"), +); +const entries = Object.entries(lock.packages) + .filter(([path]) => path !== "") + .map(([path, record]) => ({ + path, + name: record.name ?? path.slice(path.lastIndexOf("node_modules/") + 13), + version: record.version, + license: record.license ?? "UNDECLARED", + resolved: record.resolved, + integrity: record.integrity, + dev: record.dev === true, + optional: record.optional === true, + })) + .sort((left, right) => + left.path < right.path ? -1 : left.path > right.path ? 1 : 0, + ); +for (const entry of entries) + for (const field of ["name", "version", "resolved", "integrity"]) + if (typeof entry[field] !== "string" || entry[field].length === 0) + throw new Error(`Missing locked ${field}: ${entry.path}`); +const runtime = entries.filter(({ dev }) => !dev); +const runtimeFingerprint = createHash("sha256") + .update(JSON.stringify(runtime)) + .digest("hex"); +const source = [ + "REA npm dependency inventory", + "Prepared from the root package-lock.json; refresh this inventory when locked dependencies change.", + "License identifiers are upstream lockfile declarations, not a legal assessment.", + "Runtime includes transitive and optional platform packages; development includes build, test and website tooling.", + `Locked package entries: ${entries.length}; runtime: ${runtime.length}.`, + "Full runtime copyright/license/NOTICE texts: npm-runtime-notices.txt.", + "", + ...entries.flatMap((entry) => [ + `${entry.name}@${entry.version} | ${entry.dev ? "development" : "runtime"}${entry.optional ? ", optional" : ""} | ${entry.license}`, + ` Lockfile path: ${entry.path}`, + ` Package: https://www.npmjs.com/package/${entry.name}/v/${entry.version}`, + ` Archive: ${entry.resolved}`, + ` Integrity: ${entry.integrity}`, + ]), + "", +].join("\n"); +await ensureGeneratedFile({ + path: join(root, "licenses/npm-dependencies.txt"), + source, + check: arguments_.has("--check"), + generateCommand: "npm run licenses:generate", +}); + +if (arguments_.has("--check")) { + const notices = await readFile( + join(root, "licenses/npm-runtime-notices.txt"), + "utf8", + ); + const headings = [...notices.matchAll(/^===== (.+) =====$/gmu)]; + const sections = new Map(); + for (const [index, heading] of headings.entries()) { + if (sections.has(heading[1])) + throw new Error(`Duplicate runtime notice: ${heading[1]}`); + sections.set( + heading[1], + notices.slice( + heading.index + heading[0].length + 1, + headings[index + 1]?.index, + ), + ); + } + for (const entry of runtime) { + const identity = `${entry.name}@${entry.version}`; + const section = sections.get(identity); + if (section === undefined) + throw new Error(`Missing runtime notice: ${identity}`); + const metadata = [ + `Declared license: ${entry.license}`, + `Archive: ${entry.resolved}`, + `Integrity: ${entry.integrity}`, + "", + ].join("\n"); + if (!section.startsWith(metadata)) + throw new Error(`Runtime notice metadata differs for ${identity}`); + } + if ( + !notices + .slice(0, headings[0]?.index) + .includes( + `Runtime dependency fingerprint (SHA-256): ${runtimeFingerprint}\n`, + ) + ) + throw new Error( + `Runtime notice fingerprint differs; refresh verified notices for ${runtimeFingerprint}`, + ); + const references = JSON.parse( + await readFile(join(root, "licenses/upstream-sources.json"), "utf8"), + ); + for (const reference of references) { + const bytes = await readFile(join(root, reference.file)); + if (createHash("sha256").update(bytes).digest("hex") !== reference.sha256) + throw new Error(`Preserved notice digest differs: ${reference.file}`); + } +} +console.log( + JSON.stringify({ + locked_packages: entries.length, + runtime_packages: runtime.length, + runtime_dependency_fingerprint: runtimeFingerprint, + }), +); diff --git a/scripts/hopper-demo-x11.py b/scripts/hopper-demo-x11.py index 470c9fd28..da2fe884f 100644 --- a/scripts/hopper-demo-x11.py +++ b/scripts/hopper-demo-x11.py @@ -10,6 +10,7 @@ import json import os from pathlib import Path import secrets +import select import stat import subprocess import tempfile @@ -118,6 +119,7 @@ class XWindowAttributes(ctypes.Structure): def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("--probe", action="store_true") + parser.add_argument("--owner-stdin", action="store_true") parser.add_argument("--hopper") parser.add_argument("--socket") parser.add_argument( @@ -133,6 +135,43 @@ def parse_args() -> argparse.Namespace: return parser.parse_args() +class OwnerLifetime: + """The launcher's private pipe is a lifetime capability, independent of PIDs.""" + + def __init__(self, enabled: bool) -> None: + self._poll = select.poll() if enabled else None + if self._poll is not None: + # Node/libuv can implement piped stdio with a Unix socket pair. + mode = os.fstat(0).st_mode + if not (stat.S_ISFIFO(mode) or stat.S_ISSOCK(mode)): + raise AdapterFailure( + INVALID_LAUNCH_COMMAND, + "invalid_launch_command", + "owner lifetime requires a private stdin pipe", + ) + self._poll.register(0, select.POLLIN | select.POLLHUP | select.POLLERR) + + def alive(self) -> bool: + if self._poll is None: + return True + for _, events in self._poll.poll(0): + if events & (select.POLLHUP | select.POLLERR | select.POLLNVAL): + return False + if events & select.POLLIN and not os.read(0, 4096): + return False + return True + + +def wait_for_hopper(child: subprocess.Popen[bytes], owner: OwnerLifetime) -> int: + while owner.alive(): + try: + return child.wait(timeout=0.1) + except subprocess.TimeoutExpired: + continue + # run_launch's finally owns cleanup of both direct, unreaped children. + return 0 + + def digest(path: Path) -> str: value = hashlib.sha256() with path.open("rb") as file: @@ -572,6 +611,7 @@ def start_xvfb( "-auth", str(authority), ], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, ) @@ -627,6 +667,9 @@ def run_launch(args: argparse.Namespace) -> int: "invalid_launch_command", "missing Hopper launch coordinates", ) + owner = OwnerLifetime(args.owner_stdin) + if not owner.alive(): + return 0 hopper = Path(args.hopper) socket = Path(args.socket) try: @@ -654,6 +697,8 @@ def run_launch(args: argparse.Namespace) -> int: child: subprocess.Popen[bytes] | None = None display: int | None = None try: + if not owner.alive(): + return 0 hopper_environment = dict(os.environ) for name in ("WAYLAND_DISPLAY", "WAYLAND_SOCKET"): hopper_environment.pop(name, None) @@ -666,7 +711,10 @@ def run_launch(args: argparse.Namespace) -> int: "XDG_SESSION_TYPE": "x11", } ) - child = subprocess.Popen(command, env=hopper_environment) + # Children must not consume or retain REA's lifetime pipe. + child = subprocess.Popen( + command, env=hopper_environment, stdin=subprocess.DEVNULL + ) leader = os.getpid() os.environ["XAUTHORITY"] = str(authority) @@ -702,10 +750,12 @@ def run_launch(args: argparse.Namespace) -> int: observed: list[tuple[int, int, int, int, int]] = [] dialog: tuple[int, int, int, int, int] | None = None while time.monotonic() < deadline: + if not owner.alive(): + return 0 if socket.exists(): x11.XCloseDisplay(display) display = None - return child.wait() + return wait_for_hopper(child, owner) if not hopper_is_owned(leader, hopper): if child.poll() is None: time.sleep(0.1) @@ -749,7 +799,7 @@ def run_launch(args: argparse.Namespace) -> int: x11.XFlush(display) x11.XCloseDisplay(display) display = None - return child.wait() + return wait_for_hopper(child, owner) except AdapterFailure as error: raise error.with_stderr(capture) finally: diff --git a/scripts/lib/catalog-builders.mjs b/scripts/lib/catalog-builders.mjs index 1658c08fa..32ec51ee3 100644 --- a/scripts/lib/catalog-builders.mjs +++ b/scripts/lib/catalog-builders.mjs @@ -52,6 +52,11 @@ export const toolFamilyCatalog = (sources) => { surface: "android-provider", contracts: sources.androidContracts.ANDROID_TOOL_CONTRACTS, }, + { + id: "pcap", + surface: "pcap-provider", + contracts: sources.pcapContracts.PCAP_TOOL_CONTRACTS, + }, { id: "flutter", surface: "flutter-provider", @@ -251,6 +256,10 @@ export const providerCatalog = (sources) => { identity: sources.androidProvider.JADX_PROVIDER_IDENTITY, contracts: sources.androidContracts.ANDROID_TOOL_CONTRACTS, }, + { + identity: sources.pcapProvider.PCAP_PROVIDER_IDENTITY, + contracts: sources.pcapContracts.PCAP_TOOL_CONTRACTS, + }, { identity: sources.flutterProvider.FLUTTER_PROVIDER_IDENTITY, contracts: sources.flutterContracts.FLUTTER_TOOL_CONTRACTS, @@ -272,6 +281,11 @@ export const providerCatalog = (sources) => { contracts: sources.webNetworkCaptureContracts.WEB_NETWORK_CAPTURE_TOOL_CONTRACTS, }, + { + identity: sources.webNetworkCaptureProvider.SAZ_CAPTURE_PROVIDER_IDENTITY, + contracts: + sources.webNetworkCaptureContracts.WEB_NETWORK_CAPTURE_TOOL_CONTRACTS, + }, { identity: sources.webNetworkCaptureProvider.MITMPROXY_CAPTURE_PROVIDER_IDENTITY, diff --git a/scripts/lib/catalog-core.mjs b/scripts/lib/catalog-core.mjs index 5a3b0e909..f5488a9e6 100644 --- a/scripts/lib/catalog-core.mjs +++ b/scripts/lib/catalog-core.mjs @@ -68,8 +68,8 @@ const SOURCE_PATHS = { flutterProvider: "dist/flutter/FlutterBuildProvider.js", androidProvider: "dist/android/JadxRelease.js", apktoolContracts: "dist/contracts/apktool/apktoolToolContracts.js", - flutterContracts: "dist/contracts/flutter/flutterToolContracts.js", - flutterProvider: "dist/flutter/FlutterBuildProvider.js", + pcapContracts: "dist/contracts/pcap/pcapToolContracts.js", + pcapProvider: "dist/pcap/PcapProvider.js", apktoolProvider: "dist/apktool/ApktoolProvider.js", jebContracts: "dist/contracts/jeb/jebToolContracts.js", jebProvider: "dist/jeb/JebProvider.js", diff --git a/scripts/lib/clean-linux-hopper-runtime.d.mts b/scripts/lib/clean-linux-hopper-runtime.d.mts new file mode 100644 index 000000000..dd1010aa1 --- /dev/null +++ b/scripts/lib/clean-linux-hopper-runtime.d.mts @@ -0,0 +1,3 @@ +export function assertCleanLinuxHopperRuntime( + launcherPaths?: readonly string[], +): Promise; diff --git a/scripts/lib/clean-linux-hopper-runtime.mjs b/scripts/lib/clean-linux-hopper-runtime.mjs new file mode 100644 index 000000000..27a306fce --- /dev/null +++ b/scripts/lib/clean-linux-hopper-runtime.mjs @@ -0,0 +1,64 @@ +import { execFile } from "node:child_process"; +import { promisify } from "node:util"; +import { readdir, stat } from "node:fs/promises"; + +const execFileAsync = promisify(execFile); + +/** + * Observe leftover demo processes on a dedicated clean Linux runner, including + * groups reparented after their launcher exits. This is not ownership proof and + * never authorizes signaling; unrelated runtime processes also block this lane. + */ +export const assertCleanLinuxHopperRuntime = async ( + launcherPaths = [ + "/opt/hopper/bin/Hopper", + ...(process.env.HOPPER_LAUNCHER_PATH === undefined + ? [] + : [process.env.HOPPER_LAUNCHER_PATH]), + ], +) => { + const { stdout } = await execFileAsync("ps", ["-ax", "-o", "command="]); + if (/\/opt\/hopper\/bin\/Hopper|\bXvfb\b|hopper-demo-x11\.py/u.test(stdout)) + throw new Error("Clean Linux runner retained a Hopper demo process"); + const launchers = []; + for (const path of launcherPaths) { + try { + launchers.push(await stat(path, { bigint: true })); + } catch (error) { + if (error?.code !== "ENOENT") throw error; + } + } + if (launchers.length === 0) return; + // /proc exposes the executed file even when argv[0] names a removed symlink. + // Compare file identity, not a display path or a process name. + let inspectionError; + for (const entry of await readdir("/proc", { withFileTypes: true })) { + if (!entry.isDirectory() || !/^\d+$/u.test(entry.name)) continue; + let executable; + try { + executable = await stat(`/proc/${entry.name}/exe`, { bigint: true }); + } catch (error) { + if (error?.code === "ENOENT" || error?.code === "ESRCH") continue; + // Other users' executables may be unreadable. The setup lane launches + // providers as the caller; unreadable caller-owned processes fail closed. + if (error?.code === "EACCES") { + const owner = await stat(`/proc/${entry.name}`).catch((cause) => { + if (cause?.code === "ENOENT") return undefined; + throw cause; + }); + if (owner === undefined || owner.uid !== process.getuid()) continue; + } + // Finish the inventory so an unrelated restricted process cannot mask a + // positively identified leak. Unknown caller processes still fail closed. + inspectionError ??= error; + continue; + } + if ( + launchers.some( + ({ dev, ino }) => dev === executable.dev && ino === executable.ino, + ) + ) + throw new Error("Clean Linux runner retained a Hopper demo process"); + } + if (inspectionError !== undefined) throw inspectionError; +}; diff --git a/scripts/lib/nativeaot-build.d.mts b/scripts/lib/nativeaot-build.d.mts new file mode 100644 index 000000000..418111852 --- /dev/null +++ b/scripts/lib/nativeaot-build.d.mts @@ -0,0 +1,25 @@ +export function supportsNativeAotFixtureHost( + platform: string, + architecture: string, +): boolean; + +export function buildNativeAotFixture( + run: (command: string, args: string[]) => unknown, + options: { + dotnet: string; + project: string; + runtime: string; + output: string; + }, +): Promise; + +export function nativeAotCommandError( + command: string, + operation: string, + result: { + error?: { message: string }; + status: number | null; + stdout?: string | null; + stderr?: string | null; + }, +): Error; diff --git a/scripts/lib/nativeaot-build.mjs b/scripts/lib/nativeaot-build.mjs new file mode 100644 index 000000000..3b49ce839 --- /dev/null +++ b/scripts/lib/nativeaot-build.mjs @@ -0,0 +1,60 @@ +import { join } from "node:path"; +import { setTimeout as delay } from "node:timers/promises"; + +/** NativeAOT fixtures use native toolchains, not cross-compilation. */ +export function supportsNativeAotFixtureHost(platform, architecture) { + return architecture === "x64" && ["linux", "win32"].includes(platform); +} + +/** Keep network recovery separate from compilation and preserve restore failures. */ +export async function buildNativeAotFixture(run, options) { + const { dotnet, project, runtime, output } = options; + const common = [ + project, + "-r", + runtime, + "--maxcpucount:1", + "-p:Configuration=Release", + `-p:BaseIntermediateOutputPath=${join(output, "obj")}/`, + `-p:BaseOutputPath=${join(output, "bin")}/`, + `-p:NativeAotMapPath=${join(output, "NativeAotFixture.map")}`, + ]; + for (let attempt = 1; attempt <= 2; attempt++) { + console.error(`NativeAOT dependency restore: attempt ${attempt}/2`); + try { + run(dotnet, ["restore", ...common, "--verbosity", "normal"]); + break; + } catch (cause) { + if (attempt === 2) + throw new Error( + "NativeAOT dependency restore failed after two attempts", + { + cause, + }, + ); + // Child diagnostics can contain authenticated feed URLs; keep retry logs static. + console.error( + "NativeAOT dependency restore failed; retrying in 1 second", + ); + await delay(1_000); + } + } + console.error("NativeAOT compilation (dependencies already restored)"); + run(dotnet, [ + "publish", + ...common, + "--no-restore", + "-o", + join(output, "symbols"), + ]); +} + +/** Sanitize child diagnostics before any retry, cause chain, or uncaught output. */ +export function nativeAotCommandError(command, operation, result) { + const diagnostic = `NativeAOT fixture lane requires/action failed ${command} ${operation}: ${result.error?.message ?? `exit ${result.status}`}\n${result.stdout ?? ""}${result.stderr ?? ""}`; + // Only URL authority userinfo is authentication; preserve host, path, query, + // and unrelated diagnostic values. Never retain the raw result as a cause. + return new Error( + diagnostic.replace(/\b(https?:\/\/)[^\\\s/?#]*@/giu, "$1[redacted]@"), + ); +} diff --git a/scripts/lib/real-ghidra-file-offsets.mjs b/scripts/lib/real-ghidra-file-offsets.mjs new file mode 100644 index 000000000..ea881dd04 --- /dev/null +++ b/scripts/lib/real-ghidra-file-offsets.mjs @@ -0,0 +1,264 @@ +import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; +import { + mkdir, + mkdtemp, + readFile, + readdir, + rm, + writeFile, +} from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { promisify } from "node:util"; +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; +import { parseEvidence } from "../../dist/domain/evidence.js"; +import { + requireMcpOperationResult, + requireMcpToolError, + mcpTextValue, +} from "./mcp-verifier-results.mjs"; + +/** Exercise file coordinates through public CLI/MCP using the source-owned PE fixture. */ +export async function verifyGhidraFileOffsets( + targetPath, + entrypoint, + procedure, +) { + const original = await readFile(targetPath); + const workspace = await mkdtemp(join(tmpdir(), "rea-file-offsets-")); + const runtime = join(workspace, "runtime"); + await mkdir(runtime); + const env = { + ...process.env, + TEMP: runtime, + TMP: runtime, + TMPDIR: runtime, + REA_ANALYSIS_PROVIDER: "ghidra", + REA_LOG_LEVEL: "silent", + }; + const client = new Client({ name: "rea-file-offsets", version: "1" }); + const transport = new StdioClientTransport({ + command: process.execPath, + args: [entrypoint, "mcp"], + env, + stderr: "pipe", + }); + let connected = false; + let complete = false; + let primaryFailure; + const call = async (name, arguments_ = {}) => { + const result = await client.callTool( + { name, arguments: arguments_ }, + { timeout: 240_000 }, + ); + const projected = requireMcpOperationResult(result, name); + return ["open_binary", "binary_session", "close_binary"].includes(name) + ? projected + : (result.structuredContent ?? JSON.parse(mcpTextValue(result))); + }; + try { + await client.connect(transport); + connected = true; + await call("open_binary", { path: targetPath, provider_id: "ghidra" }); + const session = await call("binary_session"); + const mapping = parseEvidence( + await call("address_to_file_offset", { address: procedure }), + ); + const offset = mapping.normalized_result.file_offset; + const coordinate = `0x${offset.toString(16)}`; + const expected = parseEvidence( + await call("procedure_pseudo_code", { procedure }), + ); + const explicit = parseEvidence( + await call("procedure_pseudo_code", { + procedure: `file-offset:${coordinate}`, + }), + ); + const automatic = parseEvidence( + await call("procedure_pseudo_code", { procedure: coordinate }), + ); + for (const actual of [explicit, automatic]) { + assert.equal(actual.normalized_result, expected.normalized_result); + assert.equal(actual.raw_result.selection.file_offset, offset); + assert.equal(actual.raw_result.selection.mapped_address, procedure); + assert.ok( + actual.locations.some( + (location) => + location.kind === "file-offset" && location.offset === offset, + ), + ); + } + const invalid = await client.callTool({ + name: "procedure_pseudo_code", + arguments: { procedure: "file-offset:0x20000000000000" }, + }); + assert.equal(requireMcpToolError(invalid).code, "invalid_request"); + const unmapped = await client.callTool({ + name: "procedure_pseudo_code", + arguments: { procedure: "file-offset:0x100000" }, + }); + assert.ok( + JSON.stringify(requireMcpToolError(unmapped)).includes( + "no loaded source mapping", + ), + ); + assert.equal( + (await call("binary_session")).analysis_run.run_id, + session.analysis_run.run_id, + ); + const image = parseEvidence(await call("inspect_native_load_image")); + const headerMapping = image.normalized_result.observations.mappings.find( + (item) => item.initialized && item.file_offset === 0, + ); + assert.ok( + headerMapping, + "Fixture header must have an observed source mapping", + ); + const headerOffset = parseEvidence( + await call("address_to_file_offset", { address: headerMapping.start }), + ); + assert.equal(headerOffset.normalized_result.file_offset, 0); + for (const selector of ["file-offset:0x0", "0x0"]) { + const missing = requireMcpToolError( + await client.callTool({ + name: "procedure_pseudo_code", + arguments: { procedure: selector }, + }), + ); + assertMissingMappedProcedure(missing, headerMapping.start); + } + assert.equal( + (await call("binary_session")).analysis_run.run_id, + session.analysis_run.run_id, + ); + await call("close_binary"); + const cli = JSON.parse( + ( + await promisify(execFile)( + process.execPath, + [ + entrypoint, + "decompile", + targetPath, + `--file-offset=${coordinate}`, + "--provider", + "ghidra", + "--json", + ], + { env, timeout: 240_000, maxBuffer: 16 * 1024 * 1024 }, + ) + ).stdout, + ); + assert.equal(cli.normalized_result, explicit.normalized_result); + assert.deepEqual(cli.locations, explicit.locations); + const missingCli = await promisify(execFile)( + process.execPath, + [ + entrypoint, + "decompile", + targetPath, + "--file-offset=0x0", + "--provider", + "ghidra", + "--json", + ], + { env, timeout: 240_000, maxBuffer: 16 * 1024 * 1024 }, + ).then( + () => { + throw new Error( + "Mapped header bytes must not decompile as a procedure", + ); + }, + (cause) => JSON.parse(cause.stdout), + ); + assertMissingMappedProcedure(missingCli, headerMapping.start); + const alias = Buffer.from(original); + const pe = alias.readUInt32LE(0x3c); + if (alias.readUInt16LE(pe + 6) >= 2) { + const secondSection = pe + 24 + alias.readUInt16LE(pe + 20) + 40; + // Both sections now carry the same original bytes at distinct virtual addresses. + alias.writeUInt32LE(0x200, secondSection + 20); + const ambiguousPath = join(workspace, "ambiguous.exe"); + await writeFile(ambiguousPath, alias); + await call("open_binary", { path: ambiguousPath, provider_id: "ghidra" }); + const ambiguous = await client.callTool( + { + name: "procedure_pseudo_code", + arguments: { procedure: `file-offset:${coordinate}` }, + }, + { timeout: 240_000 }, + ); + assert.ok( + JSON.stringify(requireMcpToolError(ambiguous)).includes( + "multiple loaded mappings", + ), + ); + await call("close_binary"); + } + assert.deepEqual(await readFile(targetPath), original); + await client.close(); + connected = false; + assert.deepEqual(await readdir(runtime), []); + complete = true; + return { + cli_mcp_parity: true, + explicit_and_numeric_offsets: true, + invalid_and_unmapped_offsets: true, + mapped_offset_without_procedure: true, + ambiguous_mappings: + alias.readUInt16LE(pe + 6) >= 2 + ? "verified" + : "unavailable-single-section", + source_unchanged: true, + cleanup: "complete", + }; + } catch (cause) { + primaryFailure = cause; + throw cause; + } finally { + const cleanupFailures = []; + if (connected) { + try { + await call("close_binary"); + } catch (cause) { + cleanupFailures.push(cause); + } + } + try { + await client.close(); + } catch (cause) { + cleanupFailures.push(cause); + } + if (cleanupFailures.length > 0) { + process.stderr.write( + `Retained file-offset verifier workspace: ${workspace}\n`, + ); + throw new AggregateError( + primaryFailure === undefined + ? cleanupFailures + : [primaryFailure, ...cleanupFailures], + "File-offset verifier cleanup failed", + ); + } + if (complete) await rm(workspace, { recursive: true, force: true }); + else + process.stderr.write( + `Retained file-offset verifier workspace: ${workspace}\n`, + ); + } +} + +function assertMissingMappedProcedure(error, mappedAddress) { + assert.equal(error.code, "invalid_request"); + const message = error.details?.issues?.[0]?.message; + assert.equal(typeof message, "string"); + assert.ok( + message.includes("File offset 0x0 maps to analysis address"), + message, + ); + assert.ok(message.includes(mappedAddress), message); + assert.ok(message.includes("no procedure starts at or contains"), message); + assert.ok(!message.includes("--file-offset"), message); +} diff --git a/scripts/lib/real-hopper-owner-exit.mjs b/scripts/lib/real-hopper-owner-exit.mjs new file mode 100644 index 000000000..300b35ada --- /dev/null +++ b/scripts/lib/real-hopper-owner-exit.mjs @@ -0,0 +1,130 @@ +import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; +import { setTimeout as delay } from "node:timers/promises"; +import { promisify } from "node:util"; + +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; + +import { verifyNoTokenOwnedProcesses } from "../../dist/process/ProcessOwnership.js"; +import { + observeProcessStartIdentity, + signalProcessWithStartIdentity, +} from "../../dist/process/ProcessOwnershipObservation.js"; +import { startUnrelatedHopperSentinel } from "./unrelated-hopper-sentinel.mjs"; +import { + requireMcpEvidenceResult, + requireMcpLifecycleResult, +} from "./mcp-verifier-results.mjs"; + +const execFileAsync = promisify(execFile); + +/** Prove actual MCP owner exit releases the demo singleton for subsequent CLI/MCP sessions. */ +export async function verifyLinuxHopperOwnerExit({ + primary, + secondary, + serverCommand, + serverArgs, + environment, +}) { + const sentinel = await startUnrelatedHopperSentinel(); + const outcomes = []; + try { + for (const mode of ["graceful", "SIGKILL"]) { + const transport = new StdioClientTransport({ + command: serverCommand, + args: serverArgs, + env: environment, + stderr: "pipe", + }); + // Drain launcher diagnostics even on the deliberately interrupted owner. + transport.stderr?.resume(); + const client = new Client({ name: "hopper-owner-exit", version: "1" }); + const options = { timeout: 180_000 }; + try { + await client.connect(transport); + const ownerPid = transport.pid; + assert.ok(ownerPid !== null); + const owner = await observeProcessStartIdentity(ownerPid); + assert.equal(owner?.state, "readable"); + requireMcpLifecycleResult( + await client.callTool( + { + name: "open_binary", + arguments: { path: primary }, + }, + options, + ), + "open_binary", + ); + const procedures = requireMcpEvidenceResult( + await client.callTool( + { name: "list_procedures", arguments: {} }, + options, + ), + "list_procedures", + ); + assert.ok(procedures.length > 0); + const status = requireMcpLifecycleResult( + await client.callTool( + { name: "binary_session", arguments: {} }, + options, + ), + "binary_session", + ); + const runId = status.analysis_run?.run_id; + assert.equal(typeof runId, "string"); + assert.equal(status.analysis_provider_binding?.provider.id, "hopper"); + assert.equal((await verifyNoTokenOwnedProcesses(runId)).cleaned, false); + if (mode === "graceful") await client.close(); + else { + assert.equal( + await signalProcessWithStartIdentity( + ownerPid, + owner.identity, + "SIGKILL", + ), + "signaled", + ); + } + const deadline = Date.now() + 10_000; + let cleanup; + do { + cleanup = await verifyNoTokenOwnedProcesses(runId); + if (cleanup.cleaned) break; + await delay(100); + } while (Date.now() < deadline); + assert.equal(cleanup.cleaned, true, cleanup.reason); + // The SIGKILL case must recover the stale lease for both target identities. + for (const target of [primary, secondary]) { + const result = await execFileAsync( + process.execPath, + [ + "scripts/rea.mjs", + "inspect", + target, + "--provider", + "hopper", + "--format", + "json", + ], + { env: environment, timeout: 180_000, maxBuffer: 16 * 1024 * 1024 }, + ); + assert.ok(JSON.parse(result.stdout).normalized_result); + } + outcomes.push({ + mode, + ownedProcessesStopped: true, + sameTargetReopened: true, + differentTargetReopened: true, + }); + } finally { + await client.close(); + await transport.close(); + } + } + } finally { + assert.equal(await sentinel.verifyAndClose(), true); + } + return { outcomes, unrelatedHopperSurvived: true }; +} diff --git a/scripts/lib/real-hopper-search.d.mts b/scripts/lib/real-hopper-search.d.mts new file mode 100644 index 000000000..e64031652 --- /dev/null +++ b/scripts/lib/real-hopper-search.d.mts @@ -0,0 +1,30 @@ +type VerifierCall = ( + name: string, + arguments_?: Record, +) => Promise; + +interface StringExpectation { + readonly value: string; + readonly encoding: string; + readonly symbol?: string; + readonly recognitionOptional?: boolean; +} + +/** Verify source bytes, observed decoding, address filters and literal searches. */ +export function verifyHopperStringObjects( + call: VerifierCall, + expectations: readonly StringExpectation[], + inventory?: readonly z.output[] | null, +): Promise<{ + readonly sourceBytesVerified: true; + readonly recognition: readonly { + readonly value: string; + readonly address: string; + readonly state: "observed" | "not_observed"; + readonly decodedObject: "verified" | "unverified"; + }[]; + readonly displayEscapesExcludedFromMatching: true; +}>; +import type { z } from "zod"; + +import type { analysisStringSchema } from "../../src/domain/hopperValues.js"; diff --git a/scripts/lib/real-hopper-search.mjs b/scripts/lib/real-hopper-search.mjs index 0d796f3d2..3456bc6b2 100644 --- a/scripts/lib/real-hopper-search.mjs +++ b/scripts/lib/real-hopper-search.mjs @@ -1,13 +1,16 @@ import assert from "node:assert/strict"; import { mcpTextValue } from "./mcp-verifier-results.mjs"; +const fixtureSymbolPrefix = process.platform === "darwin" ? "_" : ""; + /** Exercise literal/regex search, Unicode identities and cache invalidation in Hopper. */ export async function verifyHopperSearch(call, invalid, procedure) { const address = procedure.address; const original = await call("address_name", { address }); + let stringCoverage; try { await verifySymbolNames(call, invalid, address); - await verifySearchModes(call, address); + stringCoverage = await verifySearchModes(call, address); } finally { await call("set_address_name", { address, name: original }); } @@ -26,7 +29,7 @@ export async function verifyHopperSearch(call, invalid, procedure) { symbolUtf16LimitValidatedBeforeMutation: true, regexAndCaseModes: true, annotationCacheInvalidation: true, - escapedUtf8AndByteStrings: true, + stringCoverage, }; } @@ -103,11 +106,26 @@ async function verifySearchModes(call, address) { [{ address, value: "REA_Search_Upper" }], ); const strings = await call("list_strings"); - const long = "REA_LONG_LITERAL_" + "x".repeat(4096) + "needle"; - const longItem = strings.find((item) => - item.value.startsWith("REA_LONG_LITERAL_"), + const linux = process.platform === "linux"; + const fullLiteral = "REA_LONG_LITERAL_" + "x".repeat(4096) + "needle"; + // Recognition is a provider/loader capability, not an adapter guarantee. + // Always retain the original size in raw-byte coverage; Linux additionally + // requires an extent observed to produce native fragmented string objects. + const fullBytes = Buffer.from(fullLiteral + "\0"); + const raw = await call("read_bytes", { + address: `${fixtureSymbolPrefix}rea_long_literal`, + length: fullBytes.length, + }); + assert.equal(raw.complete, true); + assert.equal(raw.bytes_hex, fullBytes.toString("hex")); + const long = linux + ? "REA_FRAGMENTED_LITERAL_" + "x".repeat(512) + "fragment_tail" + : fullLiteral; + const longItem = strings.find( + (item) => long.startsWith(item.value) && item.value.startsWith("REA_"), ); assert.ok(longItem, "fixture omitted its real long literal"); + if (!linux) assert.equal(longItem.address, raw.address); assert.ok(long.startsWith(longItem.value)); assert.ok(longItem.provider_value.endsWith("…")); assert.equal(longItem.string.termination, "missing"); @@ -158,7 +176,7 @@ async function verifySearchModes(call, address) { } assert.deepEqual( await call("search_strings", { - pattern: "needle", + pattern: linux ? "fragment_tail" : "needle", mode: "literal", case_sensitive: true, }), @@ -176,36 +194,122 @@ async function verifySearchModes(call, address) { }), expected, ); - await verifyHopperStringObjects(call, [ - { value: "REA_UTF8_é_😀", encoding: "utf-8" }, - { value: 'REA_ESCAPED_"\\line\nend\t\r', encoding: "utf-8" }, - { value: "REA_LITERAL_BACKSLASH_\\n", encoding: "utf-8" }, - { value: "REA_LITERAL_…", encoding: "utf-8" }, - { value: "REA_LATIN1_ÿ", encoding: "latin-1" }, - ]); + const objects = await verifyHopperStringObjects( + call, + [ + { + value: "REA_UTF8_é_😀", + encoding: "utf-8", + symbol: `${fixtureSymbolPrefix}rea_utf8_literal`, + recognitionOptional: linux, + }, + { value: 'REA_ESCAPED_"\\line\nend\t\r', encoding: "utf-8" }, + { value: "REA_LITERAL_BACKSLASH_\\n", encoding: "utf-8" }, + { + value: "REA_LITERAL_…", + encoding: "utf-8", + symbol: `${fixtureSymbolPrefix}rea_ellipsis_literal`, + recognitionOptional: linux, + }, + { + value: "REA_LATIN1_ÿ", + encoding: "latin-1", + symbol: `${fixtureSymbolPrefix}rea_latin1_literal`, + recognitionOptional: linux, + }, + ], + strings, + ); + return { + fullLiteralSourceBytes: fullBytes.length, + fragmentedLiteralSourceBytes: Buffer.byteLength(long), + fullLiteralRecognition: { + address: raw.address, + state: strings.some((item) => item.address === raw.address) + ? "observed" + : "not_observed", + // Linux validates the original through raw bytes; its required decoded + // fragment/dossier checks exercise the separate supported-size literal. + decodedObject: linux ? "unverified" : "verified", + }, + ...objects, + }; } /** Compare native string identities and values with the source fixture's bytes. */ -export async function verifyHopperStringObjects(call, expectations) { - const strings = await call("list_strings"); - for (const { value, encoding } of expectations) { - const item = strings.find((candidate) => candidate.value === value); - assert.ok( - item, - `Hopper omitted the decoded string ${JSON.stringify(value)}`, - ); - assert.equal(item.string.encoding, encoding); - assert.equal(item.string.encoding_status, "inferred"); - assert.equal(item.string.termination, "present_or_not_required"); +export async function verifyHopperStringObjects( + call, + expectations, + inventory = null, +) { + // Reuse only the caller's inventory for this unchanged document, never live + // state from an earlier session. Address-filter and search checks remain real. + const strings = inventory ?? (await call("list_strings")); + const recognition = []; + for (const { + value, + encoding, + symbol, + recognitionOptional = false, + } of expectations) { const expectedBytes = Buffer.from( value + "\0", encoding.replaceAll("-", ""), ); - assert.equal(item.string.byte_length, expectedBytes.length); - const bytes = await call("read_bytes", { + let sourceBytes; + if (symbol !== undefined) { + const raw = await call("read_bytes", { + address: symbol, + length: expectedBytes.length, + }); + sourceBytes = raw; + assert.equal(raw.complete, true); + assert.equal(raw.bytes_hex, expectedBytes.toString("hex")); + } + const item = strings.find((candidate) => + sourceBytes === undefined + ? candidate.value === value + : candidate.address === sourceBytes.address, + ); + if (item === undefined && recognitionOptional) { + assert.ok( + symbol, + "optional recognition requires independent source-byte coverage", + ); + recognition.push({ + value, + address: sourceBytes.address, + state: "not_observed", + decodedObject: "unverified", + }); + continue; + } + assert.ok( + item, + `Hopper omitted the decoded string ${JSON.stringify(value)}`, + ); + assert.equal( + item.value, + value, + "native string decoding changed the source value", + ); + recognition.push({ + value, address: item.address, - length: expectedBytes.length, + state: "observed", + decodedObject: "verified", }); + assert.equal(item.string.encoding, encoding); + assert.equal(item.string.encoding_status, "inferred"); + assert.equal(item.string.termination, "present_or_not_required"); + assert.equal(item.string.byte_length, expectedBytes.length); + const bytes = + sourceBytes ?? + (await call("read_bytes", { + address: item.address, + length: expectedBytes.length, + })); + assert.equal(bytes.complete, true); assert.equal(bytes.bytes_hex, expectedBytes.toString("hex")); assert.deepEqual(await call("list_strings", { address: item.address }), [ item, @@ -225,7 +329,7 @@ export async function verifyHopperStringObjects(call, expectations) { ); return { sourceBytesVerified: true, - inferredEncodingReported: true, + recognition, displayEscapesExcludedFromMatching: true, }; } diff --git a/scripts/rea.mjs b/scripts/rea.mjs index 78ffbdd21..75ee552c5 100755 --- a/scripts/rea.mjs +++ b/scripts/rea.mjs @@ -16,6 +16,12 @@ const isMcpMode = const isMcpDoctorMode = args[0] === "mcp" && args[1] === "doctor"; const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +// Windows home lookup throws for an empty USERPROFILE. Dependencies resolve +// home during import, before REA's own resolver can apply its account fallback. +if (process.platform === "win32" && process.env.USERPROFILE === "") { + delete process.env.USERPROFILE; +} + // Playwright's registry assumes one of its three desktop host platforms when // it chooses the browser cache directory. Termux reports `android`, although // its Node runtime and filesystem are POSIX-compatible. Keep the cache path diff --git a/scripts/test-website.py b/scripts/test-website.py index fed68227a..5c1aef876 100644 --- a/scripts/test-website.py +++ b/scripts/test-website.py @@ -401,7 +401,7 @@ class WebsiteTranslationChecks(unittest.TestCase): server.shutdown() worker.join() - def test_every_reading_page_offers_light_and_dark_theme_colors(self): + def test_every_reading_page_loads_theme_before_styles(self): site = ROOT / "website/_site" english_pages = reading_pages(ROOT / "website/public") self.assertTrue(english_pages) @@ -412,10 +412,20 @@ class WebsiteTranslationChecks(unittest.TestCase): for path in {original, site / relative if code == "en" else site / code / relative}: with self.subTest(language=code, page=str(path.relative_to(ROOT))): doc = Document(path.read_text()) - media = sorted(node.attrs.get("media") for node in doc.nodes if node.tag == "meta" and node.attrs.get("name") == "theme-color") - self.assertEqual(media, ["(prefers-color-scheme: dark)", "(prefers-color-scheme: light)"]) - styles = (ROOT / "website/public/assets/styles.css").read_text() - self.assertTrue("@media (prefers-color-scheme: dark)" in styles, "styles.css has no dark color scheme block") + colors = [node for node in doc.nodes if node.tag == "meta" and node.attrs.get("name") == "theme-color"] + self.assertEqual(len(colors), 1) + self.assertEqual(colors[0].attrs.get("content"), "#ffffff") + self.assertNotIn("media", colors[0].attrs) + theme = [node for node in doc.nodes if node.tag == "script" and (node.attrs.get("src") or "").endswith("/assets/theme.js")] + self.assertEqual(len(theme), 1) + for deferred in ("defer", "async", "type"): + self.assertNotIn(deferred, theme[0].attrs) + stylesheet = next(node for node in doc.nodes if node.tag == "link" and node.attrs.get("rel") == "stylesheet") + self.assertLess(theme[0].start, stylesheet.start) + toggle = [node for node in doc.nodes if "data-theme-toggle" in node.attrs] + self.assertEqual(len(toggle), 1) + self.assertEqual(toggle[0].tag, "button") + self.assertIn("hidden", toggle[0].attrs) if __name__ == "__main__": diff --git a/scripts/verify-documentation-routes.mjs b/scripts/verify-documentation-routes.mjs index 25e9203e8..a3d3dfc13 100644 --- a/scripts/verify-documentation-routes.mjs +++ b/scripts/verify-documentation-routes.mjs @@ -1,5 +1,5 @@ import assert from "node:assert/strict"; -import { readFile, stat } from "node:fs/promises"; +import { readFile, readdir, stat } from "node:fs/promises"; import { basename, resolve, sep } from "node:path"; import { fileURLToPath } from "node:url"; @@ -14,14 +14,14 @@ ghidra-riscv go-binaries harmony-analysis ida-provider installation javascript-application-graph javascript-application-workflows javascript-artifact-reconstruction javascript-recovery javascript-runtime-observation javascript-runtime-reconciliation jeb-analysis managed-code-analysis mcp-contracts mcp-prompts migration-6.2 -native-investigation packet-captures process-capture raw-binary reconstruction-obligation-ledgers +native-investigation packet-captures pcap-analysis process-capture raw-binary reconstruction-obligation-ledgers reconstruction-readiness recorded-crashes releasing roadmap signal-recordings sqlite-databases testing tool-design wasm-artifacts web-network-captures web-runtime web-source-location website-module-trace website-script-export windows-ghidra-p0 ` .trim() .split(/\s+/u); -assert.equal(routes.length, 56); +assert.equal(routes.length, 57); assert.equal(new Set(routes).size, routes.length); const documentation = resolve( @@ -32,28 +32,36 @@ const origin = "https://documentation.invalid"; const checked = new Set(); let internalTargets = 0; let sourceLinks = 0; +// Legacy public routes remain an independent baseline; all generated pages also +// participate so newly authored directories/specifications cannot escape checks. for (const route of routes) { const html = await readFile(resolve(output, route + ".html"), "utf8"); - const edit = html.match( - /href="https:\/\/github\.com\/morluto\/rea\/edit\/main\/docs\/([^"]+)"/u, - ); - assert.ok(edit, route + ": missing physical-source edit link"); - const source = resolve(documentation, decodeURIComponent(edit[1])); - assert.ok( - source.startsWith(documentation + sep), - route + ": source escaped documentation root", - ); - assert.equal(basename(source), route + ".md"); - assert.ok( - (await stat(source)).isFile(), - route + ": edit link source is missing", - ); - sourceLinks++; + const edit = physicalEditSource(html, route); + assert.equal(basename(edit), route + ".md"); +} +const htmlPages = []; +const directories = [output]; +while (directories.length > 0) { + const directory = directories.pop(); + for (const entry of await readdir(directory, { withFileTypes: true })) { + const path = resolve(directory, entry.name); + if (entry.isDirectory()) directories.push(path); + else if (entry.isFile() && entry.name.endsWith(".html")) htmlPages.push(path); + } +} +for (const page of htmlPages.sort()) { + const route = page.slice(output.length + 1).split(sep).join("/"); + const html = await readFile(page, "utf8"); + if (route !== "404.html") { + const source = physicalEditSource(html, route); + assert.ok((await stat(source)).isFile(), route + ": edit link source is missing"); + sourceLinks++; + } for (const match of html.matchAll( /<(?:a|img)\b[^>]*\b(?:href|src)="([^"]+)"/gu, )) { const destination = match[1].replaceAll("&", "&"); - const url = new URL(destination, origin + "/rea/" + route + ".html"); + const url = new URL(destination, origin + "/rea/" + route); if (url.origin !== origin || !url.pathname.startsWith("/rea/")) continue; const key = url.pathname + url.hash; if (checked.has(key)) continue; @@ -81,10 +89,20 @@ for (const route of routes) { internalTargets++; } } +function physicalEditSource(html, route) { + const edit = html.match( + /href="https:\/\/github\.com\/morluto\/rea\/edit\/main\/docs\/([^"]+)"/u, + ); + assert.ok(edit, route + ": missing physical-source edit link"); + const source = resolve(documentation, decodeURIComponent(edit[1])); + assert.ok(source.startsWith(documentation + sep), route + ": source escaped documentation root"); + return source; +} console.log( JSON.stringify({ ok: true, published_routes: routes.length, + html_pages: htmlPages.length, physical_edit_links: sourceLinks, distinct_internal_targets_and_anchors: internalTargets, scope: diff --git a/scripts/verify-linux-setup-e2e.mjs b/scripts/verify-linux-setup-e2e.mjs index 8b57fbacc..e08e8b160 100644 --- a/scripts/verify-linux-setup-e2e.mjs +++ b/scripts/verify-linux-setup-e2e.mjs @@ -12,6 +12,7 @@ import { tmpdir } from "node:os"; import { promisify } from "node:util"; import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs"; +import { assertCleanLinuxHopperRuntime } from "./lib/clean-linux-hopper-runtime.mjs"; const execFileAsync = promisify(execFile); const verifierRun = createVerifierRun(); @@ -19,12 +20,12 @@ const command = process.env.REA_VERIFY_SERVER_COMMAND; if (process.platform !== "linux" || process.getuid?.() !== 0) throw new Error("Linux setup verification requires a root Linux runner"); if (!command) throw new Error("REA_VERIFY_SERVER_COMMAND is required"); +await assertCleanLinuxHopperRuntime(); try { await access("/opt/hopper/bin/Hopper"); throw new Error("Linux setup verification requires a clean runner"); } catch (error) { - if (error instanceof Error && error.message.includes("clean runner")) - throw error; + if (error?.code !== "ENOENT") throw error; } const runJson = async (args) => { @@ -35,14 +36,25 @@ const runJson = async (args) => { return JSON.parse(stdout); }; -const plan = await runJson(["setup", "--json"]); -if (plan.status !== "needs_confirmation") - throw new Error("setup did not produce a read-only confirmation plan"); +const plan = await runJson([ + "setup", + "--install-hopper", + "--dry-run", + "--json", +]); +if ( + plan.status !== "planned" || + !plan.plannedActions.some(({ kind }) => kind === "install_hopper") || + plan.appliedActions.length !== 0 +) + throw new Error("setup did not produce a read-only Hopper installation plan"); await access("/opt/hopper/bin/Hopper").then( () => { throw new Error("setup plan mutated the clean runner"); }, - () => undefined, + (error) => { + if (error?.code !== "ENOENT") throw error; + }, ); const installed = await runJson([ @@ -58,7 +70,7 @@ if ( throw new Error( `approved setup did not become ready: ${JSON.stringify(installed)}`, ); -const doctor = await runJson(["doctor", "--json"]); +const doctor = await runJson(["doctor", "--provider", "hopper", "--json"]); if (doctor.healthy !== true) throw new Error(`doctor is unhealthy: ${JSON.stringify(doctor)}`); @@ -67,8 +79,6 @@ await execFileAsync(command, ["analyze", "/usr/bin/true"], { timeout: 180_000, maxBuffer: 10 * 1024 * 1024, }); -process.env.HOPPER_TARGET_PATH = "/usr/bin/true"; -process.env.HOPPER_SECOND_TARGET_PATH = "/usr/bin/false"; process.env.REA_VERIFY_SERVER_ARGS_JSON = '["mcp"]'; await import("./verify-real-hopper-linux.mjs"); @@ -95,28 +105,24 @@ try { await rm(modifiedDirectory, { recursive: true, force: true }); } -const repeated = await runJson([ - "setup", - "--yes", - "--install-hopper", - "--json", -]); +const repeated = await runJson(["setup", "--yes", "--json"]); if ( repeated.status !== "ready" || - repeated.appliedActions.includes("installed_hopper") + repeated.plannedActions.length !== 0 || + repeated.appliedActions.length !== 0 ) throw new Error("a second setup was not idempotent"); -const { stdout: processes } = await execFileAsync("ps", [ - "-ax", - "-o", - "command=", -]); -if (/\/opt\/hopper\/bin\/Hopper|\bXvfb\b|hopper-demo-x11\.py/u.test(processes)) - throw new Error("Linux setup verification leaked a Hopper demo session"); +await assertCleanLinuxHopperRuntime(); +const completedVerifierRun = await completeVerifierRun(verifierRun); +if ( + completedVerifierRun.process_lineage.status !== "verified" || + completedVerifierRun.process_lineage.descendants.length !== 0 +) + throw new Error("Linux setup verification did not prove owned child cleanup"); console.log( JSON.stringify({ - verifier_run: await completeVerifierRun(verifierRun), + verifier_run: completedVerifierRun, status: "verified", setup: true, cli: true, diff --git a/scripts/verify-package.mjs b/scripts/verify-package.mjs index fff3a07c6..32bad0a62 100644 --- a/scripts/verify-package.mjs +++ b/scripts/verify-package.mjs @@ -1,6 +1,8 @@ -import { mkdtemp, rm } from "node:fs/promises"; +import { mkdir, mkdtemp, rm, unlink } from "node:fs/promises"; +import { execFile } from "node:child_process"; import { tmpdir } from "node:os"; import { join } from "node:path"; +import { promisify } from "node:util"; import { TOOL_CONTRACTS } from "../dist/contracts/toolContracts.js"; import { PRODUCT_IDENTITY } from "../dist/identity.js"; @@ -21,12 +23,19 @@ import { verifyRepositorySkill } from "./verify-repository-skill.mjs"; import { verifyManaged } from "./verify-package-managed.mjs"; import { verifyUnknownProvider } from "./verify-package-unknown-provider.mjs"; import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs"; +import { + createVerifiedPackageMetadata, + retainVerifiedPackage, + writeVerifiedPackageManifest, +} from "./ci/verified-package.mjs"; import { measureMcpStartup, profileMcpModuleLoading, } from "./lib/mcp-startup-probe.mjs"; const root = process.cwd(); +const execFileAsync = promisify(execFile); +const retentionDirectory = process.env.REA_VERIFIED_PACKAGE_DIRECTORY; const verifierRun = createVerifierRun(); const workspace = await mkdtemp(join(tmpdir(), "rea-package-")); const evidenceRoot = join(workspace, "evidence"); @@ -37,6 +46,8 @@ let mcpModuleLoading; let update; let repositorySkill; let report; +let retainedPackage; +let retentionMetadata; const runStage = async (name, action) => { const started = performance.now(); @@ -49,6 +60,27 @@ const runStage = async (name, action) => { }; try { + if (retentionDirectory !== undefined && retentionDirectory !== "") { + const sourceSha = ( + await execFileAsync("git", ["rev-parse", "HEAD"], { cwd: root }) + ).stdout.trim(); + retentionMetadata = createVerifiedPackageMetadata({ + sourceSha, + runId: process.env.GITHUB_RUN_ID, + runAttempt: process.env.GITHUB_RUN_ATTEMPT, + platform: process.platform, + architecture: process.arch, + packageVersion: PRODUCT_IDENTITY.packageVersion, + nodeVersion: process.version, + }); + await mkdir(retentionDirectory, { recursive: true }); + await unlink(join(retentionDirectory, "manifest.json")).catch((cause) => { + if ( + !(cause instanceof Error && "code" in cause && cause.code === "ENOENT") + ) + throw cause; + }); + } repositorySkill = await runStage("repository skill", () => verifyRepositorySkill({ root, workspace }), ); @@ -215,6 +247,13 @@ try { mcpStartup, mcpModuleLoading, }; + if (retentionMetadata !== undefined) { + retainedPackage = await retainVerifiedPackage({ + sourceTarball: tarball, + directory: retentionDirectory, + metadata: retentionMetadata, + }); + } } finally { await runStage("workspace cleanup", () => rm(workspace, { recursive: true, force: true }), @@ -223,6 +262,11 @@ try { const verifierLineage = await runStage("verifier lineage", () => completeVerifierRun(verifierRun), ); +if (retainedPackage !== undefined) + await writeVerifiedPackageManifest( + retainedPackage.directory, + retainedPackage.metadata, + ); process.stdout.write( `${JSON.stringify({ verifier_run: verifierLineage, ...report })}\n`, ); diff --git a/scripts/verify-packet-capture.mjs b/scripts/verify-packet-capture.mjs index 371c72367..9993117c2 100644 --- a/scripts/verify-packet-capture.mjs +++ b/scripts/verify-packet-capture.mjs @@ -1,8 +1,9 @@ #!/usr/bin/env node import assert from "node:assert/strict"; +import { estimateTokenCount } from "tokenx"; import { execFile } from "node:child_process"; import { createHash } from "node:crypto"; -import { readFile, writeFile, readdir } from "node:fs/promises"; +import { readFile, writeFile, readdir, mkdir, rm } from "node:fs/promises"; import { isAbsolute, join } from "node:path"; import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; @@ -91,6 +92,20 @@ const source = pcap(1, [ // LINKTYPE_BLUETOOTH_HCI_H4 = 187; H4 command packet, HCI Reset opcode 0x0c03, no parameters. const bluetoothSource = pcap(187, [Buffer.from("01030c00", "hex")]); let cases = 0; +const discoveryMeasurements = []; +const inheritedAddressSpace = (await readFile("/proc/self/limits", "utf8")) + .split("\n") + .find((line) => line.startsWith("Max address space ")) + ?.trim() + .match(/^Max address space\s+(\S+)\s+(\S+)\s+bytes$/u); +assert.ok(inheritedAddressSpace); +const expectedAddressSpace = Math.min( + 1073741824, + ...inheritedAddressSpace + .slice(1) + .map((value) => (value === "unlimited" ? Infinity : Number(value))), +); + try { await writeFile(path, source); await writeFile(bluetooth, bluetoothSource); @@ -121,14 +136,16 @@ try { .digest("hex"), ); assert.equal(report.hardware_acquisition, "not-performed"); - assert.equal(report.limits.address_space_bytes, 1073741824); + assert.equal(report.limits.address_space_bytes, expectedAddressSpace); assert.equal(report.tool.configured_path, process.env.REA_TSHARK_COMMAND); assert.equal( report.resource_limiter.configured_path, process.env.REA_TSHARK_PRLIMIT_COMMAND ?? "/usr/bin/prlimit", ); assert.ok( - report.resource_limiter.arguments.includes("--as=1073741824:1073741824"), + report.resource_limiter.arguments.includes( + `--as=${expectedAddressSpace}:${expectedAddressSpace}`, + ), ); assert.equal(report.configuration, "private-empty-personal-profile"); const flags = Object.entries(input) @@ -236,6 +253,52 @@ try { const hci = await inspect({ path: bluetooth, fields: ["bthci_cmd.opcode"] }); assert.deepEqual(hci.packets[0]["bthci_cmd.opcode"], ["0x0c03"]); assert.deepEqual(await readFile(path), source); + // Exercise the incremental summary workflow against the same owned bytes + // using real installed Wireshark tools; these inputs are format fixtures. + const pcapTool = (await client.listTools()).tools.find( + (t) => t.name === "inspect_pcap_capture", + ); + assert.ok(pcapTool?.outputSchema); + const pcapAjv = new Ajv2020({ strict: false, validateFormats: false }); + assert.ok(pcapAjv.validateSchema(pcapTool.inputSchema)); + assert.ok(pcapAjv.validateSchema(pcapTool.outputSchema)); + for (const capturePath of [path, bluetooth]) { + const response = await client.callTool({ + name: pcapTool.name, + arguments: { path: capturePath, detail: "summary" }, + }); + assert.notEqual(response.isError, true, JSON.stringify(response)); + assert.ok( + pcapAjv.validate(pcapTool.outputSchema, response.structuredContent), + pcapAjv.errorsText(), + ); + const summary = parseEvidence(response.structuredContent).normalized_result; + assert.equal( + summary.summary.target.sha256, + createHash("sha256") + .update(await readFile(capturePath)) + .digest("hex"), + ); + const source = { + kind: "retained-evidence", + evidence_id: summary.parent_evidence_id, + }; + const page = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source, + view: { kind: "pcap", facet: "protocols", limit: 10 }, + }, + }); + assert.notEqual(page.isError, true, JSON.stringify(page)); + assert.equal( + parseEvidence(page.structuredContent).normalized_result + .parent_evidence_id, + source.evidence_id, + ); + cases++; + } + assert.deepEqual(await readFile(bluetooth), bluetoothSource); for (const input of [ { path, fields: ["frame.number"], display_filter: "this is not a filter" }, @@ -267,6 +330,133 @@ try { true, ); cases++; + const discovery = (await client.listTools()).tools.find( + ({ name }) => name === "inspect_packet_fields", + ); + assert.ok(discovery?.outputSchema); + assert.ok(ajv.validateSchema(discovery.inputSchema)); + assert.ok(ajv.validateSchema(discovery.outputSchema)); + const nativeProfile = join(root.path, "native-profile"); + await mkdir(nativeProfile); + const native = ( + await execute(process.env.REA_TSHARK_COMMAND, ["-G", "fields"], { + env: { ...environment, WIRESHARK_CONFIG_DIR: nativeProfile }, + timeout: 30000, + maxBuffer: 32 * 1024 * 1024, + }) + ).stdout; + await rm(nativeProfile, { recursive: true }); + const nativeLines = native.split(/\r?\n/); + if (nativeLines.at(-1) === "") nativeLines.pop(); + for (const input of [ + { query: "usb" }, + { limit: 1 }, + { offset: 1, limit: 2 }, + { kind: "fields", protocol: "usb", query: "idVendor" }, + { kind: "fields", protocol: "udp", limit: null }, + { kind: "fields", query: "rea_no_such_field" }, + ]) { + const started = performance.now(); + const response = await client.callTool({ + name: discovery.name, + arguments: input, + }); + assert.notEqual(response.isError, true, JSON.stringify(response)); + assert.ok( + ajv.validate(discovery.outputSchema, response.structuredContent), + JSON.stringify(ajv.errors), + ); + const evidence = parseEvidence(response.structuredContent); + const report = evidence.normalized_result; + const kind = input.kind ?? "protocols"; + const query = (input.query ?? "").toLowerCase(); + const expectedMatches = nativeLines.flatMap((line, index) => { + const columns = line.split("\t"); + if ((kind === "protocols") !== (columns[0] === "P")) return []; + if ( + input.protocol !== undefined && + (columns[0] === "P" ? columns[2] : columns[4]) !== input.protocol + ) + return []; + if ( + ![ + columns[1], + columns[2], + ...(columns[0] === "F" ? [columns[7]] : []), + ].some((value) => value.toLowerCase().includes(query)) + ) + return []; + return [{ sourceLine: index + 1, columns }]; + }); + const offset = input.offset ?? 0; + const limit = input.limit === null ? undefined : (input.limit ?? 50); + const expectedPage = expectedMatches.slice( + offset, + limit === undefined ? undefined : offset + limit, + ); + assert.deepEqual( + report.records.map((record) => record.source_line), + expectedPage.map((record) => record.sourceLine), + ); + assert.deepEqual(report.output_window, { + examined: nativeLines.filter((line) => + line.startsWith(kind === "protocols" ? "P\t" : "F\t"), + ).length, + matching: expectedMatches.length, + returned: expectedPage.length, + has_more: + Math.max(0, expectedMatches.length - offset) > expectedPage.length, + }); + discoveryMeasurements.push({ + input, + elapsed_ms: +(performance.now() - started).toFixed(2), + response_bytes: Buffer.byteLength(JSON.stringify(response)), + estimated_tokens_one_tool_request_response: estimateTokenCount( + JSON.stringify(discovery) + + JSON.stringify(input) + + JSON.stringify(response), + ), + }); + for (const record of report.records) { + const columns = nativeLines[record.source_line - 1].split("\t"); + assert.equal(record.name, columns[1]); + assert.equal(record.abbreviation, columns[2]); + assert.equal(record.field_type, columns[0] === "F" ? columns[3] : null); + assert.equal( + record.parent_protocol, + columns[0] === "F" ? columns[4] : null, + ); + assert.equal(record.description, columns[0] === "F" ? columns[7] : null); + assert.equal(record.display_base, columns[0] === "F" ? columns[5] : null); + assert.equal(record.bitmask, columns[0] === "F" ? columns[6] : null); + } + if (input.query === "idVendor") + assert.ok( + report.records.some( + (row) => + row.abbreviation === "usb.idVendor" && + row.field_type === "FT_UINT16", + ), + ); + if (input.query === "usb") + assert.ok(report.records.some((row) => row.abbreviation === "usb")); + if (input.query === "rea_no_such_field") + assert.equal(report.output_window.matching, 0); + const flags = Object.entries(input).flatMap(([key, value]) => + value === null ? ["--all"] : [`--${key}`, String(value)], + ); + const cli = JSON.parse( + ( + await execute( + process.execPath, + [entrypoint, "inspect-packet-fields", ...flags, "--format", "json"], + { env: environment, timeout: 60000, maxBuffer: 16 * 1024 * 1024 }, + ) + ).stdout, + ); + assert.deepEqual(cli.normalized_result, report); + cases++; + } await client.close(); assert.deepEqual((await readdir(root.path)).sort(), [ "bluetooth.pcap", @@ -283,6 +473,9 @@ console.log( { status: "passed", cases, + discovery_measurements: discoveryMeasurements, + measurement_scope: + "Warm MCP server, fresh TShark processes; tokenx estimates include one advertised tool/request/response, not billed usage. Model-driven selection, CPU and peak process-family memory are unmeasured; no cache/speedup claim.", host: `${process.platform}/${process.arch}`, scope: "real TShark CLI/MCP; synthetic Ethernet/IPv4/UDP/DNS and Bluetooth HCI PCAP; no hardware acquisition", diff --git a/scripts/verify-pcap.mjs b/scripts/verify-pcap.mjs new file mode 100644 index 000000000..3adf14531 --- /dev/null +++ b/scripts/verify-pcap.mjs @@ -0,0 +1,131 @@ +import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; +import { mkdtemp, readdir, rmdir } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; +import { promisify } from "node:util"; +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; +import { toolContract } from "../dist/contracts/toolContracts.js"; +import { hashStableFile } from "../dist/filesystem/StableFileHash.js"; +import { mcpTextValue } from "./lib/mcp-verifier-results.mjs"; + +const args = process.argv.slice(2); +if (args.includes("--help") || args.includes("-h")) { + console.log( + "Usage: npm run verify:pcap -- [--pcap PATH]\nRequires caller-supplied tshark/capinfos. Without --pcap, only client readiness is verified.", + ); + process.exit(0); +} +if (!(args.length === 0 || (args.length === 2 && args[0] === "--pcap"))) + throw new Error("Expected --pcap PATH"); +const path = args[1] === undefined ? null : resolve(args[1]); +// This parent is shared by independent CLI/MCP owners. A leased Windows +// runtime root would prevent their native admission of its directory handle. +const root = await mkdtemp(join(tmpdir(), "rea-pcap-verifier-")); +const environment = Object.fromEntries( + Object.entries(process.env).filter(([, value]) => typeof value === "string"), +); +Object.assign(environment, { + TMPDIR: root, + TMP: root, + TEMP: root, +}); +const entrypoint = resolve("scripts/rea.mjs"); +const execute = promisify(execFile); +const client = new Client({ name: "pcap-real-verifier", version: "1" }); +const transport = new StdioClientTransport({ + command: process.execPath, + args: [entrypoint, "mcp"], + env: environment, + stderr: "pipe", +}); +transport.stderr?.resume(); +try { + await client.connect(transport); + const readiness = await run("inspect_pcap_client", {}); + assert(readiness.client.tshark_version && readiness.client.capinfos_version); + if (path === null) + console.log("[unverified] Capture inspection: no --pcap was supplied"); + else { + const identity = await hashStableFile(path); + const result = await run("inspect_pcap_capture", { path }); + assert.deepEqual(result.target, { path, ...identity }); + assert(result.packet_count >= 0); + assert( + result.endpoints.every( + (entry) => entry.packet_count <= result.packet_count, + ), + ); + assert( + result.protocol_distribution.every( + (entry) => entry.packet_count <= result.packet_count, + ), + ); + const partial = + result.endpoint_count > result.endpoints.length || + result.dns_query_count > result.dns_queries.length || + result.tls_sni_count > result.tls_sni_values.length || + result.protocol_count > result.protocol_distribution.length || + result.http_request_uri_count > result.http_request_uris.length || + result.unattributed_dns_packet_count > 0 || + result.dns_queries.some( + (entry) => + entry.response_address_count > entry.response_addresses.length, + ); + assert.equal(result.coverage, partial ? "partial" : "complete"); + assert.deepEqual( + await hashStableFile(path), + identity, + "Input capture must remain unchanged", + ); + console.log( + `[ok] ${result.packet_count} packets; ${result.endpoint_count} addresses; coverage=${result.coverage}`, + ); + } +} finally { + try { + await client.close(); + } finally { + await transport.close(); + } + assert.deepEqual( + await readdir(root), + [], + `Owned capture resources remain under ${root}`, + ); + await rmdir(root); +} +console.log("All asserted pcap CLI/MCP checks passed"); + +async function run(name, input) { + const contract = toolContract(name); + const { stdout } = await execute( + process.execPath, + [ + entrypoint, + name.replaceAll("_", "-"), + ...(input.path === undefined ? [] : [input.path]), + "--json", + ], + { env: environment, timeout: 360_000, maxBuffer: 8 * 1024 * 1024 }, + ); + const cli = contract.outputSchema.parse(JSON.parse(stdout)); + const response = await client.callTool( + { name, arguments: input }, + { timeout: 360_000 }, + ); + assert.notEqual(response.isError, true, mcpTextValue(response)); + const mcp = contract.outputSchema.parse(JSON.parse(mcpTextValue(response))); + assert.deepEqual(mcp.normalized_result, cli.normalized_result); + assert.deepEqual(mcp.subject, cli.subject); + if (input.path !== undefined) { + assert.equal(cli.subject.local_path, input.path); + assert.equal( + cli.subject.digest.sha256, + cli.normalized_result.target.sha256, + ); + } + console.log(`[ok] ${name}: named output schema and CLI/MCP Evidence parity`); + return cli.normalized_result; +} diff --git a/scripts/verify-qlog-captures.mjs b/scripts/verify-qlog-captures.mjs new file mode 100644 index 000000000..8d1a16f6c --- /dev/null +++ b/scripts/verify-qlog-captures.mjs @@ -0,0 +1,215 @@ +#!/usr/bin/env node +import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; +import { createHash } from "node:crypto"; +import { readFile, writeFile } from "node:fs/promises"; +import { isAbsolute } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; +import { Ajv2020 } from "ajv/dist/2020.js"; +import { parseEvidence } from "../dist/domain/evidence.js"; + +// Caller-supplied producer evidence stays local; no fixture capture or secrets are bundled. +const [controlPath, lossPath, reportPath] = process.argv.slice(2); +if ( + ![controlPath, lossPath, reportPath].every( + (value) => typeof value === "string" && isAbsolute(value), + ) +) + throw new Error( + "Usage: node scripts/verify-qlog-captures.mjs /absolute/control/origin.qlog /absolute/loss/origin.qlog /absolute/new-report.json", + ); +const entrypoint = fileURLToPath(new URL("./rea.mjs", import.meta.url)); +const client = new Client({ name: "qlog-producer-verifier", version: "1" }); +const environment = { + PATH: process.env.PATH ?? "/usr/bin:/bin", + REA_LOG_LEVEL: "silent", + HOPPER_LAUNCHER_PATH: "/rea-unconfigured-deep-provider/hopper", +}; +const transport = new StdioClientTransport({ + command: process.execPath, + args: [entrypoint, "mcp"], + env: environment, + stderr: "pipe", +}); +let diagnostics = ""; +transport.stderr?.on("data", (bytes) => { + if (diagnostics.length < 65536) diagnostics += bytes.toString("utf8"); +}); +const ajv = new Ajv2020({ strict: false, validateFormats: false }); +const measurements = []; +try { + try { + await client.connect(transport); + } catch (cause) { + throw new Error(`MCP startup failed: ${diagnostics}`, { cause }); + } + const tool = (await client.listTools()).tools.find( + (tool) => tool.name === "inspect_web_network_capture", + ); + assert.ok(tool?.outputSchema); + for (const schema of [tool.inputSchema, tool.outputSchema]) + assert.ok(ajv.validateSchema(schema)); + const validateOutput = ajv.compile(tool.outputSchema); + for (const [lane, path] of [ + ["control", controlPath], + ["loss", lossPath], + ]) { + const source = await readFile(path); + const raw = JSON.parse(source.toString("utf8")); + const sha256 = createHash("sha256").update(source).digest("hex"); + assert.equal(raw.qlog_format, "JSON"); + assert.equal(raw.qlog_version, "0.3"); + const input = { capture_path: path, format: "qlog" }; + assert.ok(ajv.validate(tool.inputSchema, input)); + const response = await client.callTool({ + name: tool.name, + arguments: input, + }); + assert.notEqual(response.isError, true); + assert.ok( + validateOutput(response.structuredContent), + JSON.stringify(validateOutput.errors), + ); + const mcp = parseEvidence(response.structuredContent); + const completed = await promisify(execFile)( + process.execPath, + [entrypoint, "inspect-web-network-capture", path, "qlog", "--json"], + { env: environment, timeout: 40_000, maxBuffer: 96 * 1024 * 1024 }, + ); + const cli = parseEvidence(JSON.parse(completed.stdout)); + assert.equal(cli.evidence_id, mcp.evidence_id); + assert.deepEqual(cli.normalized_result, mcp.normalized_result); + const capture = mcp.normalized_result; + assert.equal(capture.artifact.sha256, sha256); + assert.equal( + capture.total_records, + raw.traces.reduce((sum, trace) => sum + trace.events.length, 0), + ); + for (const [ordinal, original] of raw.traces + .flatMap((trace) => trace.events) + .entries()) { + const record = capture.records[ordinal]; + assert.equal(record.ordinal, ordinal); + assert.equal(record.reported.name, original.name); + assert.equal(record.reported.time, original.time); + assert.deepEqual(record.binary_fields, []); + assert.ok( + record.numeric_literals.some( + (number) => + number.pointer === "/time" && + Number(number.literal) === original.time, + ), + ); + } + assert.equal(capture.qlog.body_bytes, "not-reported"); + assert.equal(mcp.authority, "historical-reference"); + assert.equal( + mcp.analysis_profile.parameters.qlog_profile, + "aioquic-1.5.0-json-0.3", + ); + const trace = capture.qlog.traces[0]; + assert.equal(trace.vantage_point, "server"); + const stream = trace.streams.find( + (stream) => stream.stream_id === "0" && stream.direction === "sent", + ); + assert.ok(stream); + assert.equal(stream.unique_bytes, "32803"); + assert.equal( + stream.frame_length_sum, + lane === "control" ? "32803" : "33972", + ); + assert.equal(stream.repeated_bytes, lane === "control" ? "0" : "1169"); + assert.equal(trace.loss_declarations.length, lane === "control" ? 0 : 1); + if (lane === "loss") + assert.deepEqual(trace.loss_declarations[0].packet_number, { + state: "reported", + value: "5", + }); + // Structurally-known secrets may not survive in Evidence, including sidecars. + const serialized = JSON.stringify(mcp); + for (const original of raw.traces.flatMap((trace) => trace.events)) { + if ( + original.name === "transport:parameters_set" && + typeof original.data.stateless_reset_token === "string" + ) + assert.ok(!serialized.includes(original.data.stateless_reset_token)); + for (const frame of original.data.frames ?? []) { + if ( + frame.frame_type === "new_connection_id" && + typeof frame.reset_token === "string" + ) + assert.ok(!serialized.includes(frame.reset_token)); + if (frame.frame_type === "new_token" && typeof frame.token === "string") + assert.ok(!serialized.includes(frame.token)); + } + } + const retained = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { kind: "retained-evidence", evidence_id: mcp.evidence_id }, + view: { kind: "api-surface" }, + }, + }); + assert.equal(retained.isError, true); + assert.equal( + JSON.parse(retained.content.find((item) => item.type === "text").text) + .error.code, + "unsupported_target", + ); + const selected = await client.callTool({ + name: tool.name, + arguments: { ...input, record_ordinals: [capture.total_records - 1, 0] }, + }); + const subset = parseEvidence(selected.structuredContent).normalized_result; + assert.deepEqual( + subset.records.map((record) => record.ordinal), + [capture.total_records - 1, 0], + ); + assert.deepEqual(subset.qlog, capture.qlog); + measurements.push({ + lane, + path, + sha256, + evidence_id: mcp.evidence_id, + profile_digest: mcp.analysis_profile.digest, + events: capture.total_records, + stream_id: stream.stream_id, + unique_bytes: stream.unique_bytes, + frame_length_sum: stream.frame_length_sum, + repeated_bytes: stream.repeated_bytes, + loss_declarations: trace.loss_declarations.length, + cli_mcp_parity: true, + retained_reference: true, + selected_scope_preserved: true, + auth_exclusions: true, + }); + } + await client.ping(); + const report = { + status: "passed", + profile: "aioquic-1.5.0-json-0.3", + measurements, + limitations: [ + "Caller supplies provenance; format selection does not authenticate the producer.", + "These known loopback cases do not establish WAN behavior, other qlog producers, platforms or general completeness.", + "No PCAP or keylog is read by this verifier; repeated STREAM coverage is not proof of retransmission or network loss.", + ], + }; + await writeFile(reportPath, JSON.stringify(report, null, 2) + "\n", { + flag: "wx", + mode: 0o600, + }); + console.log( + JSON.stringify({ + status: report.status, + cases: measurements.length, + report: reportPath, + }), + ); +} finally { + await client.close(); + await transport.close(); +} diff --git a/scripts/verify-real-ghidra-address-context.mjs b/scripts/verify-real-ghidra-address-context.mjs new file mode 100644 index 000000000..2b650df93 --- /dev/null +++ b/scripts/verify-real-ghidra-address-context.mjs @@ -0,0 +1,313 @@ +import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; +import { createHash } from "node:crypto"; +import { mkdir, mkdtemp, readFile, readdir, rm } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; +import { parseEvidence } from "../dist/domain/evidence.js"; +import { requireMcpOperationResult } from "./lib/mcp-verifier-results.mjs"; +import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs"; + +if (process.argv.length !== 2 || process.platform !== "linux") + throw new Error("Run this ELF verifier on Linux without arguments."); +if (!process.env.GHIDRA_INSTALL_DIR) + throw new Error("Set GHIDRA_INSTALL_DIR to a caller-installed Ghidra."); +const exec = promisify(execFile); +const run = createVerifierRun(); +const root = fileURLToPath(new URL("..", import.meta.url)); +const workspace = await mkdtemp(join(tmpdir(), "rea-address-context-")); +const runtime = join(workspace, "runtime"); +await mkdir(runtime); +const path = join(workspace, "pie.elf"); +const entrypoint = join(root, "scripts/rea.mjs"); +const env = { + ...process.env, + TMPDIR: runtime, + REA_ANALYSIS_PROVIDER: "ghidra", + REA_LOG_LEVEL: "silent", +}; +const transport = new StdioClientTransport({ + command: process.execPath, + args: [entrypoint, "mcp"], + env, + stderr: "pipe", +}); +const client = new Client({ name: "rea-real-address-context", version: "1" }); +let stderr = ""; +transport.stderr?.on("data", (chunk) => { + stderr = (stderr + chunk.toString()).slice(-65536); +}); +let report; +let connected = false; +let primaryFailure; +let verifierRun; +try { + const compiler = process.env.CC ?? "gcc"; + const version = await exec(compiler, ["--version"], { timeout: 10000 }); + await exec( + compiler, + [ + "-O0", + "-g", + "-fPIE", + "-pie", + "-nostdlib", + "-Wl,-e,rea_pie_entry", + "-Wl,--build-id=none", + join(root, "tests/conformance/c/pie-address-context.c"), + "-o", + path, + ], + { timeout: 30000 }, + ); + const bytes = await readFile(path); + assert.equal(bytes.subarray(0, 6).toString("hex"), "7f454c460201"); + assert.equal(bytes.readUInt16LE(16), 3); // ET_DYN: source-owned x86-64 PIE. + assert.equal(bytes.readUInt16LE(18), 62); + const declaredEntry = `0x${bytes.readBigUInt64LE(24).toString(16)}`; + const sha256 = createHash("sha256").update(bytes).digest("hex"); + await client.connect(transport); + connected = true; + await call("open_binary", { path, provider_id: "ghidra" }); + const overview = parseEvidence(await call("binary_overview")); + assert.equal(overview.subject.digest.sha256, sha256); + const base = overview.normalized_result.image_base; + assert.match(base, /^0x[0-9a-f]+$/u); + assert.notEqual(base, "0x0"); + const active = await call("binary_session"); + const image = parseEvidence(await call("inspect_native_load_image")); + assert.equal(base, image.normalized_result.observations.image_base); + assert.ok(overview.normalized_result.segments.length > 0); + assert.ok( + overview.normalized_result.segments.every( + (segment) => + segment.image_base === base && + typeof segment.address_space === "string", + ), + ); + const procedures = parseEvidence(await call("list_procedures")); + const entry = procedures.normalized_result.find( + (item) => item.value === "rea_pie_entry", + ); + const addition = procedures.normalized_result.find( + (item) => item.value === "rea_pie_add", + ); + assert.ok(entry && addition); + assert.notEqual(entry.address, declaredEntry); + assert.ok( + image.normalized_result.observations.entry_points.includes(entry.address), + ); + const mapping = image.normalized_result.observations.mappings.find( + (item) => + item.source_file_index === 0 && + item.file_offset !== null && + item.address_space === "ram" && + BigInt(item.start) <= BigInt(entry.address) && + BigInt(item.end) >= BigInt(entry.address), + ); + assert.ok(mapping); + const offset = + mapping.file_offset + Number(BigInt(entry.address) - BigInt(mapping.start)); + const reverseMapping = parseEvidence( + await call("address_to_file_offset", { address: entry.address }), + ); + assert.equal(reverseMapping.normalized_result.file_offset, offset); + const memory = parseEvidence( + await call("read_bytes", { address: entry.address, length: 8 }), + ); + assert.equal( + memory.normalized_result.bytes_hex, + bytes.subarray(offset, offset + 8).toString("hex"), + ); + const fromOffset = parseEvidence( + await call("procedure_pseudo_code", { + procedure: `file-offset:0x${offset.toString(16)}`, + }), + ); + assert.ok( + fromOffset.locations.some( + (location) => + location.kind === "file-offset" && location.offset === offset, + ), + ); + assert.equal(fromOffset.raw_result.selection.mapped_address, entry.address); + const fromNumericOffset = parseEvidence( + await call("procedure_pseudo_code", { + procedure: `0x${offset.toString(16)}`, + }), + ); + assert.equal( + fromNumericOffset.normalized_result, + fromOffset.normalized_result, + ); + const missingAddress = "ram:0xffffffff"; + const rejected = await client.callTool( + { name: "procedure_pseudo_code", arguments: { procedure: missingAddress } }, + { timeout: 240000 }, + ); + assert.equal(rejected.isError, true); + assert.ok( + JSON.stringify(rejected.content).includes(`Ghidra image base: ${base}`), + ); + assert.ok(JSON.stringify(rejected.content).includes("list_procedures")); + assert.ok( + JSON.stringify(rejected.content).includes("inspect_native_load_image"), + ); + const pseudo = parseEvidence( + await call("procedure_pseudo_code", { procedure: addition.address }), + ); + assert.match(pseudo.normalized_result, /\+\s*(?:7|0x7)\b/u); + const retained = await call("binary_session"); + assert.equal(retained.analysis_run.run_id, active.analysis_run.run_id); + await call("close_binary"); + const cli = async (args) => + exec( + process.execPath, + [entrypoint, ...args, "--provider", "ghidra", "--json"], + { env, timeout: 240000, maxBuffer: 16 * 1024 * 1024 }, + ); + const cliOverview = parseEvidence( + JSON.parse((await cli(["analyze", path])).stdout), + ); + assert.deepEqual(cliOverview.normalized_result, overview.normalized_result); + let cliFailure; + try { + await cli(["decompile", path, missingAddress]); + } catch (cause) { + cliFailure = cause; + } + assert.ok(cliFailure && typeof cliFailure.stdout === "string"); + const error = JSON.parse(cliFailure.stdout); + assert.equal(error.code, "invalid_request"); + assert.ok(JSON.stringify(error).includes(`Ghidra image base: ${base}`)); + for (const command of [ + "rea search . --kind procedures --mode regex", + "rea analyze ", + "rea inspect-native-load-image ", + ]) + assert.ok(JSON.stringify(error).includes(command)); + const cliProcedures = parseEvidence( + JSON.parse( + ( + await cli([ + "search", + path, + ".", + "--kind", + "procedures", + "--mode", + "regex", + ]) + ).stdout, + ), + ); + const cliEntry = cliProcedures.normalized_result.find( + (item) => item.value === "rea_pie_entry", + ); + assert.ok(cliEntry); + assert.equal(cliEntry.address, entry.address); + const cliImage = parseEvidence( + JSON.parse((await cli(["inspect-native-load-image", path])).stdout), + ); + assert.equal(cliImage.normalized_result.observations.image_base, base); + const cliPseudo = parseEvidence( + JSON.parse((await cli(["decompile", path, cliEntry.address])).stdout), + ); + const cliOffset = parseEvidence( + JSON.parse( + (await cli(["decompile", path, `--file-offset=0x${offset.toString(16)}`])) + .stdout, + ), + ); + assert.equal(cliOffset.normalized_result, fromOffset.normalized_result); + assert.deepEqual(cliOffset.locations, fromOffset.locations); + assert.match(cliPseudo.normalized_result, /rea_pie_add/u); + assert.deepEqual(await readFile(path), bytes); + assert.deepEqual(await readdir(runtime), []); + report = { + ok: true, + mocked: false, + provider: image.provider, + compiler: version.stdout.split("\n")[0], + sha256, + declared_elf_entry: declaredEntry, + loaded_entry: entry.address, + observed_image_base: base, + cli_mcp_overview_parity: true, + failed_lookup_guidance: true, + cli_recovery_commands: true, + loaded_decompilation: true, + file_offset_decompilation: true, + address_file_offset_round_trip: true, + source_unchanged: true, + runtime_cleanup: "complete", + }; +} catch (cause) { + primaryFailure = { cause }; + if (stderr) process.stderr.write(stderr); +} + +const cleanupFailures = []; +// Await provider-owned cleanup before the SDK can terminate its MCP parent. +if (connected) { + try { + await call("close_binary"); + } catch (cause) { + cleanupFailures.push(cause); + } +} +try { + await client.close(); +} catch (cause) { + cleanupFailures.push(cause); +} +try { + await transport.close(); +} catch (cause) { + cleanupFailures.push(cause); +} +try { + assert.deepEqual(await readdir(runtime), []); + verifierRun = await completeVerifierRun(run); + assert.equal(verifierRun.process_lineage.status, "verified"); + assert.deepEqual(verifierRun.process_lineage.descendants, []); +} catch (cause) { + cleanupFailures.push(cause); +} +if (cleanupFailures.length === 0) { + try { + await rm(workspace, { recursive: true, force: true }); + } catch (cause) { + cleanupFailures.push(cause); + } +} +if (cleanupFailures.length > 0) { + process.stderr.write( + `Retained verifier workspace after cleanup failure: ${workspace}\n`, + ); + throw new AggregateError( + primaryFailure === undefined + ? cleanupFailures + : [primaryFailure.cause, ...cleanupFailures], + "Ghidra address-context verifier cleanup failed", + ); +} +if (primaryFailure !== undefined) throw primaryFailure.cause; +process.stdout.write( + JSON.stringify({ verifier_run: verifierRun, ...report }) + "\n", +); + +async function call(name, args = {}) { + const result = await client.callTool( + { name, arguments: args }, + { timeout: 240000 }, + ); + assert.notEqual(result.isError, true, JSON.stringify(result)); + return ["open_binary", "binary_session", "close_binary"].includes(name) + ? requireMcpOperationResult(result, name) + : result.structuredContent; +} diff --git a/scripts/verify-real-ghidra-windows.mjs b/scripts/verify-real-ghidra-windows.mjs index 5adf96009..bc822211f 100644 --- a/scripts/verify-real-ghidra-windows.mjs +++ b/scripts/verify-real-ghidra-windows.mjs @@ -28,6 +28,7 @@ import { import { parseBinaryTarget } from "../dist/application/BinaryTargetResolver.js"; import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs"; import { verifyGhidraCompactReferences } from "./lib/real-ghidra-compact-references.mjs"; +import { verifyGhidraFileOffsets } from "./lib/real-ghidra-file-offsets.mjs"; const verifierRun = createVerifierRun(); const SESSION_CAPABILITIES = GHIDRA_SESSION_CAPABILITIES.filter( @@ -300,6 +301,11 @@ try { } if (report === undefined) throw new Error("Windows Ghidra report was not produced"); +report.file_offsets = await verifyGhidraFileOffsets( + targetPath, + resolve(root, "scripts", "rea.mjs"), + architecture === "x86" ? "0x401010" : "0x140001010", +); process.stdout.write( `${JSON.stringify({ verifier_run: await completeVerifierRun(verifierRun), ...report })}\n`, ); diff --git a/scripts/verify-real-hopper-linux.mjs b/scripts/verify-real-hopper-linux.mjs index 854a58ce0..951b71078 100644 --- a/scripts/verify-real-hopper-linux.mjs +++ b/scripts/verify-real-hopper-linux.mjs @@ -11,7 +11,8 @@ createVerifierRun(); if (process.platform !== "linux") throw new Error("Linux real-Hopper verification must run on Linux"); -const launcher = process.env.HOPPER_LAUNCHER_PATH ?? "/opt/hopper/bin/Hopper"; +const configuredLauncher = process.env.HOPPER_LAUNCHER_PATH; +const launcher = configuredLauncher ?? "/opt/hopper/bin/Hopper"; await access(launcher); await access("/usr/bin/Xvfb"); await access("/usr/bin/xauth"); @@ -28,5 +29,7 @@ try { process.env.HOPPER_LAUNCHER_PATH = alternateLauncher; await import("./verify-real-hopper.mjs"); } finally { + if (configuredLauncher === undefined) delete process.env.HOPPER_LAUNCHER_PATH; + else process.env.HOPPER_LAUNCHER_PATH = configuredLauncher; await rm(alternateDirectory, { recursive: true, force: true }); } diff --git a/scripts/verify-real-hopper.mjs b/scripts/verify-real-hopper.mjs index 12400cb94..8cad9a256 100644 --- a/scripts/verify-real-hopper.mjs +++ b/scripts/verify-real-hopper.mjs @@ -47,6 +47,7 @@ import { } from "./lib/real-hopper-boundaries.mjs"; import { startUnrelatedHopperSentinel } from "./lib/unrelated-hopper-sentinel.mjs"; import { snapshotHopperRuntime } from "./lib/real-hopper-cleanup.mjs"; +import { verifyLinuxHopperOwnerExit } from "./lib/real-hopper-owner-exit.mjs"; const execFileAsync = promisify(execFile); const verifierRun = createVerifierRun(); const timeout = 180_000; @@ -577,6 +578,14 @@ if (sessionsAfter.length > 0) { } if (summary === undefined) throw new Error("Real-Hopper verification did not produce a summary"); +if (process.platform === "linux") + summary.ownerExit = await verifyLinuxHopperOwnerExit({ + primary: targetA, + secondary: targetB, + serverCommand, + serverArgs, + environment: serverEnvironment, + }); const completedVerifierRun = await completeVerifierRun(verifierRun); if ( completedVerifierRun.process_lineage.status !== "verified" || diff --git a/scripts/verify-real-ida.mjs b/scripts/verify-real-ida.mjs index 4709ea0a6..d71df94b6 100644 --- a/scripts/verify-real-ida.mjs +++ b/scripts/verify-real-ida.mjs @@ -18,6 +18,8 @@ const { values } = parseArgs({ procedure: { type: "string", default: "rea_fixture_add" }, "second-procedure": { type: "string" }, "second-marker": { type: "string" }, + "expected-string": { type: "string" }, + "expected-xref": { type: "string" }, "package-root": { type: "string" }, report: { type: "string" }, }, @@ -34,6 +36,8 @@ if ( throw new Error( "IDA verification requires --second-procedure and a nonempty --second-marker together; choose a marker unique to the second function's pseudocode.", ); +if (values["expected-string"] === "" || values["expected-xref"] === "") + throw new Error("IDA verification oracles must be nonempty."); const packageRoot = resolve( values["package-root"] ?? fileURLToPath(new URL("..", import.meta.url)), ); @@ -47,12 +51,14 @@ const [ { functionDossierSchema }, { readIdaConfiguration }, { createIdaMcpConnection }, + { idaAddressSchema }, ] = await Promise.all([ importBuilt("contracts/toolContracts.js"), importBuilt("domain/evidence.js"), importBuilt("domain/hopperValues.js"), importBuilt("ida/IdaConfiguration.js"), importBuilt("ida/IdaMcpConnection.js"), + importBuilt("ida/IdaProtocolValues.js"), ]); const registration = readIdaConfiguration(process.env.REA_IDA_MCP_CONFIG); if (!registration.ok) throw registration.error; @@ -79,7 +85,12 @@ const report = { config.protocol ?? (config.mode === "attached" ? "legacy" : "modern"), checks: [], observations: [], + unverified: [], }; +const expectedXref = + values["expected-xref"] === undefined + ? undefined + : idaAddressSchema.parse(values["expected-xref"]); let phase = "target admission"; const workspaces = new Set(); const databases = new Set(); @@ -184,12 +195,85 @@ const mcp = async (cliDossier) => { ["search_procedures", { pattern: dossier.procedure.name }], ["procedure_pseudo_code", { procedure: dossier.procedure.address }], ["read_function_instructions", { procedure: dossier.procedure.address }], - ["search_strings", { pattern: "a.b", mode: "literal" }], + [ + "search_strings", + { + pattern: values["expected-string"] ?? "a.b", + mode: "literal", + case_sensitive: true, + }, + ], ["xrefs", { address: dossier.procedure.address }], ]) { const result = await call(name, args); - observe(result); + const value = observe(result); + switch (name) { + case "list_procedures": + case "search_procedures": + assert.ok( + value.some( + (item) => + item.address === dossier.procedure.address && + item.value === dossier.procedure.name, + ), + `${name} omitted the resolved procedure.`, + ); + break; + case "procedure_address": + assert.equal(value, dossier.procedure.address); + break; + case "procedure_assembly": + assert.equal(value, dossier.assembly.join("\n")); + break; + case "procedure_pseudo_code": + assert.equal(value, dossier.pseudocode); + break; + case "procedure_callers": + case "procedure_callees": { + const expected = + name === "procedure_callers" ? dossier.callers : dossier.callees; + assert.deepEqual( + [...value].sort(), + expected.map((item) => item.address).sort(), + ); + break; + } + case "read_function_instructions": + assert.deepEqual(value.procedure.address, dossier.procedure.address); + assert.deepEqual(value.instructions, dossier.assembly); + break; + case "list_strings": + case "search_strings": + if (values["expected-string"] !== undefined) + assert.ok( + value.some((item) => + item.value.includes(values["expected-string"]), + ), + `${name} omitted the expected literal.`, + ); + break; + case "xrefs": + if (expectedXref !== undefined) + assert.ok( + value.includes(expectedXref), + "xrefs omitted the expected source address.", + ); + break; + } } + if (values["expected-string"] === undefined) + report.unverified.push( + "String inventory/search correctness: no independent expected literal supplied.", + ); + else + report.checks.push( + "string inventory and literal search contain the expected literal", + ); + if (expectedXref === undefined) + report.unverified.push( + "Xref correctness: no independent expected source address supplied.", + ); + else report.checks.push("xrefs contain the expected source address"); if (values["second-procedure"] !== undefined) { const secondAddress = observe( await call("procedure_address", { @@ -231,10 +315,10 @@ const mcp = async (cliDossier) => { await call("close_binary", {}); opened = false; report.checks.push( - "one MCP connection, target selection, analysis/search/xrefs, invalid input, and close", + "one MCP connection, positive procedure inventory/search, contract-valid tool results, invalid input, and close", ); report.checks.push( - "CLI/MCP function identity, pseudocode, assembly, and raw Evidence parity", + "CLI/MCP function identity, pseudocode, assembly, instructions, and relationship parity", ); } finally { const completedPhase = phase; @@ -300,6 +384,7 @@ try { passed: report.passed, mode: report.mode, checks: report.checks, + unverified: report.unverified, ...(report.passed ? {} : { diff --git a/scripts/verify-signal-recording.mjs b/scripts/verify-signal-recording.mjs index a095b97ff..f5baaf0b9 100644 --- a/scripts/verify-signal-recording.mjs +++ b/scripts/verify-signal-recording.mjs @@ -1,5 +1,6 @@ #!/usr/bin/env node import assert from "node:assert/strict"; +import { estimateTokenCount } from "tokenx"; import { execFile } from "node:child_process"; import { createHash } from "node:crypto"; import { readFile, writeFile, readdir } from "node:fs/promises"; @@ -68,6 +69,20 @@ for (const byte of Buffer.from("REA")) { lines.push(`#${tick + 1000}`, "1!"); const source = lines.join("\n") + "\n"; let cases = 0; +const discoveryMeasurements = []; +const inheritedAddressSpace = (await readFile("/proc/self/limits", "utf8")) + .split("\n") + .find((line) => line.startsWith("Max address space ")) + ?.trim() + .match(/^Max address space\s+(\S+)\s+(\S+)\s+bytes$/u); +assert.ok(inheritedAddressSpace); +const expectedAddressSpace = Math.min( + 1073741824, + ...inheritedAddressSpace + .slice(1) + .map((value) => (value === "unlimited" ? Infinity : Number(value))), +); + try { await writeFile(path, source); await client.connect(transport); @@ -104,14 +119,16 @@ try { createHash("sha256").update(source).digest("hex"), ); assert.equal(report.hardware_acquisition, "not-performed"); - assert.equal(report.limits.address_space_bytes, 1073741824); + assert.equal(report.limits.address_space_bytes, expectedAddressSpace); assert.equal(report.tool.configured_path, process.env.REA_SIGROK_COMMAND); assert.equal( report.resource_limiter.configured_path, process.env.REA_SIGROK_PRLIMIT_COMMAND ?? "/usr/bin/prlimit", ); assert.ok( - report.resource_limiter.arguments.includes("--as=1073741824:1073741824"), + report.resource_limiter.arguments.includes( + `--as=${expectedAddressSpace}:${expectedAddressSpace}`, + ), ); assert.equal(report.diagnostics, ""); const flags = Object.entries(input) @@ -245,6 +262,88 @@ try { }); assert.equal(invalid.isError, true); cases++; + const discoveryTool = (await client.listTools()).tools.find( + ({ name }) => name === "inspect_signal_decoders", + ); + assert.ok(discoveryTool?.outputSchema); + assert.ok(ajv.validateSchema(discoveryTool.inputSchema)); + assert.ok(ajv.validateSchema(discoveryTool.outputSchema)); + const nativeHelp = ( + await execute( + process.env.REA_SIGROK_COMMAND, + ["--dont-scan", "--protocol-decoders=uart", "--show"], + { env: environment, timeout: 30000, maxBuffer: 4 * 1024 * 1024 }, + ) + ).stdout.split(/\r?\n/); + if (nativeHelp.at(-1) === "") nativeHelp.pop(); + for (const input of [ + { query: "uart" }, + { limit: 1 }, + { offset: 1, limit: 2 }, + { decoder: "uart", query: "BaUd" }, + { decoder: "uart", offset: 50, limit: null }, + { query: "rea_no_such_decoder" }, + ]) { + const started = performance.now(); + const response = await client.callTool({ + name: discoveryTool.name, + arguments: input, + }); + assert.notEqual(response.isError, true, JSON.stringify(response)); + assert.ok( + ajv.validate(discoveryTool.outputSchema, response.structuredContent), + JSON.stringify(ajv.errors), + ); + const evidence = parseEvidence(response.structuredContent); + const report = evidence.normalized_result; + discoveryMeasurements.push({ + input, + elapsed_ms: +(performance.now() - started).toFixed(2), + response_bytes: Buffer.byteLength(JSON.stringify(response)), + estimated_tokens_one_tool_request_response: estimateTokenCount( + JSON.stringify(discoveryTool) + + JSON.stringify(input) + + JSON.stringify(response), + ), + }); + if (input.decoder) { + const matched = nativeHelp + .map((text, i) => ({ line_number: i + 1, text })) + .filter(({ text }) => + text.toLowerCase().includes((input.query ?? "").toLowerCase()), + ); + assert.deepEqual( + report.help_lines, + matched.slice( + input.offset ?? 0, + input.limit === null + ? undefined + : (input.offset ?? 0) + (input.limit ?? 50), + ), + ); + } else if (input.query === "uart") + assert.ok(report.decoders.some(({ id }) => id === "uart")); + const flags = Object.entries(input).flatMap(([key, value]) => + value === null ? ["--all"] : [`--${key}`, String(value)], + ); + const cli = JSON.parse( + ( + await execute( + process.execPath, + [entrypoint, "inspect-signal-decoders", ...flags, "--format", "json"], + { env: environment, timeout: 60000, maxBuffer: 8 * 1024 * 1024 }, + ) + ).stdout, + ); + assert.deepEqual(cli.normalized_result, report); + cases++; + } + const unavailable = await client.callTool({ + name: discoveryTool.name, + arguments: { decoder: "rea_no_such_decoder" }, + }); + assert.equal(unavailable.isError, true); + cases++; await client.close(); assert.deepEqual((await readdir(root.path)).sort(), [ "paged.vcd", @@ -260,6 +359,9 @@ console.log( { status: "passed", cases, + discovery_measurements: discoveryMeasurements, + measurement_scope: + "Warm MCP server, fresh sigrok processes; tokenx estimates include one advertised tool/request/response, not billed model usage. No model-driven selection benchmark, CPU or peak process-family memory measurement; no cache or speedup claim.", host: `${process.platform}/${process.arch}`, scope: "real sigrok UART VCD through compiled CLI/MCP; no physical acquisition", diff --git a/scripts/verify-windows-native.mjs b/scripts/verify-windows-native.mjs index c63b6909f..8623081f9 100644 --- a/scripts/verify-windows-native.mjs +++ b/scripts/verify-windows-native.mjs @@ -11,6 +11,7 @@ import { mkdtemp, readFile, rename, + readdir, rm, symlink, writeFile, @@ -37,6 +38,14 @@ const { WindowsPrivateRuntime, windowsPrivateRuntime } = await import( const { ghidraSessionRoot } = await import( pathToFileURL(join(packageRoot, "dist/ghidra/GhidraSessionRoot.js")) ); +const { PrivateRuntimeRoot } = await import( + pathToFileURL(join(packageRoot, "dist/process/PrivateRuntimeRoot.js")) +); +const { PrivateRuntimeRootUnavailableError } = await import( + pathToFileURL( + join(packageRoot, "dist/process/PrivateRuntimeRootUnavailableError.js"), + ) +); const workspace = await mkdtemp(join(tmpdir(), "rea-native-conformance-")); const environment = Object.entries(process.env) .filter(([, value]) => value !== undefined) @@ -140,6 +149,30 @@ process.stdout.write(JSON.stringify({executable:basename(process.execPath),abiVe ]) assert.throws(() => native.call("open", [rejected])); report.controls.ordinaryDriveSeparatorsAndRequestedIdentity = true; + // An owned runtime's DELETE lease conflicts with a fresh parent admission. + // This produces a genuine sharing failure after successful authority caching, + // without another executable, and proves that no child runtime was created. + const sharingParent = WindowsPrivateRuntime.create( + workspace, + "rea-sharing-parent-", + ); + try { + await assert.rejects( + PrivateRuntimeRoot.create({ parent: sharingParent.observation.path }), + (failure) => { + assert.ok(failure instanceof PrivateRuntimeRootUnavailableError); + assert.equal(failure.retryable, true); + assert.ok(failure.cause instanceof Error); + assert.equal(failure.cause.win32Code, 32); + assert.equal(failure.cause.runtimeAllocation, "not-started"); + return true; + }, + ); + assert.deepEqual(await readdir(sharingParent.observation.path), []); + report.controls.transientRuntimeAdmissionBeforeAllocation = true; + } finally { + await sharingParent.close(); + } const driveRoot = parse(workspace).root; const runtimeParent = ghidraSessionRoot({ base: join(driveRoot, ".Tmp", "scratch"), @@ -629,6 +662,42 @@ setInterval(()=>{},1000);\n`, unicodeNamesPreserved: true, }); report.processes.windowsEnvironmentSemantics = true; + // Observed through this process's own id: a separate probe process would + // get its own processor group, so it cannot stand in for the process that + // spawns the child. + const callerAffinity = JSON.parse( + execFileSync(boundaryFixture, ["affinity", String(process.pid)], { + encoding: "utf8", + }), + ); + const affinityChild = native.call("process_spawn", [ + boundaryFixture, + `${quote(boundaryFixture)} affinity`, + workspace, + environment, + ]); + const observedAffinity = await wait(affinityChild); + native.call("process_close", [affinityChild.handle]); + assert.equal(observedAffinity.exitCode, 0); + const childAffinity = JSON.parse(observedAffinity.output); + // Masks cross as hexadecimal strings because a mask can exceed the + // safe-integer range. Sharing one processor group makes the caller's mask + // applicable, so it must be inherited exactly. Windows placing the child in + // another group is only permitted when the caller asked for no bound of its + // own, which its group's whole active set establishes; a narrower mask has + // to fail the spawn rather than widen to that group's default. + const sharedGroup = + callerAffinity.singleProcessorGroup && + childAffinity.singleProcessorGroup && + callerAffinity.processorGroup === childAffinity.processorGroup; + if (sharedGroup) + assert.equal(childAffinity.affinityMask, callerAffinity.affinityMask); + else assert.equal(callerAffinity.affinityMask, callerAffinity.systemMask); + report.processes.callerAffinityBoundsOwnedProcessOrRefusesToWiden = true; + report.callerAffinity = { + ...callerAffinity, + sharedGroupWithChild: sharedGroup, + }; } const ownerFixture = join(workspace, "owner.mjs"); const ownerPidFile = join(workspace, "crash-child.pid"); diff --git a/scripts/verify/harmony/analysis.mjs b/scripts/verify/harmony/analysis.mjs index 43cbc2819..996667781 100644 --- a/scripts/verify/harmony/analysis.mjs +++ b/scripts/verify/harmony/analysis.mjs @@ -153,10 +153,36 @@ try { }); try { await client.connect(transport, { timeout: 30_000 }); + await client.listTools(); + const opened = await client.callTool( + { name: "open_binary", arguments: { path } }, + { timeout: 150_000 }, + ); + assert.notEqual(opened.isError, true, JSON.stringify(opened)); + assert.equal(opened.structuredContent?.result?.format, "hap"); + assert.equal(opened.structuredContent?.result?.sha256, fixture.sha256); + const status = await client.callTool( + { name: "binary_session", arguments: {} }, + { timeout: 150_000 }, + ); + assert.notEqual(status.isError, true, JSON.stringify(status)); + assert.equal(status.structuredContent?.result?.open, true); + assert.equal(status.structuredContent?.result?.format, "hap"); + const inspected = await client.callTool( + { name: "inspect_artifact", arguments: {} }, + { timeout: 150_000 }, + ); + assert.notEqual(inspected.isError, true, JSON.stringify(inspected)); + const mcpInspection = parseEvidence(inspected.structuredContent); + assert.deepEqual( + mcpInspection.normalized_result, + inspection.normalized_result, + ); + console.log("PASS MCP open/status/inspect_artifact parity"); const response = await client.callTool( { name: "project_harmony_application_graph", - arguments: { inventory_evidence: [inspection] }, + arguments: { inventory_evidence: [mcpInspection] }, }, { timeout: 150_000 }, ); @@ -168,6 +194,23 @@ try { projectionEvidence.normalized_result, ); console.log("PASS MCP/CLI parity project_harmony_application_graph"); + const closed = await client.callTool( + { name: "close_binary", arguments: {} }, + { timeout: 150_000 }, + ); + assert.notEqual(closed.isError, true, JSON.stringify(closed)); + const empty = await client.callTool( + { name: "binary_session", arguments: {} }, + { timeout: 150_000 }, + ); + assert.notEqual(empty.isError, true, JSON.stringify(empty)); + assert.equal(empty.structuredContent?.result?.open, false); + assert.equal( + await hashFile(path), + fixture.sha256, + "MCP workflow must preserve source bytes", + ); + console.log("PASS MCP close and unchanged source bytes"); } catch (cause) { process.stderr.write(stderr); throw cause; diff --git a/scripts/website.py b/scripts/website.py index a3bd44333..22c0829b9 100644 --- a/scripts/website.py +++ b/scripts/website.py @@ -114,12 +114,12 @@ def shared_blocks(root, path, source): } from website_i18n import language_markup selector, alternates = language_markup(root, path.relative_to(site).as_posix()) - values["language_picker"] = selector if not metadata.noindex else "" + values["language_picker"] = indent(selector, " ") if not metadata.noindex else "" values["alternates"] = alternates if not metadata.noindex else "" templates = root / "website/templates" return { name: indent(Template((templates / f"{name}.html.tmpl").read_text(encoding="utf-8")).substitute(values), " ") - for name in ("sharing", "header", "footer") + for name in ("sharing", "theme", "header", "footer") } diff --git a/src/adb/AdbDeviceOutput.test.ts b/src/adb/AdbDeviceOutput.test.ts index fe11c2a26..12b82ab84 100644 --- a/src/adb/AdbDeviceOutput.test.ts +++ b/src/adb/AdbDeviceOutput.test.ts @@ -84,6 +84,24 @@ describe("parseAdbDevicesOutput", () => { ]); }); + it("accepts complete multiword states and rejects state prefixes", () => { + const output = [ + "serial-no-permission no permissions usb:1-1", + "serial-bad-device deviceXYZ ", + "serial-bad-offline offline-ish", + "serial-bad-auth unauthorizedXYZ", + ].join("\n"); + const { devices, unparsedLines } = parseAdbDevicesOutput(output); + expect(devices.map(({ serial, state }) => [serial, state])).toEqual([ + ["serial-no-permission", "no permissions"], + ]); + expect(unparsedLines).toEqual([ + "serial-bad-device deviceXYZ ", + "serial-bad-offline offline-ish", + "serial-bad-auth unauthorizedXYZ", + ]); + }); + it("returns unrecognized lines instead of dropping them", () => { const output = [ "List of devices attached", @@ -194,10 +212,10 @@ describe("parsePackageListOutput", () => { it("keeps unrecognized lines for partial coverage reporting", () => { const { packages, unparsedLines } = parsePackageListOutput( - "package:/data/app/x/base.apk=com.ok\ngarbage line\n", + "package:/data/app/x/base.apk=com.ok\n garbage line \n", ); expect(packages).toHaveLength(1); - expect(unparsedLines).toEqual(["garbage line"]); + expect(unparsedLines).toEqual([" garbage line "]); }); }); diff --git a/src/adb/AdbDeviceOutput.ts b/src/adb/AdbDeviceOutput.ts index 3380de608..8d3c74f5f 100644 --- a/src/adb/AdbDeviceOutput.ts +++ b/src/adb/AdbDeviceOutput.ts @@ -10,11 +10,15 @@ import { adbHostFileName, type AdbHostFileNameReason, } from "./AdbHostFileName.js"; +import { + ADB_DEVICE_STATES, + type AdbDeviceState, +} from "../domain/adb/adbDeviceAnalysis.js"; /** One device exactly as `adb devices -l` reports it. */ export interface AdbDeviceEntry { readonly serial: string; - readonly state: string; + readonly state: AdbDeviceState; readonly transport: "usb" | "tcp" | "unknown"; readonly product: string | null; readonly model: string | null; @@ -24,25 +28,6 @@ export interface AdbDeviceEntry { readonly kind_basis: "emulator_serial_prefix" | "usb_transport" | "none"; } -/** - * Device states adb prints after the serial, longest first so two-word - * states match before their single-word prefixes. A line whose remainder - * starts with none of them is not a device line. - */ -const DEVICE_STATES = [ - "no permissions", - "unauthorized", - "authorizing", - "offline", - "recovery", - "sideload", - "connecting", - "bootloader", - "device", - "unknown", - "host", -] as const; - const DEVICE_LINE = /^(\S+)\s+(.*)$/u; const metadataValue = (remainder: string, key: string): string | null => { @@ -73,11 +58,15 @@ export const parseAdbDevicesOutput = ( continue; } const match = DEVICE_LINE.exec(line); - const state = DEVICE_STATES.find((candidate) => - match?.[2]?.startsWith(candidate), - ); + const state = ADB_DEVICE_STATES.find((candidate) => { + const remainder = match?.[2]; + if (remainder === undefined || !remainder.startsWith(candidate)) + return false; + const next = remainder[candidate.length]; + return next === undefined || /\s/u.test(next); + }); if (match === null || state === undefined) { - if (line.trim() !== "") unparsedLines.push(line); + if (rawLine.trim() !== "") unparsedLines.push(rawLine); continue; } const serial = match[1]!; @@ -192,7 +181,7 @@ export const parsePackageListOutput = ( if (line === "") continue; const match = PACKAGE_LINE.exec(line); if (match === null) { - unparsedLines.push(line); + unparsedLines.push(rawLine); continue; } packages.push({ diff --git a/src/adb/AdbProvider.test.ts b/src/adb/AdbProvider.test.ts index d1a153848..ae81353c7 100644 --- a/src/adb/AdbProvider.test.ts +++ b/src/adb/AdbProvider.test.ts @@ -121,6 +121,52 @@ fi`, ]); }); +it("refuses device listings with an invalid state token", async () => { + const malformedLine = "serial deviceXYZ "; + const { binary } = await writeAdbStub( + () => `if [ "$1" = "version" ]; then ${VERSION_BLOCK}; exit 0; fi +if [ "$1" = "devices" ]; then + printf 'List of devices attached\\n${malformedLine}\\n' + exit 0 +fi`, + ); + const result = await providerOver(binary).execute({ + operation: "list_adb_devices", + input: {}, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error._tag).toBe("AnalysisProtocolError"); + expect(result.error.message).toContain(malformedLine); +}); + +it("lists rescue and detached transports alongside online devices", async () => { + const { binary } = await writeAdbStub( + () => `if [ "$1" = "version" ]; then ${VERSION_BLOCK}; exit 0; fi +if [ "$1" = "devices" ]; then + printf 'List of devices attached\\n' + printf 'serial-online device transport_id:1\\n' + printf 'serial-rescue rescue transport_id:2\\n' + printf 'serial-detached detached transport_id:3\\n' + exit 0 +fi`, + ); + const result = await evidenceResult(providerOver(binary), { + operation: "list_adb_devices", + input: {}, + }); + expect(result.devices).toEqual( + expect.arrayContaining([ + expect.objectContaining({ serial: "serial-online", state: "device" }), + expect.objectContaining({ serial: "serial-rescue", state: "rescue" }), + expect.objectContaining({ + serial: "serial-detached", + state: "detached", + }), + ]), + ); +}); + it("inspects a device through the getprop whitelist", async () => { const { binary } = await writeAdbStub( () => `if [ "$1" = "version" ]; then ${VERSION_BLOCK}; exit 0; fi @@ -580,6 +626,34 @@ it("projects package details from dumpsys package output", async () => { }); }); +// Android 10 and 11 append ": restricted=true" to hard- and soft-restricted +// entries of the requested-permissions list (Settings.dumpPackageLPr). +it("counts requested permissions that the device marks as restricted", async () => { + const { binary } = await writeAdbStub( + shellStub({ + "dumpsys:package": `Packages: + Package [com.example] (abcdef): + userId=10234 + versionName=1.2.3 + requested permissions: + android.permission.INTERNET + android.permission.WRITE_EXTERNAL_STORAGE: restricted=true + android.permission.CAMERA + install permissions: + android.permission.INTERNET: granted=true +`, + }), + ); + const result = await evidenceResult(providerOver(binary), { + operation: "inspect_adb_package", + input: { serial: "emulator-5554", package: "com.example" }, + }); + expect(result).toMatchObject({ + requested_permissions_count: 3, + coverage: "complete", + }); +}); + it("reports an uninstalled package from dumpsys refusal output", async () => { const { binary } = await writeAdbStub( shellStub({ "dumpsys:package": "Unable to find package: com.absent\n" }), diff --git a/src/adb/AdbShellOutput.ts b/src/adb/AdbShellOutput.ts index f3323e7b2..726e6164d 100644 --- a/src/adb/AdbShellOutput.ts +++ b/src/adb/AdbShellOutput.ts @@ -236,7 +236,11 @@ export const parseDumpsysPackageOutput = ( inPermissions = true; continue; } - if (inPermissions && /^\s{2,}[A-Za-z0-9._]+$/.test(line)) { + // Android 10 and 11 mark restricted entries as "NAME: restricted=true". + if ( + inPermissions && + /^\s{2,}[A-Za-z0-9._]+(?:: restricted=true)?$/u.test(line) + ) { permissions += 1; continue; } diff --git a/src/android/JadxMcpTransport.ts b/src/android/JadxMcpTransport.ts index c648696fc..a40d517f5 100644 --- a/src/android/JadxMcpTransport.ts +++ b/src/android/JadxMcpTransport.ts @@ -199,9 +199,11 @@ export class JadxMcpTransport implements Transport { throw new Error(`JADX MCP frame exceeds ${MAX_FRAME_BYTES} bytes`); this.#appendFrame(fragment, frameBytes); if (newline === -1) return; - const line = this.#frameBuffer - .subarray(0, this.#frameLength) - .toString("utf8"); + const line = new TextDecoder("utf-8", { + fatal: true, + // Preserve a leading BOM so the JSON-RPC parser can reject it. + ignoreBOM: true, + }).decode(this.#frameBuffer.subarray(0, this.#frameLength)); this.#frameBuffer = Buffer.alloc(0); this.#frameLength = 0; this.onmessage?.(deserializeMessage(line)); diff --git a/src/apktool/ApktoolProvider.test.ts b/src/apktool/ApktoolProvider.test.ts index 5b2a32114..b6ee249e5 100644 --- a/src/apktool/ApktoolProvider.test.ts +++ b/src/apktool/ApktoolProvider.test.ts @@ -96,6 +96,7 @@ const decodeStub = ( readonly withStrings?: boolean; readonly withGerman?: boolean; readonly failDecode?: boolean; + readonly ymlFile?: string; readonly manifestFile?: string; readonly stringsFile?: string; readonly stringsXml?: string; @@ -104,6 +105,10 @@ const decodeStub = ( const withStrings = options.withStrings ?? true; const withGerman = options.withGerman ?? true; const stringsXml = options.stringsXml ?? REAL_STRINGS; + const ymlWrite = + options.ymlFile === undefined + ? `printf '%s\\n' '${REAL_YML.replace(/'/gu, "'\\''")}' > "$5/apktool.yml"` + : `cp '${options.ymlFile}' "$5/apktool.yml"`; const manifestWrite = options.manifestFile === undefined ? `printf '%s\\n' '${REAL_MANIFEST.replace(/'/gu, "'\\''")}' > "$5/AndroidManifest.xml"` @@ -117,7 +122,7 @@ if [ "$1" = "d" ]; then ${ options.failDecode === true ? `printf 'Exception in thread "main" brut.androlib.AndrolibException: Could not decode the APK\\n' >&2; exit 1;` - : `printf '%s\\n' '${REAL_YML.replace(/'/gu, "'\\''")}' > "$5/apktool.yml" + : `${ymlWrite} ${manifestWrite} mkdir -p "$5/res/values"${withGerman ? ' "$5/res/values-de"' : ""} ${withStrings ? stringsWrite : ""} @@ -192,6 +197,47 @@ it("decodes resources with target identity, metadata, and strings", async () => expect(result.coverage).toBe("complete"); }); +it.each([ + { + name: "malformed UTF-8", + bytes: Buffer.concat([ + Buffer.from("versionInfo:\n versionName: com."), + Buffer.from([0xff]), + Buffer.from(".app\n"), + ]), + valid: false, + }, + { + name: "a literal replacement character", + bytes: Buffer.from("versionInfo:\n versionName: com.�.app\n", "utf8"), + valid: true, + }, +])("handles $name in producer metadata", async ({ bytes, valid }) => { + const { command, root } = await writeApktoolStub((root) => + decodeStub({ ymlFile: join(root, "malformed-apktool.yml") })(root), + ); + await writeFile(join(root, "malformed-apktool.yml"), bytes); + const apk = await apkFixture(root); + if (valid) { + const result = await evidenceResult(providerOver(command), { + operation: "decode_android_resources", + input: { path: apk.path, include_strings: false }, + }); + expect(result.metadata).toMatchObject({ version_name: "com.�.app" }); + expect(result.coverage).toBe("complete"); + return; + } + const result = await providerOver(command).execute({ + operation: "decode_android_resources", + input: { path: apk.path, include_strings: false }, + }); + if (result.ok) throw new Error("expected invalid producer output"); + const projected = projectAnalysisError(result.error); + expect(projected).toMatchObject({ code: "unreadable_output" }); + expect(result.error.message).toContain("invalid UTF-8"); + expect(result.error.message).toContain("apktool.yml"); +}); + it("preserves empty resource strings and reports markup omissions as partial", async () => { const stringsXml = ' A & B Hello world'; diff --git a/src/apktool/ApktoolProvider.ts b/src/apktool/ApktoolProvider.ts index 682e2f2ea..1e1f187c0 100644 --- a/src/apktool/ApktoolProvider.ts +++ b/src/apktool/ApktoolProvider.ts @@ -117,13 +117,20 @@ const readBoundedText = async ( throwIfCancelled(operation, signal); const truncated = length > budget; // A prefix may end within a UTF-8 character; omit those trailing bytes. - const decoder = new TextDecoder("utf-8"); - return { - text: decoder.decode(bytes.subarray(0, Math.min(length, budget)), { - stream: truncated, - }), - truncated, - }; + try { + const decoder = new TextDecoder("utf-8", { fatal: true }); + return { + text: decoder.decode(bytes.subarray(0, Math.min(length, budget)), { + stream: truncated, + }), + truncated, + }; + } catch (cause: unknown) { + throw new AnalysisProtocolError( + `apktool produced invalid UTF-8 in ${path}`, + { cause }, + ); + } } finally { await file.close(); } diff --git a/src/application/AnalysisProvider.ts b/src/application/AnalysisProvider.ts index cc17cac82..f3b51257a 100644 --- a/src/application/AnalysisProvider.ts +++ b/src/application/AnalysisProvider.ts @@ -54,6 +54,15 @@ export interface AnalysisExecution { readonly subject: EvidenceSubjectTarget | null; } +interface CreateAnalysisExecutionOptions { + readonly rawResult?: unknown; + readonly analysisProfile?: AnalysisProfileCommitment; + readonly limitations?: readonly string[]; + readonly relationshipCoverage?: RelationshipCoverage; + readonly locations?: readonly EvidenceLocation[]; + readonly subject?: EvidenceSubjectTarget; +} + /** * Build a validated atomic provider observation at an adapter boundary. * @@ -61,38 +70,43 @@ export interface AnalysisExecution { * `result`. Omitting it records `null` rather than a second complete copy of * the normalized result in every Evidence record and tool response. */ -export const createAnalysisExecution = ( +export function createAnalysisExecution( result: unknown, provider: ProviderIdentity, - options: { - readonly rawResult?: unknown; - readonly analysisProfile?: AnalysisProfileCommitment; - readonly limitations?: readonly string[]; - readonly relationshipCoverage?: RelationshipCoverage; - readonly locations?: readonly EvidenceLocation[]; - readonly subject?: EvidenceSubjectTarget; - } = {}, -): AnalysisExecution => ({ - result: jsonValueSchema.parse(result), - rawResult: - options.rawResult === undefined - ? null - : jsonValueSchema.parse(options.rawResult), - provider, - ...(options.analysisProfile === undefined - ? {} - : { analysisProfile: structuredClone(options.analysisProfile) }), - limitations: [...(options.limitations ?? [])], - ...(options.relationshipCoverage === undefined - ? {} - : { - relationshipCoverage: relationshipCoverageSchema.parse( - options.relationshipCoverage, - ), - }), - locations: [...(options.locations ?? [])], - subject: options.subject ?? null, -}); + options: CreateAnalysisExecutionOptions & { readonly subject: Subject }, +): Omit & { readonly subject: Subject }; +export function createAnalysisExecution( + result: unknown, + provider: ProviderIdentity, + options?: CreateAnalysisExecutionOptions, +): AnalysisExecution; +export function createAnalysisExecution( + result: unknown, + provider: ProviderIdentity, + options: CreateAnalysisExecutionOptions = {}, +): AnalysisExecution { + return { + result: jsonValueSchema.parse(result), + rawResult: + options.rawResult === undefined + ? null + : jsonValueSchema.parse(options.rawResult), + provider, + ...(options.analysisProfile === undefined + ? {} + : { analysisProfile: structuredClone(options.analysisProfile) }), + limitations: [...(options.limitations ?? [])], + ...(options.relationshipCoverage === undefined + ? {} + : { + relationshipCoverage: relationshipCoverageSchema.parse( + options.relationshipCoverage, + ), + }), + locations: [...(options.locations ?? [])], + subject: options.subject ?? null, + }; +} /** Provider-neutral application capability for one analysis operation. */ export interface AnalysisOperationPort { diff --git a/src/application/CapabilityInventory.ts b/src/application/CapabilityInventory.ts index 88cfcdd6f..cf3d862dc 100644 --- a/src/application/CapabilityInventory.ts +++ b/src/application/CapabilityInventory.ts @@ -397,7 +397,7 @@ const workflowAvailabilityFor = ({ remediation: "On Linux x64, set absolute REA_PWNTOOLS_PYTHON to caller-supplied Python with pwntools 4.15.0. No active binary target is required.", }; - if (name === "inspect_packet_capture") + if (name === "inspect_packet_capture" || name === "inspect_packet_fields") return policy.packetCaptureEnabled === true ? { reason: "available", remediation: null } : { @@ -405,7 +405,7 @@ const workflowAvailabilityFor = ({ remediation: "On Linux, supply TShark 4.x via absolute REA_TSHARK_COMMAND and util-linux prlimit (REA_TSHARK_PRLIMIT_COMMAND, default /usr/bin/prlimit). No active binary target or hardware is required; the tool is checked at execution.", }; - if (name === "decode_signal_recording") + if (name === "decode_signal_recording" || name === "inspect_signal_decoders") return policy.signalRecordingEnabled === true ? { reason: "available", remediation: null } : { @@ -481,7 +481,7 @@ const workflowAvailabilityFor = ({ remediation: "Run process capture on a supported Linux or macOS host.", }; if (kind === "application") return { reason: "available", remediation: null }; - if (kind === "flutter-provider") + if (kind === "pcap-provider" || kind === "flutter-provider") return { reason: "available", remediation: null }; const electron = electronProviderAvailability(name, kind, policy); if (electron !== null) return electron; diff --git a/src/application/ClientRegistrationStatus.ts b/src/application/ClientRegistrationStatus.ts index e2696e088..caeba4fb6 100644 --- a/src/application/ClientRegistrationStatus.ts +++ b/src/application/ClientRegistrationStatus.ts @@ -7,6 +7,7 @@ import { clientServerForcedEnabled, clientServerListedDisabled, effectiveClientServer, + type ClientConfigurationDocument, } from "./ClientConfigurationDocument.js"; import { access } from "node:fs/promises"; import { resolve } from "node:path"; @@ -74,24 +75,48 @@ const registrationSchema = z }) .passthrough(); -/** Inspect supported client registrations without reading their environment. */ +interface ClientRegistrationReadOptions { + readonly platform?: NodeJS.Platform; + readonly environment?: NodeJS.ProcessEnv; + readonly resources?: ArtifactResourceScope; +} + +/** Registration facts shared by diagnostics and update maintenance. */ +export interface ClientRegistrationInspection { + readonly status: ClientRegistrationStatus; + readonly activation: "enabled" | "disabled" | "unknown"; +} + +/** Project diagnostics from the same inspection used to select maintenance. */ export const readClientRegistrationStatuses = async ( home: string, currentCommandPath: string = resolve(process.argv[1] ?? "unknown"), - options: { - readonly platform?: NodeJS.Platform; - readonly environment?: NodeJS.ProcessEnv; - readonly resources?: ArtifactResourceScope; - } = {}, -): Promise => { - const statuses: ClientRegistrationStatus[] = []; + options: ClientRegistrationReadOptions = {}, +): Promise => + ( + await readClientRegistrationInspections(home, currentCommandPath, options) + ).map(({ status }) => status); + +/** Parse effective registrations and their client-specific activation once. */ +export const readClientRegistrationInspections = async ( + home: string, + currentCommandPath: string = resolve(process.argv[1] ?? "unknown"), + options: ClientRegistrationReadOptions = {}, +): Promise => { + const inspections: ClientRegistrationInspection[] = []; + const record = ( + status: ClientRegistrationStatus, + activation: ClientRegistrationInspection["activation"] = "unknown", + ): void => { + inspections.push({ status, activation }); + }; for (const client of supportedClients( home, options.platform, options.environment, )) { if (client.configPathError !== undefined) { - statuses.push({ + record({ client: client.name, config_path: client.configPath, command: [], @@ -104,7 +129,7 @@ export const readClientRegistrationStatuses = async ( const manualRemediation = manualRegistrationRemediation(client.name); if (client.format === "unsupported") { if (manualRemediation !== undefined) - statuses.push({ + record({ client: client.name, config_path: client.markerPath ?? client.configPath, command: [], @@ -119,7 +144,7 @@ export const readClientRegistrationStatuses = async ( options.resources, ); if (!files.ok) { - statuses.push({ + record({ client: client.name, config_path: client.configPath, command: [], @@ -130,9 +155,7 @@ export const readClientRegistrationStatuses = async ( } const parsed = effectiveClientConfiguration(files.value); if (parsed === undefined) { - statuses.push( - unavailableStatus(client.name, client.configPath, "missing"), - ); + record(unavailableStatus(client.name, client.configPath, "missing")); continue; } const policy = await readClientPolicyBlock( @@ -142,7 +165,7 @@ export const readClientRegistrationStatuses = async ( options.resources, ); if (!policy.ok) { - statuses.push({ + record({ client: client.name, config_path: client.configPath, command: [], @@ -159,7 +182,7 @@ export const readClientRegistrationStatuses = async ( ? dshDocument(parsed.document).editabilityError : undefined; if (editabilityError !== undefined) { - statuses.push({ + record({ client: client.name, config_path: client.configPath, command: [], @@ -168,9 +191,7 @@ export const readClientRegistrationStatuses = async ( }); continue; } - statuses.push( - unavailableStatus(client.name, client.configPath, "missing"), - ); + record(unavailableStatus(client.name, client.configPath, "missing")); continue; } const registration = parseRegistration(raw, client); @@ -178,21 +199,18 @@ export const readClientRegistrationStatuses = async ( registration.command, ...registration.args, ]; - statuses.push( + const activation = registrationActivation(registration, client, parsed); + record( configuredStatus( client.name, client.configPath, command, - registrationAligned( - registration, - client, - currentCommandPath, - options.platform ?? process.platform, - clientServerForcedEnabled(parsed, PRODUCT_IDENTITY.mcpServerKey), - ) && - !clientServerListedDisabled( - parsed, - PRODUCT_IDENTITY.mcpServerKey, + activation === "enabled" && + registrationAligned( + registration, + client, + currentCommandPath, + options.platform ?? process.platform, ) && (parsed.dialect !== "dsh" || dshDocument(parsed.document).ready) && policyBlock === undefined @@ -200,9 +218,10 @@ export const readClientRegistrationStatuses = async ( : "stale", policyBlock, ), + activation, ); } catch (cause: unknown) { - statuses.push( + record( unavailableStatus( client.name, client.configPath, @@ -211,26 +230,31 @@ export const readClientRegistrationStatuses = async ( ); } } - return statuses.sort((left, right) => - compareUnicodeCodePoints(left.client, right.client), + return inspections.sort((left, right) => + compareUnicodeCodePoints(left.status.client, right.status.client), ); }; +const registrationActivation = ( + registration: z.output, + client: SetupClient, + parsed: ClientConfigurationDocument, +): "enabled" | "disabled" => + (client.format !== "grok" && registration.disabled === true) || + (registration.enabled === false && + !clientServerForcedEnabled(parsed, PRODUCT_IDENTITY.mcpServerKey)) || + (client.format === "zcode" && registration.enable === false) || + clientServerListedDisabled(parsed, PRODUCT_IDENTITY.mcpServerKey) + ? "disabled" + : "enabled"; + const registrationAligned = ( registration: z.output, client: SetupClient, currentCommandPath: string, platform: NodeJS.Platform, - forcedEnabled = false, ): boolean => { const command = [registration.command, ...registration.args]; - if ( - (client.format !== "grok" && registration.disabled === true) || - (registration.enabled === false && !forcedEnabled) || - // ZCode's native flag is `enable`; other dialects leave that field opaque. - (client.format === "zcode" && registration.enable === false) - ) - return false; if (!isOwnedClientRegistrationCommand(command, currentCommandPath)) return false; if ( diff --git a/src/application/EnhancedTools.ts b/src/application/EnhancedTools.ts index c8b80519f..87d27fc5f 100644 --- a/src/application/EnhancedTools.ts +++ b/src/application/EnhancedTools.ts @@ -21,8 +21,8 @@ import { parseFunctionDossier, parseListCount, parseRelatedAddresses, - parseSegmentImageBase, parseSegments, + parseSegmentImageBase, } from "../domain/hopperValues.js"; import { err, ok, type Result } from "../domain/result.js"; import { @@ -46,6 +46,7 @@ import { traceCallPath } from "./CallPathTracing.js"; import { resolveProcedureAddress } from "./ProcedureAddressResolution.js"; import { traceLiteralFeature } from "./EnhancedLiteralTracing.js"; import { projectNativeApiInspection } from "./native/NativeApiInspection.js"; + /** * Composes direct provider operations into bounded reverse-engineering tools. * Direct callers use `execute`; adapters that own validation use @@ -528,24 +529,29 @@ export class EnhancedTools { const segments = parseSegments(segmentsResult.value); if (!segments.ok) return segments; - const imageBase = parseSegmentImageBase(segmentsResult.value); const procedureCount = parseListCount(proceduresResult.value, "procedures"); if (!procedureCount.ok) return procedureCount; const stringCount = parseListCount(stringsResult.value, "strings"); if (!stringCount.ok) return stringCount; + const imageBase = parseSegmentImageBase(segments.value); + return ok({ document: document.value, - segments: segments.value.map(({ name, start, end }) => ({ - name, - start, - end, - length: addressDistance(start, end), - })), + ...(imageBase === undefined ? {} : { image_base: imageBase }), + segments: segments.value.map( + ({ name, start, end, image_base, address_space }) => ({ + name, + start, + end, + length: addressDistance(start, end), + ...(image_base === undefined ? {} : { image_base }), + ...(address_space === undefined ? {} : { address_space }), + }), + ), segment_count: segments.value.length, procedure_count: procedureCount.value, string_count: stringCount.value, - ...(imageBase === undefined ? {} : { image_base: imageBase }), }); } diff --git a/src/application/InvestigationProviders.ts b/src/application/InvestigationProviders.ts index 883d3878c..5dcb18150 100644 --- a/src/application/InvestigationProviders.ts +++ b/src/application/InvestigationProviders.ts @@ -18,11 +18,11 @@ export const workflowAnalysisProfile = ( ): AnalysisProfileCommitment => createAnalysisProfile(REA_WORKFLOW_PROVIDER, { upstream_analysis_profile: upstream, - ...(operation === "binary_overview" || - operation === "batch_decompile" || - operation === "get_call_graph" - ? { workflow_revision: 2 } - : {}), + ...(operation === "binary_overview" + ? { workflow_revision: 3 } + : operation === "batch_decompile" || operation === "get_call_graph" + ? { workflow_revision: 2 } + : {}), }); /** Provider identity for deterministic artifact inventories. */ diff --git a/src/application/JsonInputFile.ts b/src/application/JsonInputFile.ts index a226cb0cc..25e5fcec0 100644 --- a/src/application/JsonInputFile.ts +++ b/src/application/JsonInputFile.ts @@ -78,7 +78,9 @@ export const readJsonObjectFile = ( value === null || Array.isArray(value) ) - throw new TypeError("JSON document root must be an object"); + return err( + invalidJson(operation, "JSON document root must be an object"), + ); for (const members of scans) for (const [key, member] of members) { if (!Object.hasOwn(value, key)) continue; @@ -177,7 +179,9 @@ export const readJsonObjectFile = ( signal === undefined ? {} : { signal }, ); if (!rootObject) - throw new TypeError("JSON document root must be an object"); + return err( + invalidJson(operation, "JSON document root must be an object"), + ); const digest = hash.digest("hex"); if (previousDigest !== undefined && digest !== previousDigest) throw new RegularFileChangedError(path); diff --git a/src/application/MacHopper.test.ts b/src/application/MacHopper.test.ts index d75959fd5..7896208c5 100644 --- a/src/application/MacHopper.test.ts +++ b/src/application/MacHopper.test.ts @@ -2,12 +2,16 @@ import { createHash } from "node:crypto"; import { describe, expect, it } from "vitest"; -import { installMacHopper, type MacHopperInstallHost } from "./MacHopper.js"; +import { + installMacHopper, + type MacHopperBundleVerification, + type MacHopperInstallHost, +} from "./MacHopper.js"; class FakeMacHopperHost implements MacHopperInstallHost { readonly archive = new TextEncoder().encode("hopper-dmg"); archiveOk = true; - valid = true; + verification: MacHopperBundleVerification = "verified"; existing = false; mountSucceeds = true; copySucceeds = true; @@ -15,6 +19,7 @@ class FakeMacHopperHost implements MacHopperInstallHost { badHash = false; unmounts = 0; cleanups = 0; + installs = 0; opens = 0; replaces = false; @@ -47,7 +52,7 @@ class FakeMacHopperHost implements MacHopperInstallHost { return Promise.resolve(); }; appBundle = () => Promise.resolve("/mounted/Hopper Disassembler.app"); - validBundle = () => Promise.resolve(this.valid); + validBundle = () => Promise.resolve(this.verification); destinationExists = () => Promise.resolve(this.existing); installBundle = ( _source: string, @@ -55,6 +60,7 @@ class FakeMacHopperHost implements MacHopperInstallHost { _stage: string, replaceExisting: boolean, ) => { + this.installs += 1; this.replaces = replaceExisting; return Promise.resolve(this.copySucceeds); }; @@ -115,7 +121,7 @@ describe("macOS Hopper installation", () => { it("cleans and detaches after bundle validation fails", async () => { const host = new FakeMacHopperHost(); - host.valid = false; + host.verification = "invalid_signature"; await expect(installMacHopper({}, host)).resolves.toEqual({ status: "failed", reason: "bundle", @@ -123,4 +129,17 @@ describe("macOS Hopper installation", () => { expect(host.unmounts).toBe(1); expect(host.cleanups).toBe(1); }); + + it("reports a publisher mismatch without copying or launching the bundle", async () => { + const host = new FakeMacHopperHost(); + host.verification = "unverified_publisher"; + await expect(installMacHopper({}, host)).resolves.toEqual({ + status: "failed", + reason: "publisher_verification_failed", + }); + expect(host.installs).toBe(0); + expect(host.opens).toBe(0); + expect(host.unmounts).toBe(1); + expect(host.cleanups).toBe(1); + }); }); diff --git a/src/application/MacHopper.ts b/src/application/MacHopper.ts index 31ca522f4..a211e9f2d 100644 --- a/src/application/MacHopper.ts +++ b/src/application/MacHopper.ts @@ -24,7 +24,35 @@ const execFileAsync = promisify(execFile); const RELEASES_URL = "https://www.hopperapp.com/include/files-api.php?request=releases&public=true"; const DOWNLOAD_PREFIX = "https://www.hopperapp.com:443/downloader/public/"; -const BUNDLE_IDENTIFIER = "com.cryptic-apps.hopper-web-4"; + +/** + * Apple publisher identity pinned for the official Hopper macOS bundle. The + * team identifier was captured from `Hopper-6.6.0-demo.dmg` at + * `https://www.hopperapp.com:443/downloader/public/Hopper-6.6.0-demo.dmg` + * (34846271 bytes, SHA-1 0be530f038249742590992199c7b042ea20ca955) with + * `codesign -dvvv`, which reported + * `Authority=Developer ID Application: Cryptic Apps (2AMA2753NF)`. + */ +export const HOPPER_PUBLISHER = Object.freeze({ + bundleIdentifier: "com.cryptic-apps.hopper-web-4", + teamIdentifier: "2AMA2753NF", +}); + +/** + * Code requirement enforcing the bundle identifier and signing team together. + * The identifier is read from the sealed CodeDirectory, so it cannot be changed + * by editing `Info.plist` the way the previous string comparison could. + */ +const HOPPER_PUBLISHER_REQUIREMENT = + `= identifier "${HOPPER_PUBLISHER.bundleIdentifier}"` + + ` and anchor apple generic` + + ` and certificate leaf[subject.OU] = "${HOPPER_PUBLISHER.teamIdentifier}"`; + +/** Outcome of reading a mounted bundle's signature and publisher identity. */ +export type MacHopperBundleVerification = + | "verified" + | "invalid_signature" + | "unverified_publisher"; /** Stable network and command effects disclosed before macOS Hopper setup. */ export const macHopperInstallDisclosure = { @@ -32,6 +60,7 @@ export const macHopperInstallDisclosure = { commands: [ "hdiutil attach -readonly -nobrowse -mountpoint ", "codesign --verify --deep --strict ", + `codesign --verify --strict '-R${HOPPER_PUBLISHER_REQUIREMENT}' `, "ditto ", "open ", ] as const, @@ -52,6 +81,7 @@ export type MacHopperInstallResult = | "integrity" | "mount" | "bundle" + | "publisher_verification_failed" | "destination_exists" | "copy" | "launcher_missing"; @@ -69,7 +99,7 @@ export interface MacHopperInstallHost { mount(packagePath: string, mountPath: string): Promise; unmount(mountPath: string): Promise; appBundle(mountPath: string): Promise; - validBundle(appPath: string): Promise; + validBundle(appPath: string): Promise; destinationExists(path: string): Promise; installBundle( source: string, @@ -124,8 +154,12 @@ export const installMacHopper = async ( return { status: "failed", reason: "mount" }; mounted = true; const source = await host.appBundle(mountPath); - if (source === undefined || !(await host.validBundle(source))) + if (source === undefined) return { status: "failed", reason: "bundle" }; + const verification = await host.validBundle(source); + if (verification === "invalid_signature") return { status: "failed", reason: "bundle" }; + if (verification === "unverified_publisher") + return { status: "failed", reason: "publisher_verification_failed" }; const stage = `${destination}.rea-stage`; if ( !(await host.installBundle( @@ -222,25 +256,21 @@ export const systemMacHopperInstallHost = ( environment, )) ) - return false; - try { - const identifier = ( - await execFileAsync( - "/usr/libexec/PlistBuddy", - [ - "-c", - "Print :CFBundleIdentifier", - join(appPath, "Contents/Info.plist"), - ], - { env: environment }, - ) - ).stdout.trim(); - return identifier === BUNDLE_IDENTIFIER; - } catch (cause: unknown) { - // best-effort cleanup: optional bundle probing; unreadable means invalid. - void cause; - return false; - } + return "invalid_signature"; + if ( + !(await commandSucceeds( + "codesign", + [ + "--verify", + "--strict", + `-R${HOPPER_PUBLISHER_REQUIREMENT}`, + appPath, + ], + environment, + )) + ) + return "unverified_publisher"; + return "verified"; }, async destinationExists(path) { try { diff --git a/src/application/ProgressReporter.ts b/src/application/ProgressReporter.ts index cf5ed7b7f..bb5a98f0d 100644 --- a/src/application/ProgressReporter.ts +++ b/src/application/ProgressReporter.ts @@ -23,7 +23,7 @@ export const createProgressReporter = ( } = {}, ): ProgressReporter => { const minimumIntervalMs = options.minimumIntervalMs ?? 100; - const now = options.now ?? Date.now; + const now = options.now ?? (() => performance.now()); let lastCompleted = -1; let lastSentAt = Number.NEGATIVE_INFINITY; let sequence = 0; diff --git a/src/application/ReferenceSourceImportEntries.ts b/src/application/ReferenceSourceImportEntries.ts index 3254d7cfb..36dae9949 100644 --- a/src/application/ReferenceSourceImportEntries.ts +++ b/src/application/ReferenceSourceImportEntries.ts @@ -12,12 +12,14 @@ import { detectReferenceSourceLanguage, } from "../domain/referenceSourceClassification.js"; import type { HistoricalSourceGraphInput } from "../domain/referenceSourceGraph.js"; -import { parseReferenceSourceImports } from "../domain/referenceSourceImportParsing.js"; +import { + parseReferenceSourceImports, + PARSEABLE_REFERENCE_SOURCE_LANGUAGES, +} from "../domain/referenceSourceImportParsing.js"; import type { ReferenceSourceEntry, ReferenceSourceRead, } from "../reference/ReferenceSourceReaderTypes.js"; -import { PARSEABLE_REFERENCE_SOURCE_LANGUAGES } from "./ReferenceSourceImportTypes.js"; import { typescriptEmittedSourceCandidates } from "./TypeScriptEmittedSourceCandidates.js"; export interface ParsedReferenceSourceEntries { @@ -102,7 +104,11 @@ const resolveInternalSpecifier = ( ]); // Retain present runtime files first; substitute only a missing counterpart. // Counterparts cover explicit filenames, not directory/index resolution. - candidates.push(...typescriptEmittedSourceCandidates(fromPath, normalized)); + candidates.push( + ...typescriptEmittedSourceCandidates(fromPath, normalized).map( + ({ path }) => path, + ), + ); const match = lookupPath.resolveCandidates(candidates); return match === undefined ? { to: normalized, resolution: "unresolved" } diff --git a/src/application/ReferenceSourceImportTypes.ts b/src/application/ReferenceSourceImportTypes.ts index 9395dc5c0..f8474315a 100644 --- a/src/application/ReferenceSourceImportTypes.ts +++ b/src/application/ReferenceSourceImportTypes.ts @@ -87,6 +87,3 @@ export const DEFAULT_REFERENCE_SOURCE_IGNORE_PATTERNS = [ ".coverage", "*.log", ] as const; - -export const PARSEABLE_REFERENCE_SOURCE_LANGUAGES: ReadonlySet = - new Set(["JavaScript", "TypeScript", "JSX", "TSX"]); diff --git a/src/application/RegularFileRead.ts b/src/application/RegularFileRead.ts index f09f4c192..ee4d6170a 100644 --- a/src/application/RegularFileRead.ts +++ b/src/application/RegularFileRead.ts @@ -19,6 +19,17 @@ export interface RegularFileReadOptions { readonly resources?: ArtifactResourceScope; } +export class InvalidUtf8FileError extends TypeError { + readonly _tag = "InvalidUtf8FileError"; + constructor( + readonly path: string, + cause: unknown, + ) { + super(`File is not valid UTF-8: ${path}`, { cause }); + this.name = this._tag; + } +} + export type RegularFileReadOutcome = | { readonly kind: "completed"; readonly value: Value } | { readonly kind: "failed"; readonly cause: unknown }; @@ -142,7 +153,34 @@ const withRegularFileOwned = async ( export const readRegularFile = ( path: string, options: RegularFileReadOptions = {}, -): Promise => +): Promise => readRegularFileContent(path, (bytes) => bytes, options); + +/** Read valid UTF-8 without replacing source bytes or stripping an initial BOM. */ +export const readRegularFileText = ( + path: string, + options: RegularFileReadOptions = {}, +): Promise => + readRegularFileContent( + path, + (bytes) => { + try { + return new TextDecoder("utf-8", { + fatal: true, + ignoreBOM: true, + }).decode(bytes); + } catch (cause: unknown) { + if (!(cause instanceof TypeError)) throw cause; + throw new InvalidUtf8FileError(path, cause); + } + }, + options, + ); + +const readRegularFileContent = ( + path: string, + decode: (bytes: Buffer) => Value, + options: RegularFileReadOptions, +): Promise => withRegularFile( path, async (handle, stats) => { @@ -153,30 +191,7 @@ export const readRegularFile = ( ); if (bytes === undefined || bytes.length !== stats.size) throw new RegularFileChangedError(path); - return bytes; + return decode(bytes); }, options, ); - -/** Read one admitted regular file as UTF-8 without waiting on a pipe. */ -export const readRegularFileText = async ( - path: string, - options: RegularFileReadOptions = {}, -): Promise => { - try { - return (await readRegularFile(path, options)).toString("utf8"); - } catch (cause: unknown) { - if ( - cause instanceof RegularFileCleanupFailure && - cause.outcome.kind === "completed" && - Buffer.isBuffer(cause.outcome.value) - ) - throw new RegularFileCleanupFailure( - cause.path, - cause.owner, - { kind: "completed", value: cause.outcome.value.toString("utf8") }, - cause.cleanupCause, - ); - throw cause; - } -}; diff --git a/src/application/Setup.recovery.test.ts b/src/application/Setup.recovery.test.ts index 951ef3a54..f29c9d375 100644 --- a/src/application/Setup.recovery.test.ts +++ b/src/application/Setup.recovery.test.ts @@ -54,6 +54,40 @@ describe("setup workflow", () => { expect(result.remediation).toContain("could not be updated"); }); + it("reports a failed config rollback with its destination and recovery backup", async () => { + const host = new FakeSetupHost(); + host.hopper = "/Applications/Hopper"; + host.clients = [{ name: "codex", configPath: "/fixture/codex.json" }]; + host.clientResults.set("codex", { + status: "failed", + reason: "rollback", + backupPath: "/fixture/codex.json.rea.backup", + failure: { + kind: "restore", + path: "/fixture/codex.json", + detail: "permission denied", + }, + }); + + const result = await runSetup( + { ...options(true), clientIds: ["codex"] }, + host, + ); + + expect(result.clients.codex).toEqual({ + status: "failed", + reason: "rollback", + backupPath: "/fixture/codex.json.rea.backup", + failure: { + kind: "restore", + path: "/fixture/codex.json", + detail: "permission denied", + }, + }); + expect(result.remediation).toContain("permission denied"); + expect(result.remediation).toContain("/fixture/codex.json.rea.backup"); + }); + it("explains skill installation recovery", async () => { const host = new FakeSetupHost(); host.hopper = "/Applications/Hopper"; diff --git a/src/application/SetupClientConfiguration.ts b/src/application/SetupClientConfiguration.ts index bfab80cbf..981b829a4 100644 --- a/src/application/SetupClientConfiguration.ts +++ b/src/application/SetupClientConfiguration.ts @@ -19,6 +19,7 @@ import { } from "./ClientConfigurationDocument.js"; import { dshDocument, DshCordisDocument } from "./DshCordisPatch.js"; import { constants as fsConstants } from "node:fs"; +import { createHash } from "node:crypto"; import { copyFile, mkdir, rm, writeFile } from "node:fs/promises"; import { dirname } from "node:path"; import writeFileAtomic from "write-file-atomic"; @@ -29,6 +30,7 @@ import { npxRegistrationCommand } from "./ClientRegistrationIdentity.js"; import { MCP_STARTUP_POLICY } from "../mcpStartupPolicy.js"; import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js"; import { + readRegularFile, readRegularFileText, RegularFileCleanupFailure, } from "./RegularFileRead.js"; @@ -40,6 +42,26 @@ import type { } from "./SetupTypes.js"; import type { SetupClient } from "./SupportedClients.js"; +export class ClientConfigurationCleanupRollbackFailure extends RegularFileCleanupFailure { + constructor( + failure: RegularFileCleanupFailure, + readonly configurationFailure: Extract< + ClientConfigurationResult, + { readonly status: "failed"; readonly reason: "rollback" } + >, + ) { + super( + failure.path, + failure.owner, + failure.outcome, + new AggregateError( + [failure.cleanupCause, new Error(configurationFailure.failure.detail)], + `Configuration readback cleanup and rollback failed: ${configurationFailure.failure.path}`, + ), + ); + } +} + /** Configure one supported client's native stdio MCP registration shape. */ export const configureClientConfiguration = ( client: SetupClient, @@ -167,11 +189,23 @@ const persistClientConfiguration = async ({ }: ClientConfigurationUpdate): Promise => { const backupPath = original === undefined ? undefined : `${client.configPath}.rea.backup`; - if ( - backupPath !== undefined && - !(await preserveConfigBackup(transactionPath, backupPath)) - ) - return { status: "failed", reason: "backup" }; + let recoveryBackupPath: string | undefined; + if (backupPath !== undefined && original !== undefined) { + const selection = await selectCurrentRecoveryBackup(backupPath, original); + if (!selection.ok) return { status: "failed", reason: "backup" }; + if ( + !(await preserveConfigBackup(transactionPath, selection.value.backupPath)) + ) + return { status: "failed", reason: "backup" }; + const verified = await selectCurrentRecoveryBackup(backupPath, original); + if ( + !verified.ok || + verified.value.backupPath !== selection.value.backupPath || + !verified.value.present + ) + return { status: "failed", reason: "backup" }; + recoveryBackupPath = verified.value.backupPath; + } // A native OpenCode V2 entry replaces REA's legacy V1 entry, which would // otherwise conflict with it. const legacyPath = legacyClientServerPath( @@ -239,19 +273,39 @@ const persistClientConfiguration = async ({ !clientConfigurationValuesEqual(readback.servers[name], entry), ) ) { - await restoreConfig(transactionPath, original); - return { status: "failed", reason: "readback" }; + return rollbackOrReadbackFailure( + transactionPath, + original, + recoveryBackupPath, + ); } } catch (cause: unknown) { - if (cause instanceof RegularFileCleanupFailure) throw cause; + if (cause instanceof RegularFileCleanupFailure) { + const rollback = await restoreConfig(transactionPath, original); + if (!rollback.ok) + throw new ClientConfigurationCleanupRollbackFailure(cause, { + status: "failed", + reason: "rollback", + ...(recoveryBackupPath === undefined + ? {} + : { backupPath: recoveryBackupPath }), + failure: rollback.error, + }); + throw cause; + } // Readback failure restores the transaction before reporting. void cause; - await restoreConfig(transactionPath, original); - return { status: "failed", reason: "readback" }; + return rollbackOrReadbackFailure( + transactionPath, + original, + recoveryBackupPath, + ); } return { status: "configured", - ...(backupPath === undefined ? {} : { backupPath }), + ...(recoveryBackupPath === undefined + ? {} + : { backupPath: recoveryBackupPath }), }; }; @@ -406,9 +460,18 @@ export const inspectClientConfiguration = async ( "The existing configuration is malformed. Repair it before setup applies any other changes.", }; } + const backupSelection = await selectCurrentRecoveryBackup( + `${client.configPath}.rea.backup`, + original, + ); + if (!backupSelection.ok) + return { + status: "invalid", + remediation: backupSelection.error.detail, + }; return { status: "update", - backupPath: `${client.configPath}.rea.backup`, + backupPath: backupSelection.value.backupPath, }; }; @@ -473,19 +536,101 @@ const preserveConfigBackup = async ( } }; +interface RecoveryBackupSelection { + readonly backupPath: string; + readonly present: boolean; +} + +interface RecoveryBackupSelectionFailure { + readonly kind: "unreadable" | "occupied"; + readonly path: string; + readonly detail: string; +} + +const selectCurrentRecoveryBackup = async ( + firstBackupPath: string, + original: string, +): Promise> => { + const expected = Buffer.from(original, "utf8"); + let firstBackup: Buffer | undefined; + try { + firstBackup = await readRegularFile(firstBackupPath, { + symlinks: "reject", + }); + } catch (cause: unknown) { + if (cause instanceof RegularFileCleanupFailure) throw cause; + if (!isMissing(cause)) + return err({ + kind: "unreadable", + path: firstBackupPath, + detail: `The recovery backup could not be checked: ${errorDetail(cause)}`, + }); + } + if (firstBackup === undefined) + return ok({ backupPath: firstBackupPath, present: false }); + if (firstBackup.equals(expected)) + return ok({ backupPath: firstBackupPath, present: true }); + + const digest = createHash("sha256").update(original, "utf8").digest("hex"); + const recoveryPath = `${firstBackupPath}.${digest}.recovery`; + let recovery: Buffer | undefined; + try { + recovery = await readRegularFile(recoveryPath, { symlinks: "reject" }); + } catch (cause: unknown) { + if (cause instanceof RegularFileCleanupFailure) throw cause; + if (!isMissing(cause)) + return err({ + kind: "unreadable", + path: recoveryPath, + detail: `The recovery backup could not be checked: ${errorDetail(cause)}`, + }); + } + if (recovery !== undefined && !recovery.equals(expected)) + return err({ + kind: "occupied", + path: recoveryPath, + detail: `The recovery path already contains different data: ${recoveryPath}`, + }); + return ok({ backupPath: recoveryPath, present: recovery !== undefined }); +}; + const restoreConfig = async ( path: string, original: string | undefined, -): Promise => { +): Promise< + Result< + void, + { readonly kind: "restore"; readonly path: string; readonly detail: string } + > +> => { try { if (original === undefined) await rm(path, { force: true }); else await writeFile(path, original, { encoding: "utf8", mode: 0o600 }); + return ok(undefined); } catch (cause: unknown) { - // The backup remains available for the remediation reported by setup. - void cause; + return err({ kind: "restore", path, detail: errorDetail(cause) }); } }; +const rollbackOrReadbackFailure = async ( + targetPath: string, + original: string | undefined, + backupPath: string | undefined, +): Promise => { + const rollback = await restoreConfig(targetPath, original); + return rollback.ok + ? { status: "failed", reason: "readback" } + : { + status: "failed", + reason: "rollback", + ...(backupPath === undefined ? {} : { backupPath }), + failure: rollback.error, + }; +}; + +const errorDetail = (cause: unknown): string => + cause instanceof Error ? cause.message : String(cause); + /** Whether REA's entry matches, no legacy entry remains, and no client disable list suppresses it. */ const registrationCurrent = ( parsed: ClientConfigurationDocument, diff --git a/src/application/SetupClients.ts b/src/application/SetupClients.ts index bbeeedf3f..d86d04b9e 100644 --- a/src/application/SetupClients.ts +++ b/src/application/SetupClients.ts @@ -6,15 +6,19 @@ import type { } from "./SetupTypes.js"; import type { SetupClient } from "./SupportedClients.js"; -const failedConfigurationMessage = ( - reason: "path" | "backup" | "write" | "readback", +export const failedConfigurationMessage = ( + result: Extract, ): string => { - if (reason === "path") + if (result.reason === "path") return "Agent configuration path could not be safely verified. Check its permissions and, if it is a symbolic link, verify that the link resolves to a regular file owned by the current user, then rerun setup."; - if (reason === "backup") + if (result.reason === "backup") return "Agent configuration could not be backed up, so no change was made. Check file permissions, then rerun setup."; - if (reason === "write") + if (result.reason === "write") return "Agent configuration could not be updated. Check file permissions, then rerun setup."; + if (result.reason === "rollback") + return result.backupPath === undefined + ? `Agent configuration rollback failed at ${result.failure.path}: ${result.failure.detail}; the failed first-run file may remain. Remove or repair it before rerunning setup.` + : `Agent configuration rollback failed at ${result.failure.path}: ${result.failure.detail}. Inspect the preserved backup at ${result.backupPath} and restore the intended configuration, then rerun setup.`; return "Agent configuration could not be verified after writing. Repair the configuration file or restore its `.rea.backup`, then rerun setup."; }; @@ -40,12 +44,12 @@ export const configureDetectedClients = async (options: { ); options.clients[client.name] = result; if (result.status === "failed") { - failure ??= failedConfigurationMessage(result.reason); + failure ??= failedConfigurationMessage(result); options.onProgress?.({ actionId, label, state: "failed", - detail: failedConfigurationMessage(result.reason), + detail: failedConfigurationMessage(result), }); } else if (result.status === "configured") { options.appliedActions.push(`configured_${client.name}`); diff --git a/src/application/SetupHost.ts b/src/application/SetupHost.ts index 9e2ae95f1..7ac6828fd 100644 --- a/src/application/SetupHost.ts +++ b/src/application/SetupHost.ts @@ -33,9 +33,11 @@ import { } from "./SetupSkill.js"; import { clientConfigurationAligned, + ClientConfigurationCleanupRollbackFailure, configureClientConfiguration, inspectClientConfiguration, } from "./SetupClientConfiguration.js"; +import { failedConfigurationMessage } from "./SetupClients.js"; import { setupInstallFailure } from "./SetupInstallFailure.js"; import { RegularFileCleanupFailure, @@ -275,8 +277,12 @@ const runClientConfigurationOperation = async ( cleanup.outcome.kind === "failed" ? cleanup.outcome.cause : cause.cleanupCause; + const rollbackMessage = + cause instanceof ClientConfigurationCleanupRollbackFailure + ? ` ${failedConfigurationMessage(cause.configurationFailure)}` + : ""; throw configurationCleanupError( - `Could not safely access client configuration at ${cause.path}: ${errorMessage(primary)}`, + `Could not safely access client configuration at ${cause.path}: ${errorMessage(primary)}.${rollbackMessage}`, cause, cleanup.cleanup, ); diff --git a/src/application/SetupInstallFailure.test.ts b/src/application/SetupInstallFailure.test.ts new file mode 100644 index 000000000..980e22151 --- /dev/null +++ b/src/application/SetupInstallFailure.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; + +import { HOPPER_PUBLISHER } from "./MacHopper.js"; +import { setupInstallFailure } from "./SetupInstallFailure.js"; + +describe("macOS Hopper setup failure projection", () => { + it("projects a publisher mismatch onto its own code and recovery", () => { + expect(setupInstallFailure("publisher_verification_failed")).toEqual({ + status: "failed", + code: "publisher_verification_failed", + remediation: `The mounted Hopper application is not signed by the publisher REA pins (${HOPPER_PUBLISHER.bundleIdentifier}, Apple team ${HOPPER_PUBLISHER.teamIdentifier}); nothing was copied or launched. Install Hopper yourself and set HOPPER_LAUNCHER_PATH to its launcher, then rerun rea setup.`, + }); + }); + + it("keeps a broken bundle distinct from a publisher mismatch", () => { + expect(setupInstallFailure("bundle")).toEqual({ + status: "failed", + code: "bundle_invalid", + remediation: + "The mounted package did not contain the expected Hopper application bundle. Retry setup; if it repeats, update REA before installing.", + }); + }); +}); diff --git a/src/application/SetupInstallFailure.ts b/src/application/SetupInstallFailure.ts index fe2a2739e..0b332fa25 100644 --- a/src/application/SetupInstallFailure.ts +++ b/src/application/SetupInstallFailure.ts @@ -1,3 +1,5 @@ +import { HOPPER_PUBLISHER } from "./MacHopper.js"; + export type SetupFailureCode = | "unsupported_host" | "download_failed" @@ -10,6 +12,7 @@ export type SetupFailureCode = | "destination_exists" | "mount_failed" | "bundle_invalid" + | "publisher_verification_failed" | "copy_failed" | "skill_install_failed" | "cleanup_failed"; @@ -39,6 +42,7 @@ export type HopperInstallFailureReason = | "destination_exists" | "mount" | "bundle" + | "publisher_verification_failed" | "copy"; /** Map provider installer failures to stable setup codes and safe recovery. */ @@ -115,6 +119,12 @@ export const setupInstallFailure = ( remediation: "The mounted package did not contain the expected Hopper application bundle. Retry setup; if it repeats, update REA before installing.", }; + case "publisher_verification_failed": + return { + status: "failed", + code: "publisher_verification_failed", + remediation: `The mounted Hopper application is not signed by the publisher REA pins (${HOPPER_PUBLISHER.bundleIdentifier}, Apple team ${HOPPER_PUBLISHER.teamIdentifier}); nothing was copied or launched. Install Hopper yourself and set HOPPER_LAUNCHER_PATH to its launcher, then rerun rea setup.`, + }; case "copy": return { status: "failed", diff --git a/src/application/SetupPlan.ts b/src/application/SetupPlan.ts index 83402d1a4..a78697c80 100644 --- a/src/application/SetupPlan.ts +++ b/src/application/SetupPlan.ts @@ -320,5 +320,5 @@ const clientConfigurationDetail = ( ? " If this plan installs Hopper, REA will add HOPPER_LAUNCHER_PATH using the launcher path reported by that installation." : " The HOPPER_LAUNCHER_PATH value shown above is the current fallback; if this plan installs Hopper, REA will replace it with the launcher path reported by that installation." : ""; - return `Add the REA MCP registration for ${client}; preserve unrelated configuration. Command: ${command.map((part) => JSON.stringify(part)).join(" ")}.${environmentDetail}${hopperDetail}`; + return `Add the REA MCP registration for ${client}; preserve unrelated configuration. The backup path reflects the configuration inspected for this plan; if that file changes before execution, setup will select a recovery path for its current contents. Command: ${command.map((part) => JSON.stringify(part)).join(" ")}.${environmentDetail}${hopperDetail}`; }; diff --git a/src/application/SetupTypes.ts b/src/application/SetupTypes.ts index da58abbff..241e0f6dd 100644 --- a/src/application/SetupTypes.ts +++ b/src/application/SetupTypes.ts @@ -26,6 +26,16 @@ export type ClientConfigurationResult = | { readonly status: "failed"; readonly reason: "path" | "backup" | "write" | "readback"; + } + | { + readonly status: "failed"; + readonly reason: "rollback"; + readonly backupPath?: string; + readonly failure: { + readonly kind: "restore"; + readonly path: string; + readonly detail: string; + }; }; /** Read-only state used to block unsafe setup plans before any mutation. */ diff --git a/src/application/TypeScriptEmittedSourceCandidates.ts b/src/application/TypeScriptEmittedSourceCandidates.ts index 663c7dada..0e7adf41c 100644 --- a/src/application/TypeScriptEmittedSourceCandidates.ts +++ b/src/application/TypeScriptEmittedSourceCandidates.ts @@ -8,6 +8,11 @@ const EMITTED_SUFFIXES: ReadonlyArray< [".jsx", [".tsx", ".d.ts"]], ]; +export interface TypeScriptEmittedSourceCandidate { + readonly path: string; + readonly kind: "implementation" | "declaration"; +} + /** * Return TypeScript source counterparts for an explicit emitted filename. * Callers retain exact runtime-file precedence and must not use these for @@ -16,7 +21,7 @@ const EMITTED_SUFFIXES: ReadonlyArray< export const typescriptEmittedSourceCandidates = ( sourcePath: string, candidate: string, -): readonly string[] => { +): readonly TypeScriptEmittedSourceCandidate[] => { if (!/\.(?:ts|tsx|mts|cts)$/u.test(sourcePath)) return []; const emitted = EMITTED_SUFFIXES.find(([suffix]) => candidate.endsWith(suffix), @@ -25,5 +30,8 @@ export const typescriptEmittedSourceCandidates = ( // Strip the matched suffix by length. posix.extname would miss dotfile // names such as ".js", whose whole basename is the emitted suffix itself. const stem = candidate.slice(0, candidate.length - emitted[0].length); - return emitted[1].map((suffix) => `${stem}${suffix}`); + return emitted[1].map((suffix) => ({ + path: `${stem}${suffix}`, + kind: suffix.startsWith(".d.") ? "declaration" : "implementation", + })); }; diff --git a/src/application/Uninstall.ts b/src/application/Uninstall.ts index c410280bc..a7f051a49 100644 --- a/src/application/Uninstall.ts +++ b/src/application/Uninstall.ts @@ -25,7 +25,11 @@ import { import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js"; import { dshDocument } from "./DshCordisPatch.js"; import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js"; -import { readRegularFileText } from "./RegularFileRead.js"; +import { + InvalidUtf8FileError, + RegularFileCleanupFailure, + readRegularFileText, +} from "./RegularFileRead.js"; import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; import { manualRegistrationRemediation, @@ -269,13 +273,17 @@ const readClientConfiguration = async ( try { original = await fileSystem.readText(transactionPath); } catch (cause: unknown) { + const readFailure = + cause instanceof RegularFileCleanupFailure ? cause.cause : cause; return itemRead( isMissing(cause) ? item(client.name, "skipped", "Configuration does not exist.") : item( client.name, "failed", - "Configuration could not be read. Check file permissions, then rerun uninstall.", + readFailure instanceof InvalidUtf8FileError + ? "Configuration is not valid UTF-8 and was not changed. Repair it, then rerun uninstall." + : "Configuration could not be read. Check file permissions, then rerun uninstall.", ), ); } diff --git a/src/application/UpdateMaintenance.ts b/src/application/UpdateMaintenance.ts index 06ac1b512..fd55c8f23 100644 --- a/src/application/UpdateMaintenance.ts +++ b/src/application/UpdateMaintenance.ts @@ -1,19 +1,10 @@ import { z } from "zod"; -import { PRODUCT_IDENTITY } from "../identity.js"; import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js"; -import { readClientRegistrationStatuses } from "./ClientRegistrationStatus.js"; -import { - clientServerForcedEnabled, - clientServerListedDisabled, - effectiveClientServer, - parseClientConfiguration, -} from "./ClientConfigurationDocument.js"; -import { supportedClients } from "./SupportedClients.js"; +import { readClientRegistrationInspections } from "./ClientRegistrationStatus.js"; import { existingSkillDestinations } from "./SetupSkill.js"; import type { SetupAction } from "./SetupTypes.js"; import type { Result } from "../domain/result.js"; -import { readRegularFileText } from "./RegularFileRead.js"; import type { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; /** Existing REA integrations selected for maintenance, without discovering new targets. */ @@ -61,41 +52,23 @@ export const existingMaintenanceScope = async ( environment: Readonly, resources?: ArtifactResourceScope, ): Promise => { - const registrations = await readClientRegistrationStatuses(home, entryPoint, { - environment, - ...(resources === undefined ? {} : { resources }), - }); - const supported = supportedClients(home, process.platform, environment); + const registrations = await readClientRegistrationInspections( + home, + entryPoint, + { + environment, + ...(resources === undefined ? {} : { resources }), + }, + ); const clients: string[] = []; - for (const registration of registrations) { + for (const { status: registration, activation } of registrations) { if ( + activation !== "enabled" || (registration.state !== "aligned" && registration.state !== "stale") || !isOwnedClientRegistrationCommand(registration.command, entryPoint) ) continue; - const client = supported.find(({ name }) => name === registration.client); - if (client === undefined) continue; - const parsed = parseClientConfiguration( - await readRegularFileText( - client.configPath, - resources === undefined ? {} : { resources }, - ), - client.format, - ); - const enabled = z - .object({ - enabled: z.boolean().optional(), - disabled: z.boolean().optional(), - }) - .parse(effectiveClientServer(parsed, PRODUCT_IDENTITY.mcpServerKey)); - // Root disable lists override enabled entries and OMP's force-on allowlist. - if ( - (enabled.enabled !== false || - clientServerForcedEnabled(parsed, PRODUCT_IDENTITY.mcpServerKey)) && - enabled.disabled !== true && - !clientServerListedDisabled(parsed, PRODUCT_IDENTITY.mcpServerKey) - ) - clients.push(client.name); + clients.push(registration.client); } const skillDestinations = await existingSkillDestinations( home, diff --git a/src/application/WebModulePorts.ts b/src/application/WebModulePorts.ts index 81c94a161..2f03efce0 100644 --- a/src/application/WebModulePorts.ts +++ b/src/application/WebModulePorts.ts @@ -22,6 +22,7 @@ export interface WebModuleArtifacts extends SelectedWebScriptArtifacts { /** Read selected local artifacts without refetching website assets. */ export interface WebModuleArtifactPort { + close?(): Promise; load( input: WebModuleTraceInput, options?: ExecutionOptions, diff --git a/src/application/WebModuleTraceService.ts b/src/application/WebModuleTraceService.ts index f8aa0f8b9..be0936e1c 100644 --- a/src/application/WebModuleTraceService.ts +++ b/src/application/WebModuleTraceService.ts @@ -1,3 +1,4 @@ +import { closeOwnedWebResources } from "./closeOwnedWebResources.js"; import { isAbsolute } from "node:path"; import { z } from "zod"; import type { AnalysisError } from "../domain/analysisErrorBase.js"; @@ -70,7 +71,13 @@ export class WebModuleTraceService { ) {} close(): Promise { - return this.resolver.close?.() ?? Promise.resolve(); + return closeOwnedWebResources( + [ + this.artifacts.close?.bind(this.artifacts), + this.resolver.close?.bind(this.resolver), + ], + "Web module trace cleanup failed", + ); } async trace( diff --git a/src/application/WebNetworkCapturePort.ts b/src/application/WebNetworkCapturePort.ts index 5f9cd5545..2bd0f1968 100644 --- a/src/application/WebNetworkCapturePort.ts +++ b/src/application/WebNetworkCapturePort.ts @@ -12,4 +12,6 @@ export interface WebNetworkCapturePort { input: InspectWebNetworkCaptureInput, options?: ExecutionOptions, ): Promise>; + /** Retry retained reader/runtime cleanup when the owning service shuts down. */ + close?(): Promise; } diff --git a/src/application/WebNetworkCaptureService.ts b/src/application/WebNetworkCaptureService.ts index 326016a26..5a3d5cfea 100644 --- a/src/application/WebNetworkCaptureService.ts +++ b/src/application/WebNetworkCaptureService.ts @@ -10,12 +10,14 @@ import { AnalysisInputError, AnalysisOutputError, } from "../domain/analysisErrorCore.js"; +import { createAnalysisProfile } from "../domain/analysisProfile.js"; import { createEvidence, type Evidence } from "../domain/evidence.js"; import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; import { jsonObjectSchema } from "../domain/jsonValue.js"; import { err, ok, type Result } from "../domain/result.js"; import { inspectWebNetworkCaptureInputSchema, + captureSensitiveValues, webNetworkCaptureSchema, } from "../domain/webNetworkCapture.js"; @@ -25,6 +27,11 @@ const OPERATION = "inspect_web_network_capture"; export class WebNetworkCaptureService { constructor(readonly port: WebNetworkCapturePort) {} + /** Release resources retained by the selected capture adapter. */ + close(): Promise { + return this.port.close?.() ?? Promise.resolve(); + } + /** Return selected complete records inline, without inventing live browser attribution. */ async inspect( rawInput: unknown, @@ -32,21 +39,8 @@ export class WebNetworkCaptureService { ): Promise> { if (options?.signal?.aborted) return err(new AnalysisCancelledError(OPERATION)); - const declarations = - inspectWebNetworkCaptureInputSchema.shape.sensitive_values.safeParse( - typeof rawInput === "object" && - rawInput !== null && - "sensitive_values" in rawInput - ? rawInput.sensitive_values - : undefined, - ); const failure = (error: AnalysisError): Result => - err( - redactExplicitFailure( - error, - declarations.success ? declarations.data : [], - ), - ); + err(redactExplicitFailure(error, captureSensitiveValues(rawInput))); const parsed = inspectWebNetworkCaptureInputSchema.safeParse(rawInput); if (!parsed.success) return failure( @@ -187,6 +181,15 @@ export class WebNetworkCaptureService { ? [...limitations, subjectUnavailableReason] : limitations, }, + ...(safeValue.format !== "qlog" + ? {} + : { + analysisProfile: createAnalysisProfile(value.decoder, { + qlog_profile: safeValue.qlog.profile, + clock: safeValue.qlog.clock, + scope: safeValue.qlog.scope, + }), + }), confidence: "observed", authority: "historical-reference", limitations, diff --git a/src/application/WebScriptArtifactPort.ts b/src/application/WebScriptArtifactPort.ts index 02214d006..77dcd9cfc 100644 --- a/src/application/WebScriptArtifactPort.ts +++ b/src/application/WebScriptArtifactPort.ts @@ -8,6 +8,7 @@ import type { ExecutionOptions } from "./AnalysisProvider.js"; /** Read the caller-selected capture export and verify the selected source identity. */ export interface WebScriptArtifactPort { + close?(): Promise; load( input: SelectedWebScriptInput, options?: ExecutionOptions, diff --git a/src/application/WebSourceLocationPorts.ts b/src/application/WebSourceLocationPorts.ts index 04fe1742c..1d21783cc 100644 --- a/src/application/WebSourceLocationPorts.ts +++ b/src/application/WebSourceLocationPorts.ts @@ -20,6 +20,7 @@ export interface WebSourceLocationArtifacts extends SelectedWebScriptArtifacts { /** Replaceable artifact acquisition boundary for a caller-selected pairing. */ export interface WebSourceLocationArtifactPort { + close?(): Promise; load( input: WebSourceLocationInput, options?: ExecutionOptions, diff --git a/src/application/WebSourceLocationService.ts b/src/application/WebSourceLocationService.ts index 7be901311..d084bff5a 100644 --- a/src/application/WebSourceLocationService.ts +++ b/src/application/WebSourceLocationService.ts @@ -1,3 +1,4 @@ +import { closeOwnedWebResources } from "./closeOwnedWebResources.js"; import { createHash } from "node:crypto"; import { isAbsolute } from "node:path"; import { z } from "zod"; @@ -71,7 +72,13 @@ export class WebSourceLocationService { ) {} close(): Promise { - return this.decoder.close?.() ?? Promise.resolve(); + return closeOwnedWebResources( + [ + this.artifacts.close?.bind(this.artifacts), + this.decoder.close?.bind(this.decoder), + ], + "Web source-location cleanup failed", + ); } /** Shared CLI/MCP workflow preserves raw declarations and every equal-position match. */ @@ -174,6 +181,7 @@ export class WebSourceLocationService { ); } } + const invalidOutput = (message: string): Result => err(new AnalysisOutputError(OPERATION, message)); const invalid = ( diff --git a/src/application/analysisView/AnalysisViewService.ts b/src/application/analysisView/AnalysisViewService.ts index a5b603a86..baaa6b7ca 100644 --- a/src/application/analysisView/AnalysisViewService.ts +++ b/src/application/analysisView/AnalysisViewService.ts @@ -47,14 +47,8 @@ export const inspectAnalysisViewValidated = ( input: InspectAnalysisViewInput, lookup?: EvidenceLookup, ): Result => { - const inline = input.source.kind === "inline" ? input.source.evidence : null; - const inlineCapture = - typeof inline === "object" && - inline !== null && - Object.getOwnPropertyDescriptor(inline, "operation")?.value === - "inspect_web_network_capture"; const accumulator = - input.view.kind === "api-surface" || inlineCapture + input.view.kind === "api-surface" ? new WebNetworkApiSurfaceAccumulator() : undefined; if (input.source.kind === "inline" && accumulator !== undefined) { diff --git a/src/application/android/AndroidPackageInspection.ts b/src/application/android/AndroidPackageInspection.ts new file mode 100644 index 000000000..3fbaa2f1b --- /dev/null +++ b/src/application/android/AndroidPackageInspection.ts @@ -0,0 +1,43 @@ +import type { ExecutionOptions } from "../AnalysisProvider.js"; +import type { AndroidAnalysisService } from "./AndroidAnalysisService.js"; +import { + requireAnalysisViewRetention, + summarizeRetainedAnalysis, + type AnalysisViewRetention, +} from "../analysisView/AnalysisViewService.js"; +import type { AnalysisError } from "../../domain/analysisErrorBase.js"; +import { AnalysisCancelledError } from "../../domain/analysisErrorCore.js"; +import { androidPackageInspectionInputSchema } from "../../domain/android/androidAnalysis.js"; +import type { Evidence } from "../../domain/evidence.js"; +import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; +import { err, type Result } from "../../domain/result.js"; + +/** Preserve the complete provider request; select retained delivery explicitly. */ +export const inspectAndroidPackage = async ( + service: AndroidAnalysisService, + rawInput: unknown, + retention: AnalysisViewRetention, + options?: ExecutionOptions, +): Promise> => { + const operation = "inspect_android_package"; + if (options?.signal?.aborted === true) + return err(new AnalysisCancelledError(operation)); + const parsed = androidPackageInspectionInputSchema.safeParse(rawInput); + if (!parsed.success) + return err( + analysisInputErrorFromIssues(operation, parsed.error.issues, rawInput, { + cause: parsed.error, + }), + ); + if (parsed.data.detail === "summary") { + const ready = requireAnalysisViewRetention(operation, retention); + if (!ready.ok) return ready; + } + const executed = await service.execute( + operation, + { path: parsed.data.path }, + options, + ); + if (!executed.ok || parsed.data.detail !== "summary") return executed; + return summarizeRetainedAnalysis(executed.value, retention); +}; diff --git a/src/application/binaryDiagnostics/PeResourcesPort.ts b/src/application/binaryDiagnostics/PeResourcesPort.ts index b1a7b53de..ee36d34f3 100644 --- a/src/application/binaryDiagnostics/PeResourcesPort.ts +++ b/src/application/binaryDiagnostics/PeResourcesPort.ts @@ -12,6 +12,7 @@ import type { Result } from "../../domain/result.js"; /** Stable read and PE decoding boundary, independent of an active disassembler session. */ export interface PeResourcesPort { readonly identity: ProviderIdentity; + close?(): Promise; inspect( input: InspectPeResourcesInput, options?: ExecutionOptions, diff --git a/src/application/binaryDiagnostics/PeResourcesService.ts b/src/application/binaryDiagnostics/PeResourcesService.ts index 3c8a53704..87de771a4 100644 --- a/src/application/binaryDiagnostics/PeResourcesService.ts +++ b/src/application/binaryDiagnostics/PeResourcesService.ts @@ -21,6 +21,10 @@ import { err, ok, type Result } from "../../domain/result.js"; export class PeResourcesService { constructor(readonly provider: PeResourcesPort) {} + close(): Promise { + return this.provider.close?.() ?? Promise.resolve(); + } + async inspect( rawInput: unknown, options?: ExecutionOptions, diff --git a/src/application/captures/PacketCaptureService.ts b/src/application/captures/PacketCaptureService.ts index f2098b49c..e2877fa3f 100644 --- a/src/application/captures/PacketCaptureService.ts +++ b/src/application/captures/PacketCaptureService.ts @@ -1,3 +1,9 @@ +import { + inspectPacketFieldsInputSchema, + packetFieldsCatalogSchema, + type InspectPacketFieldsInput, +} from "../../domain/captures/packetFields.js"; +import type { JsonValue } from "../../domain/jsonValue.js"; import { isAbsolute } from "node:path"; import type { AnalysisExecution, @@ -24,6 +30,10 @@ export interface PacketCapturePort { input: InspectPacketCaptureInput, options?: ExecutionOptions, ): Promise>; + inspectFields( + input: InspectPacketFieldsInput, + options?: ExecutionOptions, + ): Promise>; close(): Promise; } @@ -74,14 +84,58 @@ export class PacketCaptureService { "Capture analyzer returned malformed data or changed the selected artifact identity/options.", ), ); - const evidence = createEvidence(execution.subject, execution.provider, { - operation, - parameters: input.data, - result: report.data, - confidence: "observed", - locations: execution.locations, - limitations: execution.limitations, - }); + return this.#evidence(operation, input.data, execution, options); + } + async inspectFields( + raw: unknown, + options?: ExecutionOptions, + ): Promise> { + const operation = "inspect_packet_fields"; + if (options?.signal?.aborted) + return err(new AnalysisCancelledError(operation)); + const input = inspectPacketFieldsInputSchema.safeParse(raw); + if (!input.success) + return err( + analysisInputErrorFromIssues(operation, input.error.issues, raw, { + cause: input.error, + }), + ); + const decoded = await this.provider.inspectFields(input.data, options); + if (!decoded.ok) return decoded; + const execution = decoded.value; + const report = packetFieldsCatalogSchema.safeParse(execution.result); + if ( + !report.success || + JSON.stringify(report.data.selection) !== JSON.stringify(input.data) || + execution.subject?.path !== report.data.tool.path || + execution.subject.sha256 !== report.data.tool.sha256 + ) + return err( + new AnalysisOutputError( + operation, + "Field discovery returned malformed data or changed the selected installation/options.", + ), + ); + return this.#evidence(operation, input.data, execution, options); + } + #evidence( + operation: string, + parameters: Readonly>, + execution: AnalysisExecution, + options?: ExecutionOptions, + ): Result { + const evidence = createEvidence( + execution.subject ?? undefined, + execution.provider, + { + operation, + parameters, + result: execution.result, + confidence: "observed", + locations: execution.locations, + limitations: execution.limitations, + }, + ); return options?.signal?.aborted ? err( new AnalysisCancelledError(operation, { diff --git a/src/application/closeOwnedWebResources.ts b/src/application/closeOwnedWebResources.ts new file mode 100644 index 000000000..51b3e6f69 --- /dev/null +++ b/src/application/closeOwnedWebResources.ts @@ -0,0 +1,15 @@ +/** Attempt every web workflow cleanup owner and report all failures. */ +export const closeOwnedWebResources = async ( + close: readonly ((() => Promise) | undefined)[], + message: string, +): Promise => { + const results = await Promise.allSettled( + close.flatMap((owner) => + owner === undefined ? [] : [Promise.resolve().then(owner)], + ), + ); + const failures = results.flatMap((result) => + result.status === "rejected" ? [result.reason] : [], + ); + if (failures.length > 0) throw new AggregateError(failures, message); +}; diff --git a/src/application/evm/EvmInterfacePort.ts b/src/application/evm/EvmInterfacePort.ts index e9e29b756..a297e092c 100644 --- a/src/application/evm/EvmInterfacePort.ts +++ b/src/application/evm/EvmInterfacePort.ts @@ -4,13 +4,19 @@ import type { } from "../AnalysisProvider.js"; import type { AnalysisError } from "../../domain/analysisErrorBase.js"; import type { InspectEvmInterfaceInput } from "../../domain/evm/evmInterface.js"; +import type { EvidenceSubjectTarget } from "../../domain/evidence.js"; import type { Result } from "../../domain/result.js"; +/** Successful EVM interface recovery must identify the selected local file. */ +export type EvmInterfaceExecution = Omit & { + readonly subject: EvidenceSubjectTarget & { readonly format: "file" }; +}; + /** Replaceable offline interface-recovery engine, independent of wallets and chain clients. */ export interface EvmInterfacePort { close?(): Promise; inspect( input: InspectEvmInterfaceInput, options?: ExecutionOptions, - ): Promise>; + ): Promise>; } diff --git a/src/application/evm/EvmInterfaceService.test.ts b/src/application/evm/EvmInterfaceService.test.ts index 08cf15487..03f501742 100644 --- a/src/application/evm/EvmInterfaceService.test.ts +++ b/src/application/evm/EvmInterfaceService.test.ts @@ -1,5 +1,6 @@ import { expect, it } from "vitest"; import { EvmInterfaceService } from "./EvmInterfaceService.js"; +import type { EvmInterfaceExecution } from "./EvmInterfacePort.js"; import { evmInterfaceExecution, evmInterfaceFixture, @@ -43,7 +44,8 @@ it.each(["carrier", "encoding", "digest", "no-subject"])( }, }; const service = new EvmInterfaceService({ - inspect: () => Promise.resolve(ok(execution)), + inspect: () => + Promise.resolve(ok(execution as unknown as EvmInterfaceExecution)), }); expect( await service.inspect({ diff --git a/src/application/evm/EvmInterfaceService.ts b/src/application/evm/EvmInterfaceService.ts index eac1986d3..86ac77865 100644 --- a/src/application/evm/EvmInterfaceService.ts +++ b/src/application/evm/EvmInterfaceService.ts @@ -67,6 +67,7 @@ export class EvmInterfaceService { !report.success || report.data.artifact.path !== input.data.path || report.data.artifact.encoding !== input.data.encoding || + execution.subject?.format !== "file" || execution.subject?.path !== input.data.path || execution.subject.sha256 !== report.data.artifact.sha256 ) diff --git a/src/application/flutter/DartAotInspection.ts b/src/application/flutter/DartAotInspection.ts new file mode 100644 index 000000000..c11bbe1f4 --- /dev/null +++ b/src/application/flutter/DartAotInspection.ts @@ -0,0 +1,40 @@ +import type { ExecutionOptions } from "../AnalysisProvider.js"; +import type { FlutterBuildAnalysisService } from "./FlutterBuildAnalysisService.js"; +import { + requireAnalysisViewRetention, + summarizeRetainedAnalysis, + type AnalysisViewRetention, +} from "../analysisView/AnalysisViewService.js"; +import type { AnalysisError } from "../../domain/analysisErrorBase.js"; +import { AnalysisCancelledError } from "../../domain/analysisErrorCore.js"; +import { dartAotInspectionInputSchema } from "../../domain/flutter/flutterBuildAnalysis.js"; +import type { Evidence } from "../../domain/evidence.js"; +import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js"; +import { err, type Result } from "../../domain/result.js"; + +/** Keep the caller's ABI choice and complete analysis; select only its delivery. */ +export const inspectDartAot = async ( + service: FlutterBuildAnalysisService, + rawInput: unknown, + retention: AnalysisViewRetention, + options?: ExecutionOptions, +): Promise> => { + const operation = "inspect_dart_aot"; + if (options?.signal?.aborted === true) + return err(new AnalysisCancelledError(operation)); + const parsed = dartAotInspectionInputSchema.safeParse(rawInput); + if (!parsed.success) + return err( + analysisInputErrorFromIssues(operation, parsed.error.issues, rawInput, { + cause: parsed.error, + }), + ); + if (parsed.data.detail === "summary") { + const ready = requireAnalysisViewRetention(operation, retention); + if (!ready.ok) return ready; + } + const { detail, ...providerInput } = parsed.data; + const executed = await service.execute(operation, providerInput, options); + if (!executed.ok || detail !== "summary") return executed; + return summarizeRetainedAnalysis(executed.value, retention); +}; diff --git a/src/application/frida/FridaInstrumentationManager.test.ts b/src/application/frida/FridaInstrumentationManager.test.ts index 29ba97965..7a527a807 100644 --- a/src/application/frida/FridaInstrumentationManager.test.ts +++ b/src/application/frida/FridaInstrumentationManager.test.ts @@ -809,6 +809,42 @@ it("keeps an active script message bucket after its last message is evicted", as await manager.closeAll(); }); +it("retains the newest contiguous messages across repeated budget evictions", async () => { + const { bindings, manager, started } = await startLocalAttachedSession(); + expect(started.ok).toBe(true); + if (!started.ok) return; + bindings.device.session.nextPayload = { index: -1 }; + const loaded = await manager.loadScript(started.value.sessionId, { + sourceKind: "inline", + source: "send({index: -1});", + }); + expect(loaded.ok).toBe(true); + const script = bindings.device.session.scripts[0]; + expect(script).toBeDefined(); + if (script === undefined) return; + + // About 500 of these fit the 16 MiB budget, so 2,000 sends evict and + // compact the queue several times. + const filler = "x".repeat(32_000); + for (let index = 0; index < 2_000; index += 1) + script.message.emit({ type: "send", payload: { index, filler } }, null); + + const status = manager.status(started.value.sessionId); + expect(status?.messagesTruncated).toBe(true); + const indexes = (status?.messages ?? []).map( + (message) => (message as { payload: { index: number } }).payload.index, + ); + expect(indexes.length).toBeGreaterThan(400); + expect(indexes.at(-1)).toBe(1_999); + expect(indexes).toEqual( + Array.from( + { length: indexes.length }, + (_, offset) => 2_000 - indexes.length + offset, + ), + ); + await manager.closeAll(); +}); + it("serializes a final remote release against a new same-endpoint session", async () => { const bindings = new FakeDeviceManager(); let enteredRemoval: (() => void) | undefined; diff --git a/src/application/go/GoBinaryPort.ts b/src/application/go/GoBinaryPort.ts index 2094e9109..cef925921 100644 --- a/src/application/go/GoBinaryPort.ts +++ b/src/application/go/GoBinaryPort.ts @@ -12,6 +12,7 @@ import type { Result } from "../../domain/result.js"; /** Replaceable offline build-information reader with no target-execution authority. */ export interface GoBinaryPort { readonly identity: ProviderIdentity; + close?(): Promise; inspect( input: InspectGoBinaryInput, options?: ExecutionOptions, diff --git a/src/application/go/GoBinaryService.ts b/src/application/go/GoBinaryService.ts index f5642c96c..2b9928f82 100644 --- a/src/application/go/GoBinaryService.ts +++ b/src/application/go/GoBinaryService.ts @@ -34,6 +34,10 @@ const architectureForSubject = (architecture: string) => { export class GoBinaryService { constructor(readonly provider: GoBinaryPort) {} + close(): Promise { + return this.provider.close?.() ?? Promise.resolve(); + } + /** Inspect one explicitly selected file without acquiring a binary session. */ async inspect( rawInput: unknown, diff --git a/src/application/investigation/EvidenceLedger.residualUnknown.test.ts b/src/application/investigation/EvidenceLedger.residualUnknown.test.ts index bb81f97ce..2885c1906 100644 --- a/src/application/investigation/EvidenceLedger.residualUnknown.test.ts +++ b/src/application/investigation/EvidenceLedger.residualUnknown.test.ts @@ -78,6 +78,51 @@ const update = ( }); describe("residual unknown registry reads and identity", () => { + it("seals mutation Evidence without freezing caller-owned inputs", () => { + const store = ledger(); + const recordMutation = mutation("mutable-record-mutation"); + const recorded = store.recordUnknown( + input("Does record mutation evidence stay stable?"), + recordMutation, + ); + if (!recorded.ok) throw recorded.error; + + const updateMutation = mutation("mutable-update-mutation"); + const updated = store.updateUnknown(update(recorded.value), updateMutation); + if (!updated.ok) throw updated.error; + const atomicEvidence = evidence("mutable-atomic-evidence"); + const atomicMutation = mutation("mutable-atomic-mutation"); + const atomicallyRecorded = store.recordWithUnknown( + atomicEvidence, + input("Does atomic evidence stay stable?"), + atomicMutation, + ); + if (!atomicallyRecorded.ok) throw atomicallyRecorded.error; + + for (const callerEvidence of [ + recordMutation, + updateMutation, + atomicEvidence, + atomicMutation, + ]) { + expect(Object.isFrozen(callerEvidence)).toBe(false); + const retained = store.forAnalysis(callerEvidence.evidence_id); + if (retained === undefined) throw new Error("Missing retained Evidence"); + const originalResult = structuredClone(retained.normalized_result); + expect(Object.isFrozen(retained)).toBe(true); + Reflect.set(callerEvidence, "operation", "caller mutation"); + expect( + Reflect.set( + callerEvidence.normalized_result as object, + "label", + "caller nested mutation", + ), + ).toBe(true); + expect(retained.operation).not.toBe("caller mutation"); + expect(retained.normalized_result).toEqual(originalResult); + } + }); + it("merges record-only bundles without changing retained unknown history", () => { const store = ledger(); const created = store.recordUnknown( diff --git a/src/application/investigation/EvidenceLedger.ts b/src/application/investigation/EvidenceLedger.ts index ce806ad38..0cb1c5e29 100644 --- a/src/application/investigation/EvidenceLedger.ts +++ b/src/application/investigation/EvidenceLedger.ts @@ -11,11 +11,7 @@ import { import { AnalysisInputError } from "../../domain/analysisErrorCore.js"; import { EvidenceIntegrityError } from "../../domain/evidenceErrors.js"; import { UnknownRegistryError } from "../../domain/unknownRegistryError.js"; -import { - immutableEvidence, - parseEvidence, - type Evidence, -} from "../../domain/evidence.js"; +import { immutableEvidence, type Evidence } from "../../domain/evidence.js"; import { createResidualUnknown, updateResidualUnknown, @@ -220,7 +216,7 @@ export class EvidenceLedger { ): Result { let parsedMutation: Evidence; try { - parsedMutation = parseEvidence(mutationEvidence); + parsedMutation = immutableEvidence(mutationEvidence); } catch (cause: unknown) { return err( new EvidenceIntegrityError("Unknown mutation evidence is invalid", { @@ -255,8 +251,8 @@ export class EvidenceLedger { let evidence: Evidence; let mutation: Evidence; try { - evidence = parseEvidence(evidenceInput); - mutation = parseEvidence(mutationInput); + evidence = immutableEvidence(evidenceInput); + mutation = immutableEvidence(mutationInput); } catch (cause: unknown) { return err( new EvidenceIntegrityError("Atomic Evidence validation failed", { @@ -394,7 +390,7 @@ export class EvidenceLedger { ): Result { let mutationEvidence: Evidence; try { - mutationEvidence = parseEvidence(mutationEvidenceInput); + mutationEvidence = immutableEvidence(mutationEvidenceInput); } catch (cause: unknown) { return err( new EvidenceIntegrityError("Unknown mutation evidence is invalid", { diff --git a/src/application/javascript/JavaScriptArtifactAnalysis.sourceMaps.test.ts b/src/application/javascript/JavaScriptArtifactAnalysis.sourceMaps.test.ts new file mode 100644 index 000000000..cbd9c745c --- /dev/null +++ b/src/application/javascript/JavaScriptArtifactAnalysis.sourceMaps.test.ts @@ -0,0 +1,71 @@ +import { expect, it } from "vitest"; +import { TraceMap } from "@jridgewell/trace-mapping"; + +import { analyzeJavaScriptArtifactFiles } from "./JavaScriptArtifactAnalysis.js"; + +const HASH = "a".repeat(64); + +it("retains batched TraceMap-resolved paths and null source positions", () => { + const sourceMapText = JSON.stringify({ + version: 3, + file: "main.js", + sourceRoot: "../src/", + sources: ["cafe\u0301.ts", null, "other.ts"], + sourcesContent: ["export const value = 1;", null, "export {};"], + names: [], + mappings: "", + }); + const analysis = analyzeJavaScriptArtifactFiles({ + files: [ + { + path: "dist/main.js.map", + container_sha256: HASH, + sha256: HASH, + bytes: Buffer.byteLength(sourceMapText), + inventory_artifact_id: "artifact_test", + kind: "source-map", + unpacked: false, + text: { included: true, value: sourceMapText }, + }, + ], + containers: [], + text_bytes_read: Buffer.byteLength(sourceMapText), + invalid_utf8_files: 0, + }); + const originals = analysis.source_maps[0]?.sources; + const original = originals?.[0]; + const producerPath = new TraceMap( + { + version: 3, + file: "main.js", + sourceRoot: "../src/", + sources: ["cafe\u0301.ts", "", "other.ts"], + names: [], + mappings: "", + }, + "file:///artifact/dist/main.js.map", + ).resolvedSources[0]; + + if (producerPath === undefined) + throw new Error("TraceMap should resolve its single source declaration"); + expect(originals?.[1]?.reference).toBeNull(); + expect(originals?.[2]?.reference?.resolution).toEqual({ + kind: "artifact-relative", + path: "src/other.ts", + }); + expect(original?.reference).toMatchObject({ + source_name: "cafe\u0301.ts", + source_root: "../src/", + map_path: "dist/main.js.map", + resolution: { + kind: "artifact-relative", + path: "src/cafe\u0301.ts", + }, + }); + expect(original?.reference?.resolution).toEqual({ + kind: "artifact-relative", + path: decodeURIComponent( + new URL(producerPath).pathname.slice("/artifact/".length), + ), + }); +}); diff --git a/src/application/javascript/JavaScriptArtifactAnalysis.ts b/src/application/javascript/JavaScriptArtifactAnalysis.ts index e52ba04dd..e61d3ae94 100644 --- a/src/application/javascript/JavaScriptArtifactAnalysis.ts +++ b/src/application/javascript/JavaScriptArtifactAnalysis.ts @@ -1,9 +1,9 @@ import { createHash } from "node:crypto"; -import { moduleKindForJavaScriptReference } from "./JavaScriptArtifactPathResolution.js"; +import { moduleResolutionModeForJavaScriptReference } from "../../domain/javascript/javascriptModuleResolutionMode.js"; import { setImmediate } from "node:timers/promises"; -import { resolveJavaScriptSourceMapReference } from "../../domain/javascript/javascriptSourceMapPaths.js"; +import { resolveJavaScriptSourceMapReferences } from "../../domain/javascript/javascriptSourceMapPaths.js"; import { analyzeParsedJavaScriptStaticSourceSteps } from "../../domain/javascript/javascriptStaticAnalysis.js"; import { analyzeParsedJavaScriptSemanticsSteps, @@ -384,7 +384,10 @@ function* analyzeArtifactFileSteps< analysis.parse_status === "complete" || analysis.parse_status === "partial" ? yield* analyzeParsedJavaScriptSemanticsSteps( parsed, - moduleKindForJavaScriptReference(file.path, "static-import"), + moduleResolutionModeForJavaScriptReference( + file.path, + "static-import", + ), ) : null; const projected = @@ -561,21 +564,27 @@ const collectSourceMapOriginals = ( "Source map sourceRoot must be a string or null.", ); const root = typeof map.sourceRoot === "string" ? map.sourceRoot : null; - for (const [index, raw] of names.entries()) { + const sourceNames: (string | null)[] = []; + for (const raw of names) { if (raw !== null && typeof raw !== "string") return invalidSourceMap( file, "Source map contains a non-string source name.", ); + sourceNames.push(raw); + } + const references = resolveJavaScriptSourceMapReferences( + sourceNames, + root, + file.path, + ); + for (const [index, reference] of references.entries()) { const rawContent = Array.isArray(contents) ? contents[index] : undefined; const content = typeof rawContent === "string" ? rawContent : null; sources.push({ source_index: index, declaration_index: declarationIndex++, - reference: - typeof raw === "string" - ? resolveJavaScriptSourceMapReference(raw, root, file.path) - : null, + reference, content, content_sha256: content === null ? null : sha256(content), }); diff --git a/src/application/javascript/JavaScriptArtifactGraphContext.ts b/src/application/javascript/JavaScriptArtifactGraphContext.ts index 8b0fed5f1..1779bdaae 100644 --- a/src/application/javascript/JavaScriptArtifactGraphContext.ts +++ b/src/application/javascript/JavaScriptArtifactGraphContext.ts @@ -66,6 +66,7 @@ export interface AstEdgeInput { /** Inferred static relationship edge values. */ export interface InferenceEdgeInput extends AstEdgeInput { + readonly limitations?: readonly string[]; readonly relation: | "imports" | "loads" @@ -162,6 +163,9 @@ export const addStaticInferenceEdge = ( range: input.range, operation: "map-static-relationship", coverage: input.coverage, + ...(input.limitations === undefined + ? {} + : { limitations: input.limitations }), }), }); }; @@ -347,7 +351,7 @@ export const resolveArtifactPath = ( specifier: string, sourcePath: string, files: ReadonlyMap, - moduleKind?: "import" | "require", + moduleKind?: "import" | "require" | "compiler-dependent", ): string | null => resolveArtifactPathByContext({ declaredPath: specifier, diff --git a/src/application/javascript/JavaScriptArtifactGraphFindings.ts b/src/application/javascript/JavaScriptArtifactGraphFindings.ts index 3e92ff1a4..0020ef577 100644 --- a/src/application/javascript/JavaScriptArtifactGraphFindings.ts +++ b/src/application/javascript/JavaScriptArtifactGraphFindings.ts @@ -12,7 +12,6 @@ import { javascriptAnalysisCoverage, linkElectronRoleToAsset, moduleLookupKey, - resolveArtifactPath, selfReferenceOmissions, sourceNodeFor, type JavaScriptArtifactGraphContext, @@ -23,9 +22,11 @@ import { staticInferenceEvidence, } from "./JavaScriptArtifactGraphEvidence.js"; import { - moduleKindForJavaScriptReference, + artifactPathResolutionProperties, resolveArtifactPathByContext, + type ArtifactPathResolution, } from "./JavaScriptArtifactPathResolution.js"; +import { moduleResolutionModeForJavaScriptReference } from "../../domain/javascript/javascriptModuleResolutionMode.js"; type StaticReference = JavaScriptStaticAnalysis["references"][number]; type StaticEndpoint = JavaScriptStaticAnalysis["endpoints"][number]; @@ -41,9 +42,12 @@ interface FindingInput { } interface ResolvedReference { - readonly path: string; - readonly file: JavaScriptArtifactFile; + readonly path: string | null; + readonly file: JavaScriptArtifactFile | null; readonly node: ApplicationNode; + readonly limitations: readonly string[]; + readonly resolutionStatus?: string; + readonly resolution?: ArtifactPathResolution; } /** Project imports, workers, roles, endpoints, storage, and source-map links. */ @@ -90,7 +94,7 @@ const addReference = ( const resolved = input.value.specifier === null ? null - : resolveReference(context, input.file.path, input.value); + : resolveReference(context, input.file.path, input.value, input.coverage); if (input.value.kind === "worker" || input.value.kind === "service-worker") { const worker = context.accumulator.addNode({ kind: input.value.kind === "worker" ? "worker" : "service-worker", @@ -126,7 +130,7 @@ const addReference = ( relation: "loads", properties: { kind: input.value.kind }, }); - if (resolved !== null) + if (resolved !== null && resolved.path !== null) addStaticInferenceEdge(context, { source: worker, target: resolved.node, @@ -135,6 +139,7 @@ const addReference = ( coverage: input.coverage, relation: "maps_to", properties: { resolved_path: resolved.path }, + limitations: resolved.limitations, }); return; } @@ -154,13 +159,25 @@ const addReference = ( file: input.file, range: input.value.location, coverage: input.coverage, - relation: resolved?.file.kind === "native-addon" ? "loads" : "imports", + relation: resolved?.file?.kind === "native-addon" ? "loads" : "imports", properties: { kind: input.value.kind, specifier: input.value.specifier, expression: input.value.expression, + resolution_mode: + input.value.kind === "static-import" || + input.value.kind === "dynamic-import" || + input.value.kind === "require" + ? moduleResolutionModeForJavaScriptReference( + input.file.path, + input.value.kind, + ) + : null, resolved_path: resolved?.path ?? null, + resolution_status: resolved?.resolutionStatus ?? null, + ...artifactPathResolutionProperties(resolved?.resolution), }, + ...(resolved === null ? {} : { limitations: resolved.limitations }), }); }; @@ -373,6 +390,7 @@ const resolveReference = ( context: JavaScriptArtifactGraphContext, sourcePath: string, reference: StaticReference, + coverage: JavaScriptArtifactGraphCoverage, ): ResolvedReference | null => { const specifier = reference.specifier; if (specifier === null) return null; @@ -392,30 +410,70 @@ const resolveReference = ( const file = context.filesByPath.get(sourcePath); return file === undefined ? null - : { path: `${sourcePath}#module:${specifier}`, file, node: module }; + : { + path: `${sourcePath}#module:${specifier}`, + file, + node: module, + limitations: [], + }; } // Worker scripts are URLs relative to the script, not module specifiers. - const path = isWorker + const resolution = isWorker ? resolveArtifactPathByContext({ declaredPath: specifier, sourcePath, context: "url-reference", files: context.filesByPath, - }).resolved_path - : resolveArtifactPath( - specifier, + }) + : resolveArtifactPathByContext({ + declaredPath: specifier, sourcePath, - context.filesByPath, - reference.kind === "require" || - reference.kind === "static-import" || - reference.kind === "dynamic-import" - ? moduleKindForJavaScriptReference(sourcePath, reference.kind) - : undefined, - ); - if (path === null) return null; + context: "module-specifier", + files: context.filesByPath, + ...("require" === reference.kind || + "static-import" === reference.kind || + "dynamic-import" === reference.kind + ? { + moduleKind: moduleResolutionModeForJavaScriptReference( + sourcePath, + reference.kind, + ), + } + : {}), + }); + const path = resolution.resolved_path; + if (path === null) { + if (isWorker) return null; + const source = context.filesByPath.get(sourcePath); + return source === undefined + ? null + : { + path: null, + file: null, + node: unresolvedReferenceNode( + context, + source, + reference, + coverage, + resolution, + ), + limitations: resolution.limitations, + resolutionStatus: resolution.resolution_status, + resolution, + }; + } const file = context.filesByPath.get(path); const node = context.fileNodes.get(path); - return file === undefined || node === undefined ? null : { path, file, node }; + return file === undefined || node === undefined + ? null + : { + path, + file, + node, + limitations: resolution.limitations, + resolutionStatus: resolution.resolution_status, + resolution, + }; }; const resolveBundlerChunkReference = ( @@ -453,7 +511,7 @@ const resolveBundlerChunkReference = ( const node = unique[0]; return node === undefined ? null - : { path: `${sourcePath}#chunk:${key}`, file, node }; + : { path: `${sourcePath}#chunk:${key}`, file, node, limitations: [] }; }; const unresolvedReferenceNode = ( @@ -461,6 +519,7 @@ const unresolvedReferenceNode = ( file: JavaScriptArtifactFile, reference: StaticReference, coverage: JavaScriptArtifactGraphCoverage, + resolution?: ArtifactPathResolution, ): ApplicationNode => context.accumulator.addNode({ kind: "javascript-module", @@ -477,6 +536,10 @@ const unresolvedReferenceNode = ( specifier: reference.specifier, expression: reference.expression, resolution: "unresolved", + ...(resolution === undefined + ? {} + : { resolution_status: resolution.resolution_status }), + ...artifactPathResolutionProperties(resolution), }, evidence: staticInferenceEvidence({ sha256: file.sha256, @@ -487,6 +550,7 @@ const unresolvedReferenceNode = ( confidence: "low", limitations: [ "The static reference could not be resolved within the inventoried artifact.", + ...(resolution?.limitations ?? []), ], }), }, diff --git a/src/application/javascript/JavaScriptArtifactPathResolution.test.ts b/src/application/javascript/JavaScriptArtifactPathResolution.test.ts index 1a8713929..b746d7e97 100644 --- a/src/application/javascript/JavaScriptArtifactPathResolution.test.ts +++ b/src/application/javascript/JavaScriptArtifactPathResolution.test.ts @@ -1890,21 +1890,40 @@ describe("TypeScript NodeNext emitted-extension resolution", () => { ).toMatchObject({ resolution_status: "resolved", resolved_path: target }); }, ); +}); + +describe("TypeScript declaration fallback ownership", () => { + const container = "container"; it.each([ ["./dep.js", "src/dep.d.ts"], ["./cfg.mjs", "src/cfg.d.mts"], ["./legacy.cjs", "src/legacy.d.cts"], ] as const)( - "resolves %s to a declaration counterpart", + "retains %s as compile-time evidence without inventing a runtime target", (specifier, target) => { const files = fileMap([ file("src/main.ts", container), file(target, container, "export const value = 1;"), ]); + for (const moduleKind of ["import", "require"] as const) { + expect( + resolve({ + declaredPath: specifier, + sourcePath: "src/main.ts", + context: "module-specifier", + moduleKind, + files, + }), + ).toMatchObject({ + resolution_status: "unavailable", + resolved_path: null, + candidate_path: target, + }); + } expect( resolve({ - declaredPath: specifier, + declaredPath: "./" + target.slice(4), sourcePath: "src/main.ts", context: "module-specifier", moduleKind: "import", diff --git a/src/application/javascript/JavaScriptArtifactPathResolution.ts b/src/application/javascript/JavaScriptArtifactPathResolution.ts index b3d769af6..cb29ab2a9 100644 --- a/src/application/javascript/JavaScriptArtifactPathResolution.ts +++ b/src/application/javascript/JavaScriptArtifactPathResolution.ts @@ -19,7 +19,13 @@ import { classifyPackageImportTargetString, lookupExactPackageImport, } from "../../domain/javascript/javascriptPackageImportAliases.js"; -import { typescriptEmittedSourceCandidates } from "../TypeScriptEmittedSourceCandidates.js"; +import { + typescriptEmittedSourceCandidates, + type TypeScriptEmittedSourceCandidate, +} from "../TypeScriptEmittedSourceCandidates.js"; +import { isRelativeJavaScriptModuleSpecifier } from "../../domain/javascript/javascriptModuleSpecifier.js"; +import type { JavaScriptModuleResolutionMode } from "../../domain/javascript/javascriptModuleResolutionMode.js"; +import type { JsonValue } from "../../domain/jsonValue.js"; type ArtifactPathResolutionContext = | "package-entrypoint" @@ -38,6 +44,16 @@ interface ArtifactPathResolutionBase { readonly declared_path: string; readonly resolution_context: ArtifactPathResolutionContext; readonly limitations: readonly string[]; + readonly conditional_resolutions?: readonly ConditionalModuleResolution[]; + readonly candidate_path?: string; +} + +export interface ConditionalModuleResolution { + readonly mode: "import" | "require"; + readonly resolution_status: UnresolvedArtifactPathStatus | "resolved"; + readonly resolved_path: string | null; + readonly candidate_path?: string; + readonly limitations: readonly string[]; } /** Explicit outcome of artifact-confined path resolution. */ @@ -61,26 +77,13 @@ export interface ResolveArtifactPathInput { readonly files: ReadonlyMap; readonly htmlBaseHref?: string | null; /** Import/require semantics; runtime resource paths omit this provenance. */ - readonly moduleKind?: "import" | "require"; + readonly moduleKind?: JavaScriptModuleResolutionMode; } -/** Loader selected by a source-level JavaScript module reference. */ -export const moduleKindForJavaScriptReference = ( - sourcePath: string, - referenceKind: "static-import" | "dynamic-import" | "require", - resolutionMode?: "import" | "require", -): "import" | "require" => - resolutionMode ?? - (referenceKind === "require" || - (referenceKind === "static-import" && - posix.extname(sourcePath).toLowerCase() === ".cts") - ? "require" - : "import"); - /** Preserve an explicitly retained loader mode on graph relationships. */ export const moduleResolutionModeProperties = ( - mode: "import" | "require" | undefined, -): Readonly> => + mode: JavaScriptModuleResolutionMode | undefined, +): Readonly> => mode === undefined ? {} : { resolution_mode: mode }; const EXTENSIONS = [ @@ -109,43 +112,116 @@ interface PackageFileTarget { readonly url: URL; } -type CandidateResolution = - | { - readonly resolvedPath: string; - readonly status: "resolved"; - readonly limitations: readonly string[]; - } +type CandidateResolution = { + readonly limitations: readonly string[]; + readonly candidatePath?: string; + readonly conditionalResolutions?: readonly ConditionalModuleResolution[]; +} & ( + | { readonly resolvedPath: string; readonly status: "resolved" } | { readonly resolvedPath: null; readonly status: UnresolvedArtifactPathStatus; - readonly limitations: readonly string[]; /** A truthy package main failed, so Node must not try ancestor packages. */ readonly stopsAncestorLookup?: true; - }; + } +); /** Resolve one declaration while preserving its original input identity. */ export const resolveArtifactPathByContext = ( input: ResolveArtifactPathInput, ): ArtifactPathResolution => { const resolution = resolvePath(input); + const facts = { + declared_path: input.declaredPath, + resolution_context: input.context, + limitations: resolution.limitations, + ...(resolution.candidatePath === undefined + ? {} + : { candidate_path: resolution.candidatePath }), + ...(resolution.conditionalResolutions === undefined + ? {} + : { conditional_resolutions: resolution.conditionalResolutions }), + }; return resolution.status === "resolved" ? { - declared_path: input.declaredPath, - resolution_context: input.context, + ...facts, resolved_path: resolution.resolvedPath, resolution_status: resolution.status, - limitations: resolution.limitations, } - : { - declared_path: input.declaredPath, - resolution_context: input.context, - resolved_path: null, - resolution_status: resolution.status, - limitations: resolution.limitations, - }; + : { ...facts, resolved_path: null, resolution_status: resolution.status }; }; +/** Project retained conditional identities without flattening them into display text. */ +export const artifactPathResolutionProperties = ( + resolution: ArtifactPathResolution | undefined, +): Readonly> => ({ + ...(resolution?.candidate_path === undefined + ? {} + : { candidate_path: resolution.candidate_path }), + ...(resolution?.conditional_resolutions === undefined + ? {} + : { + conditional_resolutions: resolution.conditional_resolutions.map( + (branch) => ({ + mode: branch.mode, + resolution_status: branch.resolution_status, + resolved_path: branch.resolved_path, + limitations: [...branch.limitations], + ...(branch.candidate_path === undefined + ? {} + : { candidate_path: branch.candidate_path }), + }), + ), + }), +}); + +const conditionalResolution = ( + mode: "import" | "require", + result: CandidateResolution, +): ConditionalModuleResolution => ({ + mode, + resolution_status: result.status, + resolved_path: result.resolvedPath, + limitations: result.limitations, + ...(result.candidatePath === undefined + ? {} + : { candidate_path: result.candidatePath }), +}); + const resolvePath = (input: ResolveArtifactPathInput): CandidateResolution => { + if (input.moduleKind === "compiler-dependent") { + const imported = resolvePath({ ...input, moduleKind: "import" }); + const required = resolvePath({ ...input, moduleKind: "require" }); + const sameOutcome = + imported.status === required.status && + imported.resolvedPath === required.resolvedPath && + imported.candidatePath === required.candidatePath; + const limitation = + "Static TypeScript loader mode is compiler-dependent without retained compiler options. " + + (sameOutcome + ? "Node import and require resolution agree on this outcome." + : "Node import and require resolution disagree; neither branch is an established target."); + return sameOutcome + ? { + ...imported, + limitations: [ + ...new Set([ + ...imported.limitations, + ...required.limitations, + limitation, + ]), + ], + } + : { + resolvedPath: null, + status: "unavailable", + limitations: [limitation], + conditionalResolutions: [ + conditionalResolution("import", imported), + conditionalResolution("require", required), + ], + }; + } // Package import keys are literal lookup identities, not artifact paths. // The selected target is admitted separately by resolveExportTarget. if ( @@ -166,7 +242,7 @@ const resolvePath = (input: ResolveArtifactPathInput): CandidateResolution => { ); const isModuleUrlPath = input.context === "module-specifier" && - (input.declaredPath.startsWith(".") || + (isRelativeJavaScriptModuleSpecifier(input.declaredPath) || input.declaredPath.startsWith("/") || fileUrlPath(input.declaredPath) !== undefined); const emittedSourceCandidates = @@ -175,12 +251,47 @@ const resolvePath = (input: ResolveArtifactPathInput): CandidateResolution => { : []; if (isModuleUrlPath && input.moduleKind === "import") return ( - resolveFileCandidates(input, [confined, ...emittedSourceCandidates]) ?? - notFoundCandidate() + resolveRuntimeSourceCandidates( + input, + confined, + emittedSourceCandidates, + ) ?? notFoundCandidate() ); return resolveCandidate(input, confined, new Set(), emittedSourceCandidates); }; +const resolveRuntimeSourceCandidates = ( + input: ResolveArtifactPathInput, + exactPath: string, + sourceCandidates: readonly TypeScriptEmittedSourceCandidate[], +): CandidateResolution | null => { + const source = input.files.get(input.sourcePath); + const exactCandidate: TypeScriptEmittedSourceCandidate = { + path: exactPath, + kind: "implementation", + }; + for (const candidate of [exactCandidate, ...sourceCandidates]) { + const target = input.files.get(candidate.path); + if ( + target === undefined || + (source !== undefined && + target.container_sha256 !== source.container_sha256) + ) + continue; + return candidate.kind === "declaration" + ? { + resolvedPath: null, + status: "unavailable", + candidatePath: candidate.path, + limitations: [ + "Only a TypeScript declaration fallback was found; it does not establish the requested runtime module.", + ], + } + : { resolvedPath: candidate.path, status: "resolved", limitations: [] }; + } + return null; +}; + const rejectDeclaration = (declared: string): CandidateResolution | null => { if (declared.length === 0) return unresolvedCandidate("rejected", ["The declared path is empty."]); @@ -229,7 +340,10 @@ const contextualCandidate = ( return unresolvedCandidate("external", [ "URL and Node builtin schemes are outside static artifact module resolution.", ]); - if (!declared.startsWith(".") && !declared.startsWith("/")) + if ( + !isRelativeJavaScriptModuleSpecifier(declared) && + !declared.startsWith("/") + ) return bareModuleCandidate(input); if (input.moduleKind !== "require") { const decoded = decodeModuleUrlPath(stripQueryAndFragment(declared)); @@ -275,7 +389,10 @@ const contextualCandidate = ( "URL", ); } - return relativeCandidate(input.sourcePath, declared); + const candidate = relativeCandidate(input.sourcePath, declared); + return context === "module-specifier" && input.moduleKind === "import" + ? exactUrlPathCandidate(declared, candidate, "module URL") + : candidate; }; const decodeModuleUrlPath = ( @@ -310,9 +427,12 @@ const bareModuleCandidate = ( return unresolvedCandidate("external", [ "The bare specifier is a Node builtin or invalid package name.", ]); - if (input.moduleKind === "import" && request.packageName.includes("%")) + if ( + input.moduleKind === "import" && + (request.packageName.startsWith(".") || request.packageName.includes("%")) + ) return unresolvedCandidate("rejected", [ - "Percent signs are not admitted in ES module package names.", + "ES module package names cannot start with a dot or contain percent signs.", ]); const self = packageSelfCandidate(input, request); if (self !== null) return self; @@ -735,7 +855,7 @@ const htmlCandidate = ( const exactUrlPathCandidate = ( declared: string, candidate: string, - kind: "HTML" | "URL", + kind: "HTML" | "URL" | "module URL", ): string | CandidateResolution => { if (!urlPathIsDirectory(declared)) return candidate; const confined = confineCandidate(candidate); @@ -839,12 +959,10 @@ const resolveCandidate = ( input: ResolveArtifactPathInput, candidate: string, packageChain: ReadonlySet, - emittedSourceCandidates: readonly string[] = [], + emittedSourceCandidates: readonly TypeScriptEmittedSourceCandidate[] = [], ): CandidateResolution => - resolveFileCandidates(input, [ - ...fileCandidates(candidate, input.moduleKind), - ...emittedSourceCandidates, - ]) ?? + resolveFileCandidates(input, fileCandidates(candidate, input.moduleKind)) ?? + resolveRuntimeSourceCandidates(input, candidate, emittedSourceCandidates) ?? resolveDirectory( input, candidate, @@ -930,11 +1048,26 @@ const resolveFileCandidates = ( (source === undefined || target.container_sha256 === source.container_sha256) ) - return { resolvedPath: path, status: "resolved", limitations: [] }; + return isRuntimeDeclarationPath(input, path) + ? { + resolvedPath: null, + status: "unavailable", + candidatePath: path, + limitations: [ + `The TypeScript declaration ${path} is compile-time evidence and cannot identify a runtime module implementation.`, + ], + } + : { resolvedPath: path, status: "resolved", limitations: [] }; } return null; }; +const isRuntimeDeclarationPath = ( + input: ResolveArtifactPathInput, + path: string, +): boolean => + input.moduleKind !== undefined && /\.d\.(?:ts|mts|cts)$/iu.test(path); + const NODE_MODULE_EXTENSIONS = [".js", ".json", ".node"] as const; const fileCandidates = ( diff --git a/src/application/javascript/JavaScriptModuleRelationships.ts b/src/application/javascript/JavaScriptModuleRelationships.ts index 874377810..3b46e95ae 100644 --- a/src/application/javascript/JavaScriptModuleRelationships.ts +++ b/src/application/javascript/JavaScriptModuleRelationships.ts @@ -18,6 +18,7 @@ import type { JavaScriptModuleOrigin, JavaScriptSemanticModuleLink, } from "../../domain/javascript/javascriptSemanticIr.js"; +import { moduleResolutionModeForJavaScriptReference } from "../../domain/javascript/javascriptModuleResolutionMode.js"; import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js"; import { addAstContainsEdge, @@ -30,7 +31,7 @@ import { staticInferenceEvidence, } from "./JavaScriptArtifactGraphEvidence.js"; import { - moduleKindForJavaScriptReference, + artifactPathResolutionProperties, moduleResolutionModeProperties, resolveArtifactPathByContext, type ArtifactPathResolution, @@ -54,6 +55,7 @@ interface RelationshipInput { type ResolvedModuleTarget = { readonly node: ApplicationNode; readonly limitations: readonly string[]; + readonly resolution?: ArtifactPathResolution; } & ( | { readonly path: string; @@ -81,8 +83,13 @@ export const addJavaScriptSourceModules = ( if (asset === undefined || semantic === null || program === undefined) continue; const exports = semantic.ir.moduleLinks - .flatMap(({ exportedName }) => - exportedName === null ? [] : [exportedName], + .flatMap(({ exportedName, kind }) => + exportedName === null || kind === "type-import" ? [] : [exportedName], + ) + .sort(compareUnicodeCodePoints); + const typeExports = semantic.ir.moduleLinks + .flatMap(({ exportedName, kind }) => + exportedName === null || kind !== "type-import" ? [] : [exportedName], ) .sort(compareUnicodeCodePoints); const retainedExports = [...new Set(exports)]; @@ -105,8 +112,12 @@ export const addJavaScriptSourceModules = ( import_relationships: semantic.ir.moduleLinks.filter( ({ kind }) => kind === "import" || kind === "require", ).length, + type_relationships: semantic.ir.moduleLinks.filter( + ({ kind }) => kind === "type-import", + ).length, export_relationships: exports.length, export_names: retainedExports, + type_export_names: [...new Set(typeExports)], omitted_export_names: 0, }, evidence: astObservationEvidence({ @@ -152,6 +163,7 @@ export function* addJavaScriptModuleRelationshipsSteps( for (const link of semantic.ir.moduleLinks) { // One module can export thousands of bindings, each with return shapes. yield; + if (link.kind === "type-import") continue; const input = { context, file, semantic, source, link }; if (isExportLink(link)) addExportRelationship(input, omissions); else if (link.specifier !== null) @@ -277,7 +289,7 @@ const resolveModuleTarget = ( sourcePath: input.file.path, context: "module-specifier", files: input.context.filesByPath, - moduleKind: moduleKindForJavaScriptReference( + moduleKind: moduleResolutionModeForJavaScriptReference( input.file.path, input.link.kind === "require" || input.link.kind === "commonjs-export" ? "require" @@ -287,15 +299,12 @@ const resolveModuleTarget = ( }); if (resolution.resolution_status !== "resolved") return { - node: unresolvedModuleNode( - input, - specifier, - resolution.resolution_status, - ), + node: unresolvedModuleNode(input, specifier, resolution), path: null, file: null, status: resolution.resolution_status, limitations: resolution.limitations, + resolution, }; const path = resolution.resolved_path; const file = input.context.filesByPath.get(path); @@ -312,20 +321,24 @@ const resolveModuleTarget = ( file, status: "resolved", limitations: resolution.limitations, + resolution, }; }; const unresolvedModuleNode = ( input: RelationshipInput, specifier: string, - status: Exclude, + resolution: Extract< + ArtifactPathResolution, + { resolution_status: Exclude } + >, ): ApplicationNode => input.context.accumulator.addNode({ kind: "javascript-module", identity: artifactLocalIdentity( input.file.sha256, "unresolved-semantic-module", - `${status}:${specifier}`, + `${resolution.resolution_status}:${specifier}`, ), observations: [ { @@ -333,7 +346,8 @@ const unresolvedModuleNode = ( properties: { semantic_role: "module-reference", declared_specifier: specifier, - resolution_status: status, + resolution_status: resolution.resolution_status, + ...artifactPathResolutionProperties(resolution), }, evidence: staticInferenceEvidence({ sha256: input.file.sha256, @@ -354,6 +368,9 @@ const moduleOriginForExport = ( ): JavaScriptModuleOrigin | null => { if (link.specifier !== null) return { + ...(link.resolutionMode === undefined + ? {} + : { resolutionMode: link.resolutionMode }), specifier: link.specifier, importedPath: link.importedName === null ? [] : [link.importedName], }; @@ -383,6 +400,7 @@ const relationshipProperties = ( exported_name: link.exportedName, resolved_path: target?.path ?? null, resolution_status: target?.status ?? null, + ...artifactPathResolutionProperties(target?.resolution), target_file_kind: target?.file?.kind ?? null, target_json_status: target?.file?.kind === "json" || target?.file?.kind === "package-json" @@ -431,6 +449,7 @@ const moduleFormat = ( const extension = posix.extname(path).toLowerCase(); if (extension === ".mjs" || extension === ".mts") return "esm"; if (extension === ".cjs" || extension === ".cts") return "commonjs"; + if (extension === ".ts" || extension === ".tsx") return "unknown"; const esm = ir.moduleLinks.some(({ kind }) => ["import", "export", "re-export"].includes(kind), ); diff --git a/src/application/managed/ManagedReconstructionService.test.ts b/src/application/managed/ManagedReconstructionService.test.ts index 56b9d9442..793951ae9 100644 --- a/src/application/managed/ManagedReconstructionService.test.ts +++ b/src/application/managed/ManagedReconstructionService.test.ts @@ -22,6 +22,26 @@ const exampleMethod = () => { }; describe("managed decompiler reconstruction import", () => { + it("reports UTF-8 byte totals while preserving UTF-16 text lengths", () => { + const text = 'return "é"; // 😀'; + const method = exampleMethod(); + const result = importManagedReconstructionEvidence({ + ...MANAGED_RECONSTRUCTION_IMPORT_EXAMPLE, + methods: [ + { + ...method, + reconstruction: { ...method.reconstruction, text }, + }, + ], + }); + if (!result.ok) throw result.error; + + expect(result.value.normalized_result).toMatchObject({ + summary: { total_text_bytes: 20 }, + methods: [{ reconstruction: { text, text_length: 17 } }], + }); + }); + it("rejects reconstruction text hash drift", () => { expect(() => importManagedReconstruction({ diff --git a/src/application/pcap/PcapAnalysisPort.ts b/src/application/pcap/PcapAnalysisPort.ts new file mode 100644 index 000000000..c5acecd38 --- /dev/null +++ b/src/application/pcap/PcapAnalysisPort.ts @@ -0,0 +1,23 @@ +import type { + AnalysisExecution, + ExecutionOptions, + ProviderAvailability, +} from "../AnalysisProvider.js"; +import type { PcapRequest } from "../../domain/pcap/pcapAnalysis.js"; +import type { AnalysisError } from "../../domain/analysisErrorBase.js"; +import type { Result } from "../../domain/result.js"; + +/** + * Packet-capture analysis boundary over caller-supplied tshark/capinfos. + * Implementation details belong to the provider adapter. + */ +export interface PcapAnalysisPort { + /** Probe both tools without reading any capture file. */ + inspectAvailability(signal?: AbortSignal): Promise; + /** Retry cleanup of retained owned commands and capture snapshots. */ + close(): Promise; + execute( + request: PcapRequest, + options?: ExecutionOptions, + ): Promise>; +} diff --git a/src/application/pcap/PcapAnalysisService.ts b/src/application/pcap/PcapAnalysisService.ts new file mode 100644 index 000000000..23b968e58 --- /dev/null +++ b/src/application/pcap/PcapAnalysisService.ts @@ -0,0 +1,36 @@ +import type { PcapAnalysisPort } from "./PcapAnalysisPort.js"; +import type { ExecutionOptions } from "../AnalysisProvider.js"; +import { + pcapRequestSchema, + type PcapOperation, +} from "../../domain/pcap/pcapAnalysis.js"; +import { + AnalysisCancelledError, + AnalysisInputError, +} from "../../domain/analysisErrorCore.js"; +import type { AnalysisError } from "../../domain/analysisErrorBase.js"; +import type { Evidence } from "../../domain/evidence.js"; +import { createPcapEvidence } from "../../domain/pcap/pcapEvidence.js"; +import { err, ok, type Result } from "../../domain/result.js"; + +/** Shared CLI/MCP admission, execution, and Evidence composition for pcap. */ +export class PcapAnalysisService { + constructor(readonly provider: PcapAnalysisPort) {} + + /** Run one caller-selected pcap request and retain capture identity inline. */ + async execute( + operation: PcapOperation, + input: unknown, + options?: ExecutionOptions, + ): Promise> { + if (options?.signal?.aborted === true) + return err(new AnalysisCancelledError(operation)); + const request = pcapRequestSchema.safeParse({ operation, input }); + if (!request.success) + return err(new AnalysisInputError(operation, { cause: request.error })); + const executed = await this.provider.execute(request.data, options); + if (!executed.ok) return executed; + const execution = executed.value; + return ok(createPcapEvidence(request.data, execution)); + } +} diff --git a/src/application/signals/SignalRecordingService.ts b/src/application/signals/SignalRecordingService.ts index 921ac19c7..e5b99f1b7 100644 --- a/src/application/signals/SignalRecordingService.ts +++ b/src/application/signals/SignalRecordingService.ts @@ -1,3 +1,9 @@ +import { + inspectSignalDecodersInputSchema, + signalDecodersSchema, + type InspectSignalDecodersInput, +} from "../../domain/signals/signalDecoders.js"; +import type { JsonValue } from "../../domain/jsonValue.js"; import { isAbsolute } from "node:path"; import type { AnalysisExecution, @@ -24,6 +30,10 @@ export interface SignalRecordingPort { input: DecodeSignalRecordingInput, options?: ExecutionOptions, ): Promise>; + inspectDecoders( + input: InspectSignalDecodersInput, + options?: ExecutionOptions, + ): Promise>; close(): Promise; } @@ -74,14 +84,58 @@ export class SignalRecordingService { "Decoder returned malformed data or changed the selected recording identity/options.", ), ); - const evidence = createEvidence(execution.subject, execution.provider, { - operation, - parameters: input.data, - result: report.data, - confidence: "observed", - locations: execution.locations, - limitations: execution.limitations, - }); + return this.#evidence(operation, input.data, execution, options); + } + async inspectDecoders( + raw: unknown, + options?: ExecutionOptions, + ): Promise> { + const operation = "inspect_signal_decoders"; + if (options?.signal?.aborted) + return err(new AnalysisCancelledError(operation)); + const input = inspectSignalDecodersInputSchema.safeParse(raw); + if (!input.success) + return err( + analysisInputErrorFromIssues(operation, input.error.issues, raw, { + cause: input.error, + }), + ); + const decoded = await this.provider.inspectDecoders(input.data, options); + if (!decoded.ok) return decoded; + const execution = decoded.value; + const report = signalDecodersSchema.safeParse(execution.result); + if ( + !report.success || + JSON.stringify(report.data.selection) !== JSON.stringify(input.data) || + execution.subject?.path !== report.data.tool.path || + execution.subject.sha256 !== report.data.tool.sha256 + ) + return err( + new AnalysisOutputError( + operation, + "Decoder discovery returned malformed data or changed the selected installation/options.", + ), + ); + return this.#evidence(operation, input.data, execution, options); + } + #evidence( + operation: string, + parameters: Readonly>, + execution: AnalysisExecution, + options?: ExecutionOptions, + ): Result { + const evidence = createEvidence( + execution.subject ?? undefined, + execution.provider, + { + operation, + parameters, + result: execution.result, + confidence: "observed", + locations: execution.locations, + limitations: execution.limitations, + }, + ); return options?.signal?.aborted ? err( new AnalysisCancelledError(operation, { diff --git a/src/application/wasm/WasmArtifactPort.ts b/src/application/wasm/WasmArtifactPort.ts index 6cf6de352..90daab4b1 100644 --- a/src/application/wasm/WasmArtifactPort.ts +++ b/src/application/wasm/WasmArtifactPort.ts @@ -4,8 +4,14 @@ import type { } from "../AnalysisProvider.js"; import type { AnalysisError } from "../../domain/analysisErrorBase.js"; import type { InspectWasmArtifactInput } from "../../domain/wasm/wasmArtifact.js"; +import type { EvidenceSubjectTarget } from "../../domain/evidence.js"; import type { Result } from "../../domain/result.js"; +/** Successful WASM inspection must identify the selected local file. */ +export type WasmArtifactExecution = Omit & { + readonly subject: EvidenceSubjectTarget & { readonly format: "file" }; +}; + /** Replaceable offline WASM inspection engine, independent of target execution and network clients. */ export interface WasmArtifactPort { /** Retry removal of retained workspaces; failures preserve ownership for another attempt. */ @@ -13,5 +19,5 @@ export interface WasmArtifactPort { inspect( input: InspectWasmArtifactInput, options?: ExecutionOptions, - ): Promise>; + ): Promise>; } diff --git a/src/artifacts/ArtifactResourceScope.ts b/src/artifacts/ArtifactResourceScope.ts index 7c0bcf2c2..872899631 100644 --- a/src/artifacts/ArtifactResourceScope.ts +++ b/src/artifacts/ArtifactResourceScope.ts @@ -57,6 +57,10 @@ export class ArtifactResourceScope { #draining: Promise | undefined; #closed = false; + get hasPending(): boolean { + return this.#pending.size > 0; + } + /** Admit a resource operation while the scope remains open. */ async run(operation: () => Promise): Promise { while (true) { diff --git a/src/artifacts/MachOSliceArtifactReader.ts b/src/artifacts/MachOSliceArtifactReader.ts index 9420bef26..f567458c7 100644 --- a/src/artifacts/MachOSliceArtifactReader.ts +++ b/src/artifacts/MachOSliceArtifactReader.ts @@ -8,11 +8,11 @@ import { type NativeCommandRunner, } from "../native/CommandRunner.js"; import { - lipoSubtypeBits, parseLipoArchitectures, type LipoArchitecture, } from "../native/parsers/lipo.js"; import type { MachoSlice } from "../domain/apple/dylibResolution.js"; +import { machoCpuSubtypeBase } from "../domain/apple/machoCpuIdentity.js"; import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js"; import { readMachoImage, type ReadAt } from "./apple/MachoLoadCommandReader.js"; import { @@ -81,7 +81,9 @@ export class MachOSliceArtifactReader implements ArtifactReader { if (!captured.ok) throw new ArtifactReaderFailure( captured.error.reason === "cancelled" ? "cancelled" : "unavailable", - "lipo could not enumerate universal Mach-O slices", + captured.error.detail === null + ? "lipo could not enumerate universal Mach-O slices" + : `lipo could not enumerate universal Mach-O slices: ${captured.error.detail}`, { cause: captured.error, ...(captured.error.cleanupFailure === null && @@ -469,8 +471,10 @@ const lipoSubtypeMatches = ( ): boolean => { if (reported.cpu_subtype_code !== null) return reported.cpu_subtype_code === observedCpuSubtype; - const bits = lipoSubtypeBits(reported.cpu_subtype); - return bits === null || bits === (observedCpuSubtype & 0x00ffffff); + return ( + reported.cpu_subtype_base === null || + reported.cpu_subtype_base === machoCpuSubtypeBase(observedCpuSubtype) + ); }; /** diff --git a/src/artifacts/NativeDmgArtifactReader.ts b/src/artifacts/NativeDmgArtifactReader.ts index a3f3fb120..801ee4daf 100644 --- a/src/artifacts/NativeDmgArtifactReader.ts +++ b/src/artifacts/NativeDmgArtifactReader.ts @@ -22,6 +22,7 @@ import { type NativeDmgInfo, } from "./NativeDmgOwnership.js"; const HDIUTIL_COMMAND_TIMEOUT_MS = 120_000; +const VERIFY_SETTLE_DELAYS_MS = [250, 500] as const; // APFS ejects and busy reporting can lag a detach attempt. const DETACH_SETTLE_DELAYS_MS = [250, 500, 1000] as const; const delay = (milliseconds: number): Promise => @@ -44,22 +45,30 @@ export interface NativeDmgHost { class NativeDmgCommandFailure extends ArtifactReaderFailure { readonly processNotStarted: boolean; + readonly verifyDiagnostic: string | undefined; + readonly exitCode: number | null; constructor( - reason: ArtifactReaderFailure["reason"], + failure: { + readonly reason: ArtifactReaderFailure["reason"]; + readonly verifyDiagnostic?: string; + }, message: string, readonly stdout: string, options?: { readonly cause?: unknown; readonly processNotStarted?: boolean; + readonly exitCode?: number; }, ) { super( - reason, + failure.reason, message, options?.cause === undefined ? undefined : { cause: options.cause }, ); this.processNotStarted = options?.processNotStarted ?? false; + this.verifyDiagnostic = failure.verifyDiagnostic; + this.exitCode = options?.exitCode ?? null; } } @@ -84,7 +93,7 @@ const createSystemHost = ( const output = execFileOutputFailure(cause); if (cause instanceof Error && cause.name === "AbortError") throw new NativeDmgCommandFailure( - "cancelled", + { reason: "cancelled" }, "DMG operation cancelled", output?.stdout ?? "", { cause }, @@ -99,7 +108,7 @@ const createSystemHost = ( cause, }; throw new NativeDmgCommandFailure( - commandFailureReason(cause, arguments_[0]), + classifyCommandFailure(cause, arguments_[0]), `hdiutil ${arguments_[0] ?? "operation"} failed: ${describeCommandFailure(cause, arguments_)}`, output?.stdout ?? "", { cause, processNotStarted: processNotStarted(cause) }, @@ -348,8 +357,7 @@ export class NativeDmgArtifactReader implements ArtifactReader { } async #attach(signal?: AbortSignal): Promise { - await runChecked(this.host, ["verify", this.path], signal); - this.#provenance.push(command(["verify", this.path], ["read"])); + await this.#verify(signal); const baseline = await this.#readInfo(); this.#baselineDevices = new Set( baseline.images.flatMap((image) => @@ -431,6 +439,40 @@ export class NativeDmgArtifactReader implements ArtifactReader { } } + async #verify(signal?: AbortSignal): Promise { + const arguments_ = ["verify", this.path]; + const deadline = performance.now() + HDIUTIL_COMMAND_TIMEOUT_MS; + for (let attempt = 0; ; attempt += 1) { + if (signal?.aborted === true) + throw new NativeDmgCommandFailure( + { reason: "cancelled" }, + "DMG operation cancelled", + "", + { cause: signal.reason }, + ); + try { + await runChecked(this.host, arguments_, signal, { + timeoutMs: Math.max(1, Math.ceil(deadline - performance.now())), + }); + this.#provenance.push(command(arguments_, ["read"])); + return; + } catch (cause: unknown) { + if (!(cause instanceof NativeDmgCommandFailure)) throw cause; + this.#provenance.push(command(arguments_, ["read"], cause.exitCode)); + const delayMs = VERIFY_SETTLE_DELAYS_MS[attempt]; + // Retry only the producer's explicit transient diagnostic, before any mount. + if ( + cause.verifyDiagnostic !== "Resource temporarily unavailable" || + delayMs === undefined || + deadline - performance.now() <= delayMs + ) + throw cause; + await (this.host.delay ?? delay)(delayMs); + if (performance.now() >= deadline) throw cause; + } + } + } + async #readInfo(): Promise { const info = await runChecked(this.host, ["info", "-plist"], undefined, { timeoutMs: HDIUTIL_COMMAND_TIMEOUT_MS, @@ -501,14 +543,14 @@ const runChecked = async ( if (cause instanceof ArtifactReaderFailure) throw cause; if (cause instanceof Error && cause.name === "AbortError") throw new NativeDmgCommandFailure( - "cancelled", + { reason: "cancelled" }, "DMG operation cancelled", execFileOutputFailure(cause)?.stdout ?? "", { cause }, ); const output = execFileOutputFailure(cause); throw new NativeDmgCommandFailure( - commandFailureReason(cause, arguments_[0]), + classifyCommandFailure(cause, arguments_[0]), `hdiutil ${arguments_[0] ?? "operation"} failed: ${describeCommandFailure( cause, arguments_, @@ -527,17 +569,17 @@ const runChecked = async ( stdout: result.stdout, ...(result.stderr === undefined ? {} : { stderr: result.stderr }), }; - const reason = commandFailureReason(failure, arguments_[0]); + const classification = classifyCommandFailure(failure, arguments_[0]); const details = describeCommandFailure(failure, arguments_); const unknownVerifyFailure = - arguments_[0] === "verify" && reason === "unavailable"; + arguments_[0] === "verify" && classification.reason === "unavailable"; throw new NativeDmgCommandFailure( - reason, + classification, unknownVerifyFailure ? `hdiutil verify failed; captured diagnostics do not establish the failure cause: ${details}` : `hdiutil ${arguments_[0] ?? "operation"} failed: ${details}`, result.stdout, - { cause: result.cause ?? failure }, + { cause: result.cause ?? failure, exitCode: result.exitCode }, ); } return { stdout: result.stdout, exitCode: 0 }; @@ -587,20 +629,36 @@ const processOutput = (cause: unknown, field: "stdout" | "stderr"): string => { return typeof value === "string" ? value : ""; }; -const commandFailureReason = ( +const classifyCommandFailure = ( cause: unknown, operation: string | undefined, -): ArtifactReaderFailure["reason"] => { - if (typeof cause !== "object" || cause === null) return "unavailable"; +): { + readonly reason: ArtifactReaderFailure["reason"]; + readonly verifyDiagnostic?: string; +} => { + if (typeof cause !== "object" || cause === null) + return { reason: "unavailable" }; const code = Reflect.get(cause, "code"); const exitCode = Reflect.get(cause, "exitCode"); - if (typeof code === "number" || typeof exitCode === "number") - return operation === "verify" ? verifyFailureReason(cause) : "unavailable"; + if (typeof code === "number" || typeof exitCode === "number") { + if (operation !== "verify") return { reason: "unavailable" }; + const diagnostic = verifyFailureDiagnostic( + processOutput(cause, "stdout"), + processOutput(cause, "stderr"), + ); + return { + reason: verifyFailureReason(diagnostic), + ...(diagnostic === undefined ? {} : { verifyDiagnostic: diagnostic }), + }; + } if (code === "ENOENT") { const syscall = Reflect.get(cause, "syscall"); - return typeof syscall === "string" && syscall.startsWith("spawn") - ? "unavailable" - : "io"; + return { + reason: + typeof syscall === "string" && syscall.startsWith("spawn") + ? "unavailable" + : "io", + }; } if ( code === "EACCES" || @@ -613,17 +671,13 @@ const commandFailureReason = ( code === "EMFILE" || code === "ENFILE" ) - return "io"; - return "unavailable"; + return { reason: "io" }; + return { reason: "unavailable" }; }; const verifyFailureReason = ( - cause: unknown, + diagnostic: string | undefined, ): ArtifactReaderFailure["reason"] => { - const diagnostic = verifyFailureDiagnostic( - processOutput(cause, "stdout"), - processOutput(cause, "stderr"), - ); switch (diagnostic) { // hdiutil follows AppleLanguages, so en-GB and en-AU spell it "recognised". case "image not recognized": @@ -656,11 +710,12 @@ const verifyFailureDiagnostic = ( const command = ( arguments_: readonly string[], effects: ArtifactCommand["effects"], + exitCode: number | null = 0, ): ArtifactCommand => ({ tool: "/usr/bin/hdiutil", arguments: [...arguments_], tool_version: null, executable_sha256: null, - exit_code: 0, + exit_code: exitCode, effects, }); diff --git a/src/artifacts/SafeOutputTree.ts b/src/artifacts/SafeOutputTree.ts index 4bb4cfe1a..73885ad05 100644 --- a/src/artifacts/SafeOutputTree.ts +++ b/src/artifacts/SafeOutputTree.ts @@ -280,9 +280,11 @@ export class SafeOutputTree { } /** Sync the owned output tree and prevent further writes through this instance. */ - async commit(): Promise { + async commit(signal?: AbortSignal): Promise { this.#assertWritable(); + abortIfNeeded(signal); await this.#assertOwnedDirectories(); + abortIfNeeded(signal); // Windows has no directory fsync; file contents are already synced in write(). if (this.platform === "win32") { this.#published = true; @@ -315,6 +317,7 @@ export class SafeOutputTree { ); await output.handle.sync(); await parent.handle.sync(); + abortIfNeeded(signal); this.#published = true; } catch (cause: unknown) { sync = { kind: "failed", cause }; @@ -336,23 +339,26 @@ export class SafeOutputTree { closeFailure, this.#outputRoot, ); - if (sync.kind === "failed") - throw ArtifactReaderFailure.withCleanup( - new ArtifactReaderFailure( - "path", - "Could not durably sync extraction output", - { cause: sync.cause }, - ), - cleanup, - ); + if (sync.kind === "failed") { + const primary = isCancellationFailure(sync.cause) + ? sync.cause + : new ArtifactReaderFailure( + "path", + "Could not durably sync extraction output", + { cause: sync.cause }, + ); + throw ArtifactReaderFailure.withCleanup(primary, cleanup); + } throw ArtifactReaderFailure.withCleanup(closeFailure, cleanup); } - if (sync.kind === "failed") + if (sync.kind === "failed") { + if (isCancellationFailure(sync.cause)) throw sync.cause; throw new ArtifactReaderFailure( "path", "Could not durably sync extraction output", { cause: sync.cause }, ); + } } /** Remove only this operation's unsealed tree and verify absence. */ @@ -579,6 +585,11 @@ const normalizeDestinationPath = ( "path", `Windows destination cannot materialize artifact path as a regular file: ${path}; ':' denotes alternate data stream syntax.`, ); + if (platform === "win32" && /[\u0001-\u001f]/u.test(path)) + throw new ArtifactReaderFailure( + "path", + `Windows destination cannot materialize artifact path: ${JSON.stringify(path)}; Windows names cannot contain U+0001-U+001F.`, + ); return path; }; @@ -590,6 +601,11 @@ const abortIfNeeded = (signal?: AbortSignal): void => { ); }; +const isCancellationFailure = ( + cause: unknown, +): cause is ArtifactReaderFailure => + cause instanceof ArtifactReaderFailure && cause.reason === "cancelled"; + const isAlreadyExists = (cause: unknown): boolean => cause instanceof Error && "code" in cause && cause.code === "EEXIST"; diff --git a/src/artifacts/ZipArtifactReader.ts b/src/artifacts/ZipArtifactReader.ts index 11c68557b..dfbee8b27 100644 --- a/src/artifacts/ZipArtifactReader.ts +++ b/src/artifacts/ZipArtifactReader.ts @@ -255,10 +255,29 @@ const decodeZipEntryText = ( encoding: string, type: "filename" | "comment", ): string | undefined => { - if (type !== "filename" || encoding !== "utf-8") return undefined; - return decodeStrictZipUtf8(bytes, "ZIP filename is not valid UTF-8"); + if (type !== "filename") return undefined; + if (encoding === "utf-8") + return decodeStrictZipUtf8(bytes, "ZIP filename is not valid UTF-8"); + return encoding === "cp437" ? decodeCp437(bytes) : undefined; }; +/** CP437 characters for bytes 0x80-0xFF. */ +const CP437_HIGH_HALF = + "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\u00A0"; + +/** + * Decode a legacy ZIP name with the Unicode CP437 mapping, which Python's + * zipfile also uses: bytes below 0x80 are ASCII. zip.js shows 0x01-0x1F and + * 0x7F as IBM PC display glyphs, which turns the macOS folder icon file + * `Icon\r` into `Icon♪`. + */ +const decodeCp437 = (bytes: Uint8Array): string => + Array.from(bytes, (byte) => + byte < 0x80 + ? String.fromCharCode(byte) + : CP437_HIGH_HALF.charAt(byte - 0x80), + ).join(""); + const zipEntryPath = (entry: Entry): string => { const field = entry.extraFieldUnicodePath; if (field?.valid !== true) return entry.filename; diff --git a/src/artifacts/apple/NibArchive.ts b/src/artifacts/apple/NibArchive.ts index bd8ef12ca..c673184f4 100644 --- a/src/artifacts/apple/NibArchive.ts +++ b/src/artifacts/apple/NibArchive.ts @@ -134,7 +134,14 @@ export const decodeNibArchive = ( const value = values.get(index); if (value === undefined) continue; const key = keys[value.key_index]; - if (key !== undefined) fields[key] = value.value; + if (key !== undefined) + // Archive keys are data, including the legacy __proto__ setter name. + Object.defineProperty(fields, key, { + value: value.value, + enumerable: true, + configurable: true, + writable: true, + }); } return [{ id, class_name: className, values: fields }]; }); @@ -519,7 +526,8 @@ const decodeUtf8 = ( label: string, ): string => { try { - return new TextDecoder("utf-8", { fatal: true }).decode( + // These are length-prefixed names, not standalone text documents. + return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode( bytes.subarray(start, end), ); } catch (cause: unknown) { diff --git a/src/artifacts/extraction/ArtifactExtraction.ts b/src/artifacts/extraction/ArtifactExtraction.ts index 6306a08bf..8cad3543e 100644 --- a/src/artifacts/extraction/ArtifactExtraction.ts +++ b/src/artifacts/extraction/ArtifactExtraction.ts @@ -17,6 +17,7 @@ import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js"; import { SafeOutputTree } from "../SafeOutputTree.js"; import { SafeOutputTreeCreationFailure } from "../SafeOutputTreeCreationFailure.js"; import { ZipArtifactReader } from "../ZipArtifactReader.js"; +import { isZipPackageFormat } from "../../domain/zipPackageFormat.js"; import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js"; import { artifactExtractionResultSchema, @@ -248,7 +249,7 @@ const materializeSelection = async ({ compareUnicodeCodePoints(left.relative_path, right.relative_path), ); completed = createExtractionResult(input, inventory, selected, extracted); - await output.commit(); + await output.commit(signal); return completed; } catch (cause: unknown) { const cleanupFailures = await releaseExtractionOwners( @@ -400,13 +401,6 @@ interface ExtractionInventory { readonly integrityContradictions: readonly IntegrityContradiction[]; } -const ZIP_FORMATS = ["ipa", "apk", "msix", "appx", "zip"] as const; - -const isZipFormat = ( - format: BinaryTarget["format"], -): format is (typeof ZIP_FORMATS)[number] => - (ZIP_FORMATS as readonly string[]).includes(format); - /** * Refuse a format without an extraction reader before inventory work starts. * The target kind, not the host, is unsupported by extraction. The error keeps @@ -422,7 +416,7 @@ const requireExtractableFormat = async ( !directory && format !== "asar" && !isMachOFormat(format) && - !isZipFormat(format) + !isZipPackageFormat(format) ) throw new AnalysisUnsupportedTargetError( "extract_artifact", @@ -443,7 +437,7 @@ const createReader = async ( if (await requireExtractableFormat(path, input)) return new DirectoryArtifactReader(path); if (format === "asar") return new AsarArtifactReader(path); - if (isZipFormat(format)) return new ZipArtifactReader(path, format); + if (isZipPackageFormat(format)) return new ZipArtifactReader(path, format); return new MachOSliceArtifactReader(path, input.environment); }; diff --git a/src/artifacts/readStableArtifact.ts b/src/artifacts/readStableArtifact.ts index e35a20783..808133d89 100644 --- a/src/artifacts/readStableArtifact.ts +++ b/src/artifacts/readStableArtifact.ts @@ -38,6 +38,13 @@ const afterValidation = async ( } }; +const assertReadActive = (signal: AbortSignal | undefined): void => { + if (signal?.aborted) + throw new ArtifactReaderFailure("cancelled", "Artifact read cancelled", { + cause: signal.reason, + }); +}; + /** Read one bounded regular file and reject replacement or in-place changes. */ export const readStableArtifact = async ( path: string, @@ -46,7 +53,7 @@ export const readStableArtifact = async ( fileSystem: StableArtifactFileSystem = FILE_SYSTEM, resourceScope?: ArtifactResourceScope, ): Promise<{ readonly bytes: Buffer; readonly sha256: string }> => { - signal?.throwIfAborted(); + assertReadActive(signal); const before = await fileSystem.lstat(path); if (!before.isFile() || before.isSymbolicLink()) throw new ArtifactReaderFailure( @@ -84,7 +91,7 @@ export const readStableArtifact = async ( autoClose: false, highWaterMark: 65536, })) { - signal?.throwIfAborted(); + assertReadActive(signal); const value: unknown = chunk; if (!Buffer.isBuffer(value)) throw new ArtifactReaderFailure( @@ -120,6 +127,7 @@ export const readStableArtifact = async ( "integrity", `Artifact changed during read: ${path}`, ); + assertReadActive(signal); const bytes = Buffer.concat(chunks, count); return { bytes, sha256: createHash("sha256").update(bytes).digest("hex") }; } catch (cause: unknown) { diff --git a/src/browser/BrowserScenarioPartialObservation.ts b/src/browser/BrowserScenarioPartialObservation.ts index ca0df4273..a573f600f 100644 --- a/src/browser/BrowserScenarioPartialObservation.ts +++ b/src/browser/BrowserScenarioPartialObservation.ts @@ -91,7 +91,7 @@ export const browserScenarioCaptureData = (input: { network_content: input.scenario.capture.network, event_families: [...new Set(input.scenario.capture.events)].sort(), }, - duration_ms: Date.now() - input.startedAt, + duration_ms: Math.max(0, Math.round(performance.now() - input.startedAt)), steps: [...input.steps], events, limitations: [ diff --git a/src/browser/PlaywrightBrowserScenarioProvider.test.ts b/src/browser/PlaywrightBrowserScenarioProvider.test.ts index aacf766ad..734e32426 100644 --- a/src/browser/PlaywrightBrowserScenarioProvider.test.ts +++ b/src/browser/PlaywrightBrowserScenarioProvider.test.ts @@ -303,6 +303,7 @@ describe("PlaywrightBrowserScenarioProvider", () => { }); expect(result.value.limitations).toContain(session.eventGaps[0]); }); + it("returns an initial state and every step beyond the former action ceiling", async () => { const session = new FakeSession("launch"); const provider = new PlaywrightBrowserScenarioProvider(() => @@ -376,6 +377,35 @@ describe("PlaywrightBrowserScenarioProvider", () => { }); }); +describe("PlaywrightBrowserScenarioProvider timing", () => { + it("keeps capture elapsed values valid across a backward wall-clock jump", async () => { + let wallClock = 10_000; + vi.spyOn(Date, "now").mockImplementation(() => wallClock); + const session = new FakeSession("launch"); + session.onPerform = () => { + wallClock = 1; + }; + const provider = new PlaywrightBrowserScenarioProvider(() => + Promise.resolve(session), + ); + + try { + const result = await provider.captureScenario(scenario()); + if (!result.ok) throw result.error; + expect(wallClock).toBe(1); + expect(Number.isInteger(result.value.duration_ms)).toBe(true); + expect(result.value.duration_ms).toBeGreaterThanOrEqual(0); + expect( + result.value.steps.every( + ({ elapsed_ms }) => Number.isInteger(elapsed_ms) && elapsed_ms >= 0, + ), + ).toBe(true); + } finally { + vi.restoreAllMocks(); + } + }); +}); + describe("PlaywrightBrowserScenarioProvider comparison coverage", () => { it("keeps quiet captures with different event families from comparing unchanged", async () => { const capture = async (events: readonly BrowserScenarioEventFamily[]) => { diff --git a/src/browser/PlaywrightBrowserScenarioProvider.ts b/src/browser/PlaywrightBrowserScenarioProvider.ts index a3c6d6a62..b0833e89c 100644 --- a/src/browser/PlaywrightBrowserScenarioProvider.ts +++ b/src/browser/PlaywrightBrowserScenarioProvider.ts @@ -172,7 +172,7 @@ const executeStep = async (input: { ), }); - const actionStartedAt = Date.now(); + const actionStartedAt = performance.now(); session.setStep(stepIndex); const requestCancelled = (): boolean => signal?.aborted === true; let outcome: BrowserScenarioStepOutcome = { @@ -200,7 +200,7 @@ const executeStep = async (input: { stepId: action.step_id, action: action.action, ...outcome, - elapsedMs: Date.now() - actionStartedAt, + elapsedMs: Math.max(0, Math.round(performance.now() - actionStartedAt)), beforeUrl, afterUrl: session.sanitizeUrl(session.currentUrl()), eventStart, @@ -233,7 +233,7 @@ const runScenario = async ( ): Promise => { if (options.signal?.aborted === true) throw new BrowserObservationError(OPERATION, "cancelled"); - const startedAt = Date.now(); + const startedAt = performance.now(); const session = await openSession(scenario, { ...(options.signal === undefined ? {} : { signal: options.signal }), retainCleanup, @@ -250,7 +250,7 @@ const runScenario = async ( await initialStep({ session, scenario, - elapsedMs: Date.now() - startedAt, + elapsedMs: Math.max(0, Math.round(performance.now() - startedAt)), signal: options.signal, }), ); diff --git a/src/browser/PlaywrightElectronActiveActions.ts b/src/browser/PlaywrightElectronActiveActions.ts index d59afb676..7bb9ec83b 100644 --- a/src/browser/PlaywrightElectronActiveActions.ts +++ b/src/browser/PlaywrightElectronActiveActions.ts @@ -72,7 +72,7 @@ export const runElectronActions = async ( ): Promise => { const actions: ElectronActions = []; for (const action of input.actions) { - const actionStartedAt = Date.now(); + const actionStartedAt = performance.now(); const windowIndex = actionWindowIndex(action); let selectedWindow: Page | undefined; try { @@ -107,7 +107,10 @@ export const runElectronActions = async ( target: selectedWindow === undefined ? null : `window:${String(windowIndex)}`, status: "completed", - elapsed_ms: Date.now() - actionStartedAt, + elapsed_ms: Math.max( + 0, + Math.round(performance.now() - actionStartedAt), + ), error: null, }); } catch (cause: unknown) { @@ -118,7 +121,10 @@ export const runElectronActions = async ( target: selectedWindow === undefined ? null : `window:${String(windowIndex)}`, status: options.signal?.aborted ? "cancelled" : "failed", - elapsed_ms: Date.now() - actionStartedAt, + elapsed_ms: Math.max( + 0, + Math.round(performance.now() - actionStartedAt), + ), error: safeActionErrorMessage(cause), }); break; @@ -366,7 +372,7 @@ export const runWithExecutionLimits = async ( new Promise((_, reject) => { timer = setTimeout( () => reject(new BrowserObservationError(OPERATION, "timeout")), - Math.max(1, deadline - Date.now()), + Math.max(1, deadline - performance.now()), ); }), ); diff --git a/src/browser/PlaywrightElectronActiveProvider.ts b/src/browser/PlaywrightElectronActiveProvider.ts index 4b6e6bb14..23379524d 100644 --- a/src/browser/PlaywrightElectronActiveProvider.ts +++ b/src/browser/PlaywrightElectronActiveProvider.ts @@ -86,7 +86,7 @@ export class PlaywrightElectronActiveProvider implements ElectronActiveObservati if (options.signal?.aborted === true) throw new BrowserObservationError(OPERATION, "cancelled"); await prepareProcessOwnershipInspection(options.signal); - const startupDeadline = Date.now() + STARTUP_TIMEOUT_MS; + const startupDeadline = performance.now() + STARTUP_TIMEOUT_MS; paths = { executable: input.executable_path, application: input.application_path, @@ -101,7 +101,7 @@ export class PlaywrightElectronActiveProvider implements ElectronActiveObservati cwd: paths.root, env: safeElectronEnvironment(this.environment, runId), args: ["-r", hookPath, paths.application, ...input.args], - timeout: Math.max(1, startupDeadline - Date.now()), + timeout: Math.max(1, startupDeadline - performance.now()), }); const leaderPid = application.process().pid; if ( @@ -128,7 +128,7 @@ export class PlaywrightElectronActiveProvider implements ElectronActiveObservati const state = await runWithExecutionLimits( readApplicationState(application), undefined, - options.signal?.aborted ? Date.now() + 5_000 : undefined, + options.signal?.aborted ? performance.now() + 5_000 : undefined, ); capture = projectElectronActiveCapture(paths, actions, state); outcome = options.signal?.aborted @@ -187,7 +187,7 @@ export class PlaywrightElectronActiveProvider implements ElectronActiveObservati await runWithExecutionLimits( application.close(), undefined, - Date.now() + 5_000, + performance.now() + 5_000, ); } catch (cause: unknown) { closeError = cause; diff --git a/src/browser/PlaywrightExecutionBoundary.test.ts b/src/browser/PlaywrightExecutionBoundary.test.ts index 323b4506c..51df81701 100644 --- a/src/browser/PlaywrightExecutionBoundary.test.ts +++ b/src/browser/PlaywrightExecutionBoundary.test.ts @@ -7,7 +7,10 @@ import { } from "../domain/analysisErrorCore.js"; describe("withPlaywrightExecutionBoundary", () => { - afterEach(() => vi.useRealTimers()); + afterEach(() => { + vi.useRealTimers(); + vi.restoreAllMocks(); + }); it("rejects work that exceeds its absolute remaining duration", async () => { vi.useFakeTimers(); @@ -31,4 +34,20 @@ describe("withPlaywrightExecutionBoundary", () => { controller.abort(); await expect(result).rejects.toBeInstanceOf(AnalysisCancelledError); }); + + it("keeps its timeout stable across a wall-clock jump", async () => { + vi.spyOn(Date, "now") + .mockReturnValueOnce(1_000) + .mockReturnValue(10_000_000); + + await expect( + withPlaywrightExecutionBoundary( + () => + new Promise((resolve) => + setTimeout(() => resolve("done"), 5), + ), + 1_000, + ), + ).resolves.toBe("done"); + }); }); diff --git a/src/browser/PlaywrightExecutionBoundary.ts b/src/browser/PlaywrightExecutionBoundary.ts index 9fd21fcf3..759fcd484 100644 --- a/src/browser/PlaywrightExecutionBoundary.ts +++ b/src/browser/PlaywrightExecutionBoundary.ts @@ -19,10 +19,10 @@ export const withPlaywrightExecutionBoundary = ( let settled = false; let timer: ReturnType | undefined; const deadline = - timeoutMs === undefined ? undefined : Date.now() + timeoutMs; + timeoutMs === undefined ? undefined : performance.now() + timeoutMs; const scheduleTimeout = (): void => { if (deadline === undefined) return; - const remaining = deadline - Date.now(); + const remaining = deadline - performance.now(); if (remaining <= 0) { fail(new AnalysisTimeoutError(OPERATION, timeoutMs ?? 0)); return; diff --git a/src/browser/PlaywrightScenarioSession.ts b/src/browser/PlaywrightScenarioSession.ts index 486f555ea..949193b7c 100644 --- a/src/browser/PlaywrightScenarioSession.ts +++ b/src/browser/PlaywrightScenarioSession.ts @@ -133,7 +133,7 @@ export class PlaywrightScenarioSession implements BrowserScenarioSessionPort { const secrets = BrowserScenarioSecrets.resolve(scenario, environment); if (secrets === undefined) throw new BrowserObservationError(OPERATION, "secret_unavailable"); - const startedAt = Date.now(); + const startedAt = performance.now(); const opening = openPlaywrightScenarioBrowser(scenario, environment, { signal: options.signal, ...(options.retainCleanup === undefined diff --git a/src/browser/WebSourceMapFetcher.ts b/src/browser/WebSourceMapFetcher.ts index 0b17df0cb..c4bae782a 100644 --- a/src/browser/WebSourceMapFetcher.ts +++ b/src/browser/WebSourceMapFetcher.ts @@ -2,7 +2,6 @@ import * as t from "@babel/types"; import { decodeValidatedSourceMapLeaves, isBeforeSourceMapLeafStop, - resolveSourceMapSource, } from "../javascript/sourceMaps/DecodedSourceMap.js"; import { sanitizeBrowserUrl } from "../domain/browserObservation.js"; @@ -21,6 +20,7 @@ import { webSourceMapsSchema } from "../domain/webBundleAnalysis.js"; import { createWebTextArtifact } from "../domain/webContentArtifact.js"; import { safeParseJson } from "../domain/safeJson.js"; import { sourceMapJsonText } from "../domain/sourceMapEnvelope.js"; +import { resolveJavaScriptSourceMapUrl } from "../domain/javascript/javascriptSourceMapPaths.js"; import { jsonParts } from "../domain/jsonSerialization.js"; import { inspectSourceMapValue, @@ -86,7 +86,7 @@ export const fetchWebSourceMaps = async ( signal?.addEventListener("abort", abortFromCaller, { once: true }); const operationSignal = operationController.signal; const deadlineAt = - Date.now() + (host.timeoutMs ?? SOURCE_MAP_FETCH_TIMEOUT_MS); + performance.now() + (host.timeoutMs ?? SOURCE_MAP_FETCH_TIMEOUT_MS); const budget = { retainedBytes: 0, deadlineAt, @@ -110,7 +110,7 @@ export const fetchWebSourceMaps = async ( } const expandedBytesBeforeItem = budget.decodedRecords.expandedBytes; budget.decodedRecords.expandedBytes += reservation; - if (operationSignal.aborted || Date.now() >= deadlineAt) { + if (operationSignal.aborted || performance.now() >= deadlineAt) { items.push( emptySourceMapItem( request, @@ -789,7 +789,7 @@ const checkOperation = ( ): void => { if (callerSignal?.aborted === true) throw callerSignal.reason; if (operationSignal?.aborted === true) throw operationSignal.reason; - if (Date.now() >= deadlineAt) throw new SourceMapDeadlineError(); + if (performance.now() >= deadlineAt) throw new SourceMapDeadlineError(); }; const approvedUrl = ( @@ -867,7 +867,11 @@ const preflightResolvedSourceBytes = ( const sourceKey = source; let resolved = sourcesForRoot.get(sourceKey); if (resolved === undefined) - resolved = resolveSourceMapSource(source, map.sourceRoot, mapUrl); + resolved = resolveJavaScriptSourceMapUrl( + source, + map.sourceRoot, + mapUrl, + ); const bytes = Buffer.byteLength(resolved, "utf8"); if (bytes > SOURCE_MAP_RESPONSE_BYTES - resolvedBytes) throw resolvedSourceLimitFailure(); diff --git a/src/browser/assets/LocalWebScriptArtifacts.ts b/src/browser/assets/LocalWebScriptArtifacts.ts index c5d6ea8ed..51fc14c45 100644 --- a/src/browser/assets/LocalWebScriptArtifacts.ts +++ b/src/browser/assets/LocalWebScriptArtifacts.ts @@ -1,6 +1,7 @@ import { lstat, realpath } from "node:fs/promises"; import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; +import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { normalizeArtifactPath } from "../../artifacts/ArtifactPaths.js"; import type { WebScriptArtifactPort } from "../../application/WebScriptArtifactPort.js"; @@ -19,10 +20,36 @@ import { /** Read one digest-verified captured source under the manifest's current location. */ export class LocalWebScriptArtifacts implements WebScriptArtifactPort { - constructor(readonly operation: WebArtifactReadContext["operation"]) {} + constructor( + readonly operation: WebArtifactReadContext["operation"], + readonly resources = new ArtifactResourceScope(), + ) {} + + close(): Promise { + return this.resources.close(); + } /** Read the selected source; relocated exports retain their reported original root. */ async load(input: SelectedWebScriptInput, options?: ExecutionOptions) { + try { + return await this.resources.run(() => this.#load(input, options)); + } catch (cause: unknown) { + return err( + webArtifactReadError( + cause, + { + operation: this.operation, + field: ["manifest_path"], + targetPath: input.manifest_path, + callerSelected: true, + }, + options?.signal, + ), + ); + } + } + + async #load(input: SelectedWebScriptInput, options?: ExecutionOptions) { let field: readonly (string | number)[] = ["manifest_path"]; let targetPath = input.manifest_path; let callerSelected = true; @@ -31,6 +58,7 @@ export class LocalWebScriptArtifacts implements WebScriptArtifactPort { input.manifest_path, 32 * 1024 * 1024, options?.signal, + this.resources, ); const manifest = webScriptExportManifestSchema.parse(manifestBytes.value); field = ["script_index"]; @@ -65,6 +93,8 @@ export class LocalWebScriptArtifacts implements WebScriptArtifactPort { sourcePath, 16 * 1024 * 1024, options?.signal, + undefined, + this.resources, ); await assertContained(root, sourcePath); if ( diff --git a/src/browser/assets/PublishWebScripts.ts b/src/browser/assets/PublishWebScripts.ts index 2db5d7dcf..ba886f00e 100644 --- a/src/browser/assets/PublishWebScripts.ts +++ b/src/browser/assets/PublishWebScripts.ts @@ -113,7 +113,7 @@ export const publishWebScripts = async ( options.signal, ); options.signal?.throwIfAborted(); - await tree.commit(); + await tree.commit(options.signal); return result; } catch (cause: unknown) { if (cause instanceof SafeOutputTreeCreationFailure) tree = cause.tree; diff --git a/src/browser/assets/WebArtifactReads.ts b/src/browser/assets/WebArtifactReads.ts index cd142f62f..e045e1575 100644 --- a/src/browser/assets/WebArtifactReads.ts +++ b/src/browser/assets/WebArtifactReads.ts @@ -1,5 +1,6 @@ import { z } from "zod"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; +import type { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import type { AnalysisError } from "../../domain/analysisErrorBase.js"; import { @@ -9,6 +10,8 @@ import { } from "../../domain/analysisErrorCore.js"; import { ArtifactOperationError } from "../../domain/artifactOperationError.js"; import { ProviderAdapterError } from "../../domain/providerAdapterError.js"; +import { ProviderCleanupError } from "../../domain/providerCleanupError.js"; +import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; import { safeParseJson } from "../../domain/safeJson.js"; /** The selected artifact and input field owning a reader failure. */ @@ -42,8 +45,15 @@ export const readWebArtifactJson = async ( path: string, maximumBytes: number, signal?: AbortSignal, + resourceScope?: ArtifactResourceScope, ) => { - const data = await readStableArtifact(path, maximumBytes, signal); + const data = await readStableArtifact( + path, + maximumBytes, + signal, + undefined, + resourceScope, + ); const value = safeParseJson(decodeWebArtifact(data.bytes)); if (!value.ok) throw new WebArtifactFormatFailure(value.error); return { ...data, value: value.value }; @@ -55,8 +65,30 @@ export const webArtifactReadError = ( context: WebArtifactReadContext, signal?: AbortSignal, ): AnalysisError => { + if (cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined) { + const primary = + signal?.aborted === true + ? new AnalysisCancelledError(context.operation, { cause }) + : new ArtifactOperationError( + context.operation, + cause.reason, + cause.details, + cause.message, + { cause }, + ); + return analysisErrorWithCleanupFailure( + primary, + new ProviderCleanupError( + "captured-web-artifacts", + cause.cleanup.resources, + { reason: cause.cleanup.reason }, + { cause, operation: context.operation }, + ), + context.operation, + ); + } if (signal?.aborted === true) - return new AnalysisCancelledError(context.operation); + return new AnalysisCancelledError(context.operation, { cause }); const selection = context.callerSelected ? selectedFileError(cause, context) : undefined; diff --git a/src/browser/assets/WebSourceLocationArtifacts.ts b/src/browser/assets/WebSourceLocationArtifacts.ts index 21c483bd8..733069469 100644 --- a/src/browser/assets/WebSourceLocationArtifacts.ts +++ b/src/browser/assets/WebSourceLocationArtifacts.ts @@ -1,6 +1,7 @@ import type { WebSourceLocationArtifactPort } from "../../application/WebSourceLocationPorts.js"; import type { WebScriptArtifactPort } from "../../application/WebScriptArtifactPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; +import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { WEB_SOURCE_MAP_LIMITS, @@ -12,14 +13,64 @@ import { decodeWebArtifact, webArtifactReadError } from "./WebArtifactReads.js"; /** Read one verified capture source and the caller-selected map, without fetching. */ export class LocalWebSourceLocationArtifacts implements WebSourceLocationArtifactPort { + readonly scripts: WebScriptArtifactPort; + readonly #resources: ArtifactResourceScope; + constructor( - readonly scripts: WebScriptArtifactPort = new LocalWebScriptArtifacts( - "trace_web_source_location", - ), - ) {} + scripts?: WebScriptArtifactPort, + resources = scripts instanceof LocalWebScriptArtifacts + ? scripts.resources + : new ArtifactResourceScope(), + ) { + this.#resources = resources; + this.scripts = + scripts ?? + new LocalWebScriptArtifacts("trace_web_source_location", resources); + } + + async close(): Promise { + const closeScript = + this.scripts instanceof LocalWebScriptArtifacts && + this.scripts.resources === this.#resources + ? undefined + : this.scripts.close?.bind(this.scripts); + const results = await Promise.allSettled([ + Promise.resolve().then(() => this.#resources.close()), + ...(closeScript === undefined + ? [] + : [Promise.resolve().then(closeScript)]), + ]); + const failures = results.flatMap((result) => + result.status === "rejected" ? [result.reason] : [], + ); + if (failures.length > 0) + throw new AggregateError( + failures, + "Web source-location artifact cleanup failed", + ); + } /** Preserve actual map identity separately from the selected deployment URL. */ async load(input: WebSourceLocationInput, options?: ExecutionOptions) { + try { + return await this.#resources.run(() => this.#load(input, options)); + } catch (cause: unknown) { + return err( + webArtifactReadError( + cause, + { + operation: "trace_web_source_location", + field: ["source_map", "path"], + targetPath: input.source_map.path, + callerSelected: true, + }, + options?.signal, + ), + ); + } + } + + async #load(input: WebSourceLocationInput, options?: ExecutionOptions) { const loaded = await this.scripts.load(input, options); if (!loaded.ok) return loaded; try { @@ -27,6 +78,8 @@ export class LocalWebSourceLocationArtifacts implements WebSourceLocationArtifac input.source_map.path, WEB_SOURCE_MAP_LIMITS.mapBytes, options?.signal, + undefined, + this.#resources, ); return ok({ ...loaded.value, diff --git a/src/browser/history/CaptureFailures.test.ts b/src/browser/history/CaptureFailures.test.ts index ff7be71a6..047722ac5 100644 --- a/src/browser/history/CaptureFailures.test.ts +++ b/src/browser/history/CaptureFailures.test.ts @@ -4,7 +4,7 @@ import { projectAnalysisError } from "../../domain/analysisErrorProjection.js"; import { analysisErrorProjectionSchema } from "../../contracts/errorSchemas.js"; import { inspectWebNetworkCaptureInputSchema } from "../../domain/webNetworkCapture.js"; import { historicalCaptureFailure } from "./CaptureFailures.js"; -import { HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES } from "./CaptureRelease.js"; +import { NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES } from "./CaptureRelease.js"; import { redactExplicitFailure } from "../../domain/explicitSensitiveFailure.js"; import { OwnedCommandFailure } from "../../process/OwnedCommand.js"; @@ -118,7 +118,7 @@ it.each([ }, }); // The enforced limit is reported only where Bun runs on Windows. - if (HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null) + if (NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null) expect(JSON.stringify(projected)).not.toContain( "process_memory_limit_bytes", ); @@ -126,12 +126,12 @@ it.each([ expect(projected).toMatchObject({ details: { reported_limits: { - process_memory_limit_bytes: HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, + process_memory_limit_bytes: NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, }, }, remediation: { action: expect.stringContaining( - `${String(HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES)} bytes`, + `${String(NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES)} bytes`, ), }, }); diff --git a/src/browser/history/CaptureFailures.ts b/src/browser/history/CaptureFailures.ts index 228541545..b525126a5 100644 --- a/src/browser/history/CaptureFailures.ts +++ b/src/browser/history/CaptureFailures.ts @@ -18,9 +18,9 @@ import { } from "../../domain/webNetworkCapture.js"; import { OwnedCommandFailure } from "../../process/OwnedCommand.js"; import { - HAR_CAPTURE_HEAP_ENFORCED, - HAR_CAPTURE_HEAP_LIMITS, - HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, + NODE_CAPTURE_HEAP_ENFORCED, + NODE_CAPTURE_HEAP_LIMITS, + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, } from "./CaptureRelease.js"; const OPERATION = "inspect_web_network_capture"; @@ -78,7 +78,7 @@ export const historicalCaptureFailure = ( ); if ( phase === "decoder" && - input.format === "har" && + input.format !== "mitmproxy" && cause.reason === "process" && (cause.snapshot?.signal === "SIGABRT" || (cause.snapshot?.signal === null && cause.snapshot.exitCode === 134)) && @@ -86,7 +86,7 @@ export const historicalCaptureFailure = ( ) return captureMemoryFailure( input, - "The HAR decoder exhausted its fixed V8 heap", + `The ${input.format} decoder exhausted its fixed V8 heap`, cause, ); } @@ -195,15 +195,17 @@ export const captureMemoryFailure = ( format: input.format, maximum_input_bytes: WEB_NETWORK_CAPTURE_LIMITS.inputBytes, maximum_reply_bytes: WEB_NETWORK_CAPTURE_LIMITS.outputBytes, - ...(input.format === "har" && HAR_CAPTURE_HEAP_ENFORCED + ...(input.format !== "mitmproxy" && NODE_CAPTURE_HEAP_ENFORCED ? { - old_generation_heap_mib: HAR_CAPTURE_HEAP_LIMITS.oldGenerationMiB, - semi_space_heap_mib: HAR_CAPTURE_HEAP_LIMITS.semiSpaceMiB, + old_generation_heap_mib: NODE_CAPTURE_HEAP_LIMITS.oldGenerationMiB, + semi_space_heap_mib: NODE_CAPTURE_HEAP_LIMITS.semiSpaceMiB, } : {}), - ...(input.format === "har" && - HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES !== null - ? { process_memory_limit_bytes: HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES } + ...(input.format !== "mitmproxy" && + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES !== null + ? { + process_memory_limit_bytes: NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, + } : {}), ...(cause instanceof OwnedCommandFailure ? { @@ -214,7 +216,7 @@ export const captureMemoryFailure = ( }, { cause, - remediationAction: `Use a smaller capture exported by its producer, or another decoder with sufficient capacity for the original capture. Preserve the original for provenance; a subset does not establish complete-capture coverage.${input.format === "har" && HAR_CAPTURE_HEAP_ENFORCED ? ` REA's HAR old-generation heap is fixed at ${HAR_CAPTURE_HEAP_LIMITS.oldGenerationMiB} MiB; inherited NODE_OPTIONS cannot raise it.` : ""}${input.format === "har" && HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES !== null ? ` REA's HAR decoder process commit limit is fixed at ${String(HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES)} bytes.` : ""}`, + remediationAction: `Use a smaller capture exported by its producer, or another decoder with sufficient capacity for the original capture. Preserve the original for provenance; a subset does not establish complete-capture coverage.${input.format !== "mitmproxy" && NODE_CAPTURE_HEAP_ENFORCED ? ` REA's Node capture old-generation heap is fixed at ${NODE_CAPTURE_HEAP_LIMITS.oldGenerationMiB} MiB; inherited NODE_OPTIONS cannot raise it.` : ""}${input.format !== "mitmproxy" && NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES !== null ? ` REA's Node capture decoder process commit limit is fixed at ${String(NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES)} bytes.` : ""}`, ...(cause instanceof OwnedCommandFailure && cause.snapshot !== null ? { capturedOutput: { diff --git a/src/browser/history/CaptureFormatError.ts b/src/browser/history/CaptureFormatError.ts index fd7a9272d..a31b3057d 100644 --- a/src/browser/history/CaptureFormatError.ts +++ b/src/browser/history/CaptureFormatError.ts @@ -1,7 +1,7 @@ /** Expected malformed, unsupported or oversized producer data at a historical decoder boundary. */ export class CaptureFormatError extends Error { constructor( - readonly reason: "format" | "unsupported" | "input-limit", + readonly reason: "format" | "unsupported" | "input-limit" | "limit", message: string, readonly pointer = "", ) { diff --git a/src/browser/history/HarJson.ts b/src/browser/history/CaptureJson.ts similarity index 83% rename from src/browser/history/HarJson.ts rename to src/browser/history/CaptureJson.ts index 257630932..59743788a 100644 --- a/src/browser/history/HarJson.ts +++ b/src/browser/history/CaptureJson.ts @@ -2,6 +2,7 @@ import { visit } from "jsonc-parser"; import { LosslessNumber } from "lossless-json"; import { WEB_NETWORK_CAPTURE_LIMITS } from "../../domain/webNetworkCapture.js"; import { CaptureFormatError } from "./CaptureFormatError.js"; +import { TextDecoder } from "node:util"; type Frame = | { @@ -13,7 +14,10 @@ type Frame = | { kind: "array"; pointer: string; items: unknown[] }; /** Materialize upstream JSON events without duplicate folding, prototype setters or numeric rounding. */ -export const parseHarJson = (text: string): unknown => { +export const parseCaptureJson = ( + text: string, + format: "HAR" | "qlog", +): unknown => { const frames: Frame[] = []; let result: unknown; const valuePointer = (): string => { @@ -29,7 +33,7 @@ export const parseHarJson = (text: string): unknown => { if (frames.length > WEB_NETWORK_CAPTURE_LIMITS.depth) throw new CaptureFormatError( "input-limit", - "HAR exceeds the 64-level complete-evidence nesting budget.", + `${format} exceeds the 64-level complete-evidence nesting budget.`, valuePointer(), ); }; @@ -69,7 +73,7 @@ export const parseHarJson = (text: string): unknown => { if (frame.members.has(key)) throw new CaptureFormatError( "format", - "HAR JSON contains duplicate object members.", + `${format} JSON contains duplicate object members.`, ); frame.pendingKey = key; }, @@ -103,7 +107,7 @@ export const parseHarJson = (text: string): unknown => { throw new TypeError("JSON visitor emitted an unsupported literal."); }, onError: () => { - throw new CaptureFormatError("format", "HAR is malformed JSON."); + throw new CaptureFormatError("format", `${format} is malformed JSON.`); }, }, { @@ -114,3 +118,18 @@ export const parseHarJson = (text: string): unknown => { ); return result; }; + +/** UTF-8 JSON decoding skips one permitted BOM and rejects malformed bytes. */ +export const decodeCaptureText = ( + bytes: Uint8Array, + format: "HAR" | "qlog", +): string => { + try { + return new TextDecoder("utf-8", { fatal: true }).decode(bytes); + } catch { + throw new CaptureFormatError( + "format", + `${format} is not valid UTF-8 JSON.`, + ); + } +}; diff --git a/src/browser/history/CaptureRelease.ts b/src/browser/history/CaptureRelease.ts index d8af643aa..77f29df51 100644 --- a/src/browser/history/CaptureRelease.ts +++ b/src/browser/history/CaptureRelease.ts @@ -8,19 +8,19 @@ export const HAR_CAPTURE_PROVIDER_IDENTITY = { version: "har-schema@2.0.0;jsonc-parser@3.3.1;lossless-json@4.3.1", } as const; -/** Fixed V8 heap settings used by the owned HAR decoder process. */ -export const HAR_CAPTURE_HEAP_LIMITS = { +/** Fixed V8 heap settings used by the owned Node capture decoder process. */ +export const NODE_CAPTURE_HEAP_LIMITS = { oldGenerationMiB: 192, semiSpaceMiB: 8, } as const; -/** The HAR decoder runs on this executable; Bun accepts but ignores V8 heap flags. */ -export const HAR_CAPTURE_HEAP_ENFORCED = +/** The Node capture decoder runs on this executable; Bun accepts but ignores V8 heap flags. */ +export const NODE_CAPTURE_HEAP_ENFORCED = javaScriptRuntime(process.versions).id === "node"; /** Windows Job Object commit limit replacing the ignored heap flags under Bun; otherwise null. */ -export const HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES = - javaScriptWorkerMemoryLimitBytes(HAR_CAPTURE_HEAP_LIMITS.oldGenerationMiB); +export const NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES = + javaScriptWorkerMemoryLimitBytes(NODE_CAPTURE_HEAP_LIMITS.oldGenerationMiB); /** Native executable profile verified with unchanged mitmproxy raw-state decoding. */ export const MITMPROXY_CAPTURE_PROVIDER_IDENTITY = { @@ -28,3 +28,18 @@ export const MITMPROXY_CAPTURE_PROVIDER_IDENTITY = { name: "REA offline native mitmproxy adapter", version: "12.2.3", } as const; + +/** Native SAZ member decoding with the existing ZIP and XML package profiles. */ +export const SAZ_CAPTURE_PROVIDER_IDENTITY = { + id: "fiddler-saz", + name: "REA Fiddler SAZ capture adapter", + version: "1;zip.js@2.15.0;xmldom@0.9.12", +} as const; + +/** Fixed offline interpretation profile, not an authenticated producer claim. */ +export const QLOG_CAPTURE_PROVIDER_IDENTITY = { + id: "aioquic-qlog-json", + name: "REA aioquic qlog capture adapter", + version: + "aioquic-profile@1.5.0;qlog@0.3;jsonc-parser@3.3.1;lossless-json@4.3.1", +} as const; diff --git a/src/browser/history/HarCapture.test.ts b/src/browser/history/HarCapture.test.ts index 2eb1fe21a..b931fda06 100644 --- a/src/browser/history/HarCapture.test.ts +++ b/src/browser/history/HarCapture.test.ts @@ -1,7 +1,8 @@ import { createHash } from "node:crypto"; import { expect, it } from "vitest"; import { historicalHar } from "../../../tests/fixtures/historicalHar.js"; -import { decodeHarCapture, decodeHarText } from "./HarCapture.js"; +import { decodeCaptureText } from "./CaptureJson.js"; +import { decodeHarCapture } from "./HarCapture.js"; it.each([ { values: [] }, @@ -161,6 +162,19 @@ it("rejects identical duplicate core fields before schema validation", () => { expect(() => decodeHarCapture(text, [])).toThrow("duplicate"); }); +it("names the violated HAR schema constraint without restating capture values", () => { + expect(() => + decodeHarCapture( + JSON.stringify({ + log: { creator: { name: "x", version: "1" }, entries: [] }, + }), + [], + ), + ).toThrow( + "HAR schema validation failed: required (must have required property 'version').", + ); +}); + it("preserves prototype-named producer members through the capture boundary", () => { const text = JSON.stringify(historicalHar()).replace( '"cache":{}', @@ -563,18 +577,21 @@ it("ignores one leading byte-order mark, as HAR 1.2 requires of readers", () => const text = JSON.stringify(historicalHar()); const body = Buffer.from(text, "utf8"); const marked = Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), body]); - expect(decodeHarText(marked)).toBe(text); - expect(decodeHarCapture(decodeHarText(marked), [])).toEqual( - decodeHarCapture(decodeHarText(body), []), + expect(decodeCaptureText(marked, "HAR")).toBe(text); + expect(decodeHarCapture(decodeCaptureText(marked, "HAR"), [])).toEqual( + decodeHarCapture(decodeCaptureText(body, "HAR"), []), ); // A second mark is content, not an encoding signature. expect(() => decodeHarCapture( - decodeHarText(Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), marked])), + decodeCaptureText( + Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), marked]), + "HAR", + ), [], ), ).toThrow("HAR is malformed JSON."); - expect(() => decodeHarText(Buffer.from([0x7b, 0xff, 0x7d]))).toThrow( - "HAR is not valid UTF-8 JSON.", - ); + expect(() => + decodeCaptureText(Buffer.from([0x7b, 0xff, 0x7d]), "HAR"), + ).toThrow("HAR is not valid UTF-8 JSON."); }); diff --git a/src/browser/history/HarCapture.ts b/src/browser/history/HarCapture.ts index f3a83af15..81c5ffb15 100644 --- a/src/browser/history/HarCapture.ts +++ b/src/browser/history/HarCapture.ts @@ -1,7 +1,6 @@ import { createHash } from "node:crypto"; -import { TextDecoder } from "node:util"; import { isSafeNumber, LosslessNumber } from "lossless-json"; -import { parseHarJson } from "./HarJson.js"; +import { parseCaptureJson } from "./CaptureJson.js"; import type { JsonValue } from "../../domain/jsonValue.js"; import { WEB_NETWORK_CAPTURE_LIMITS, @@ -26,25 +25,12 @@ type Projection = Pick< "reported" | "numeric_literals" | "binary_fields" | "redactions" >; -/** - * Decode retained HAR bytes as UTF-8. HAR 1.2 lets writers emit a byte-order - * mark and requires readers to ignore it, so one leading BOM is skipped. - */ -export const decodeHarText = (bytes: Uint8Array): string => { - try { - // ignoreBOM: false (the default) is what skips the mark; true keeps it. - return new TextDecoder("utf-8", { fatal: true }).decode(bytes); - } catch { - throw new CaptureFormatError("format", "HAR is not valid UTF-8 JSON."); - } -}; - /** Decode a retained HAR with exact numeric lexemes and unchanged upstream schema validation. */ export const decodeHarCapture = ( text: string, sensitiveValues: readonly string[], ): DecodedCapture => { - const raw = parseHarJson(text); + const raw = parseCaptureJson(text, "HAR"); const validation = projectHar(raw, [], false); createHarValidator()(validation.reported); if ( @@ -158,7 +144,8 @@ const projectHar = ( (literal) => item.includes(literal) || contentBase64.includes(literal) || - sha256.includes(literal), + sha256.includes(literal) || + String(bytes.length).includes(literal), ); binary_fields.push( hidden diff --git a/src/browser/history/HarCaptureAdapter.ts b/src/browser/history/HarCaptureAdapter.ts deleted file mode 100644 index 9a5204257..000000000 --- a/src/browser/history/HarCaptureAdapter.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { fileURLToPath } from "node:url"; -import type { HistoricalCaptureFormatAdapter } from "./HistoricalCaptureFormatAdapter.js"; -import { - HAR_CAPTURE_PROVIDER_IDENTITY, - HAR_CAPTURE_HEAP_LIMITS, - HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, -} from "./CaptureRelease.js"; - -/** HAR's parser/schema packages run in one bounded Node heap, without network or target execution. */ -export class HarCaptureAdapter implements HistoricalCaptureFormatAdapter { - readonly format = "har"; - readonly identity = HAR_CAPTURE_PROVIDER_IDENTITY; - async command(requestPath: string): Promise<{ - command: string; - arguments: readonly string[]; - memoryLimitBytes?: number; - }> { - return { - command: process.execPath, - arguments: [ - `--max-old-space-size=${HAR_CAPTURE_HEAP_LIMITS.oldGenerationMiB}`, - `--max-semi-space-size=${HAR_CAPTURE_HEAP_LIMITS.semiSpaceMiB}`, - "--v8-pool-size=1", - "--single-threaded", - fileURLToPath(new URL("./HarCaptureProcess.js", import.meta.url)), - requestPath, - ], - ...(HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null - ? {} - : { memoryLimitBytes: HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES }), - }; - } -} diff --git a/src/browser/history/HarSchema.ts b/src/browser/history/HarSchema.ts index 069377f8a..add8c301e 100644 --- a/src/browser/history/HarSchema.ts +++ b/src/browser/history/HarSchema.ts @@ -23,9 +23,13 @@ export const createHarValidator = (): ((value: unknown) => void) => { allowMitmproxyAbsentPostData(value); if (!validate(value)) { const error = validate.errors?.[0]; + // AJV messages name the violated constraint, such as the missing + // property, without restating any captured value. throw new CaptureFormatError( "format", - `HAR schema validation failed: ${error?.keyword ?? "unknown constraint"}.`, + error === undefined + ? "HAR schema validation failed: unknown constraint." + : `HAR schema validation failed: ${error.keyword} (${error.message ?? "no detail"}).`, error?.instancePath ?? "", ); } diff --git a/src/browser/history/HistoricalCaptureDecoder.ts b/src/browser/history/HistoricalCaptureDecoder.ts index 155ba229b..85a91ef76 100644 --- a/src/browser/history/HistoricalCaptureDecoder.ts +++ b/src/browser/history/HistoricalCaptureDecoder.ts @@ -4,9 +4,9 @@ import { captureMemoryFailure, } from "./CaptureFailures.js"; import { - HAR_CAPTURE_HEAP_ENFORCED, - HAR_CAPTURE_HEAP_LIMITS, - HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, + NODE_CAPTURE_HEAP_ENFORCED, + NODE_CAPTURE_HEAP_LIMITS, + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, } from "./CaptureRelease.js"; import { projectAnalysisError } from "../../domain/analysisErrorProjection.js"; import type { HistoricalCaptureFormatAdapter } from "./HistoricalCaptureFormatAdapter.js"; @@ -17,6 +17,7 @@ import { z } from "zod"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; +import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import type { AnalysisError } from "../../domain/analysisErrorBase.js"; import { AnalysisCapabilityUnavailableError, @@ -26,6 +27,7 @@ import { } from "../../domain/analysisErrorCore.js"; import { ProviderAdapterError } from "../../domain/providerAdapterError.js"; import { ProviderCleanupError } from "../../domain/providerCleanupError.js"; +import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; import { err, ok, type Result } from "../../domain/result.js"; import { WEB_NETWORK_CAPTURE_LIMITS, @@ -60,18 +62,52 @@ const replySchema = z.discriminatedUnion("ok", [ /** One owned snapshot/process/root lifecycle for replaceable historical format decoders. */ export class HistoricalCaptureDecoder { + readonly #resources: ArtifactResourceScope; + constructor( readonly adapters: readonly HistoricalCaptureFormatAdapter[], readonly environment: Readonly, readonly createRuntime: () => Promise< Pick > = () => PrivateRuntimeRoot.create({ prefix: "rea-web-capture-" }), - ) {} + resources = new ArtifactResourceScope(), + ) { + this.#resources = resources; + } + + /** Retry retained readers and private roots at service shutdown. */ + close(): Promise { + return this.#resources.close(); + } /** Snapshot the selected artifact, decode it offline, and release private credentials and processes. */ async inspect( input: InspectWebNetworkCaptureInput, options?: ExecutionOptions, + ): Promise> { + try { + return await this.#resources.run(() => + this.inspectAdmitted(input, options), + ); + } catch (cause: unknown) { + const error = historicalCaptureFailure( + input, + cause, + "capture-read", + options, + ); + return err( + redactExplicitFailure( + this.withReaderCleanup(error, cause), + input.sensitive_values, + ), + ); + } + } + + private async inspectAdmitted( + input: InspectWebNetworkCaptureInput, + options?: ExecutionOptions, ): Promise> { let runtime: Pick | undefined; let result: Result; @@ -90,6 +126,8 @@ export class HistoricalCaptureDecoder { input.capture_path, WEB_NETWORK_CAPTURE_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); phase = "decoder"; runtime = await this.createRuntime(); @@ -139,9 +177,16 @@ export class HistoricalCaptureDecoder { replyPath, WEB_NETWORK_CAPTURE_LIMITS.outputBytes, options?.signal, + undefined, + this.#resources, ); reply = replySchema.parse(JSON.parse(replyFile.bytes.toString("utf8"))); } catch (cause: unknown) { + if ( + cause instanceof ArtifactReaderFailure && + cause.cleanup !== undefined + ) + throw cause; if (options?.signal?.aborted) throw new AnalysisCancelledError(OPERATION); throw new AnalysisOutputError( @@ -198,34 +243,53 @@ export class HistoricalCaptureDecoder { OPERATION, "Capture decoder changed the selected upstream profile identity.", ); - result = ok({ - ...reply.value, + const common = { artifact: { path: input.capture_path, sha256: snapshot.sha256, bytes: snapshot.bytes.length, }, - format: input.format, - runtime_attribution: "unknown", + + runtime_attribution: "unknown" as const, limitations: [ + ...(adapter.limitations ?? []), "This is retained producer evidence, without live browser transaction IDs, scenario provenance, execution attribution or deployment authenticity. Recorded URLs are never fetched.", "Every record is decoded before selection; no partial success is returned on malformed input or a resource limit.", "Known authentication headers/cookies and explicitly marked literal values are excluded. Unknown extension names do not establish sensitivity.", - `A 32 MiB input, 96 MiB reply and 64-level nesting budget bound complete evidence. ${harMemoryLimitation()}; native decoding uses a 768 MiB Linux address-space limit. Each owned command has a 30-second deadline with independent cleanup.`, + `A 32 MiB input, 96 MiB reply and 64-level nesting budget bound complete evidence. ${nodeMemoryLimitation()}; mitmproxy decoding uses a 768 MiB Linux address-space limit. Each owned command has a 30-second deadline with independent cleanup.`, ], - }); + }; + if (input.format === "qlog") { + if (!("qlog" in reply.value)) + throw new AnalysisOutputError( + OPERATION, + "Capture decoder omitted qlog transport facts.", + ); + result = ok({ ...reply.value, ...common, format: "qlog" }); + } else { + if ("qlog" in reply.value) + throw new AnalysisOutputError( + OPERATION, + "Capture decoder supplied inapplicable qlog transport facts.", + ); + result = ok({ ...reply.value, ...common, format: input.format }); + } } catch (cause: unknown) { + const error = historicalCaptureFailure(input, cause, phase, options); result = err( redactExplicitFailure( - historicalCaptureFailure(input, cause, phase, options), + this.withReaderCleanup(error, cause), input.sensitive_values, ), ); } if (runtime !== undefined) { - try { - await runtime.close(); - } catch (cause: unknown) { + const cleanup = await this.#resources.release({ + kind: "private-runtime-root", + resource: runtime.path, + root: runtime, + }); + if (cleanup.kind === "failed") { return err( redactExplicitFailure( new ProviderCleanupError( @@ -236,9 +300,12 @@ export class HistoricalCaptureDecoder { previous_error: result.ok ? null : projectAnalysisError(result.error), - reason: cause instanceof Error ? cause.message : String(cause), + reason: + cleanup.cause instanceof Error + ? cleanup.cause.message + : String(cleanup.cause), }, - { operation: OPERATION }, + { operation: OPERATION, cause: cleanup.cause }, ), input.sensitive_values, ), @@ -249,15 +316,43 @@ export class HistoricalCaptureDecoder { ? err(new AnalysisCancelledError(OPERATION)) : result; } + + private withReaderCleanup( + primary: AnalysisError, + cause: unknown, + ): AnalysisError { + if ( + !(cause instanceof ArtifactReaderFailure) || + cause.cleanup === undefined + ) + return primary; + if (cause.reason === "unavailable") + return new ProviderCleanupError( + "web-network-capture", + cause.cleanup.resources, + { reason: cause.cleanup.reason }, + { operation: OPERATION, cause }, + ); + const cleanup = new ProviderCleanupError( + "web-network-capture", + cause.cleanup.resources, + { + reason: cause.cleanup.reason, + previous_error: projectAnalysisError(primary), + }, + { operation: OPERATION, cause }, + ); + return analysisErrorWithCleanupFailure(primary, cleanup, OPERATION); + } } -/** The HAR decoder runs on this executable; only Node.js enforces its V8 heap flags. */ -const harMemoryLimitation = (): string => { - if (HAR_CAPTURE_HEAP_ENFORCED) - return `HAR uses a ${String(HAR_CAPTURE_HEAP_LIMITS.oldGenerationMiB)} MiB Node old-generation heap`; - return HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null - ? "HAR runs on Bun, which does not enforce REA's V8 heap flags" - : `HAR runs on Bun, which does not enforce REA's V8 heap flags, under a ${String(HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES)}-byte Windows Job Object commit limit`; +/** The Node capture decoder runs on this executable; only Node.js enforces its V8 heap flags. */ +const nodeMemoryLimitation = (): string => { + if (NODE_CAPTURE_HEAP_ENFORCED) + return `HAR/SAZ/qlog use a ${String(NODE_CAPTURE_HEAP_LIMITS.oldGenerationMiB)} MiB Node old-generation heap`; + return NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null + ? "HAR/SAZ/qlog run on Bun, which does not enforce REA's V8 heap flags" + : `HAR/SAZ/qlog run on Bun, which does not enforce REA's V8 heap flags, under a ${String(NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES)}-byte Windows Job Object commit limit`; }; const replyFailureReason = (cause: unknown): string => { diff --git a/src/browser/history/HistoricalCaptureFormatAdapter.ts b/src/browser/history/HistoricalCaptureFormatAdapter.ts index 811ea56e2..9660fd579 100644 --- a/src/browser/history/HistoricalCaptureFormatAdapter.ts +++ b/src/browser/history/HistoricalCaptureFormatAdapter.ts @@ -3,6 +3,7 @@ import type { InspectWebNetworkCaptureInput } from "../../domain/webNetworkCaptu /** Format-specific process profile keeps mature upstream code behind a replaceable adapter seam. */ export interface HistoricalCaptureFormatAdapter { readonly format: InspectWebNetworkCaptureInput["format"]; + readonly limitations?: readonly string[]; readonly identity: { readonly id: string; readonly name: string; diff --git a/src/browser/history/NodeCaptureAdapter.test.ts b/src/browser/history/NodeCaptureAdapter.test.ts new file mode 100644 index 000000000..bf2528f5b --- /dev/null +++ b/src/browser/history/NodeCaptureAdapter.test.ts @@ -0,0 +1,18 @@ +import { expect, it, vi } from "vitest"; +import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js"; +import { NodeCaptureAdapter } from "./NodeCaptureAdapter.js"; + +vi.mock("./CaptureRelease.js", async (original) => ({ + ...(await original()), + NODE_CAPTURE_HEAP_ENFORCED: false, + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES: null, +})); + +it.each(["saz", "qlog"] as const)( + "refuses a %s worker when the runtime has no enforceable memory bound", + async (format) => { + await expect( + new NodeCaptureAdapter(format).command("/owned/request.json"), + ).rejects.toBeInstanceOf(AnalysisCapabilityUnavailableError); + }, +); diff --git a/src/browser/history/NodeCaptureAdapter.ts b/src/browser/history/NodeCaptureAdapter.ts new file mode 100644 index 000000000..8f33430ca --- /dev/null +++ b/src/browser/history/NodeCaptureAdapter.ts @@ -0,0 +1,61 @@ +import { fileURLToPath } from "node:url"; +import type { HistoricalCaptureFormatAdapter } from "./HistoricalCaptureFormatAdapter.js"; +import { + NODE_CAPTURE_HEAP_ENFORCED, + HAR_CAPTURE_PROVIDER_IDENTITY, + SAZ_CAPTURE_PROVIDER_IDENTITY, + QLOG_CAPTURE_PROVIDER_IDENTITY, + NODE_CAPTURE_HEAP_LIMITS, + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, +} from "./CaptureRelease.js"; +import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js"; + +/** Package-backed capture decoders share one bounded offline Node process profile. */ +export class NodeCaptureAdapter implements HistoricalCaptureFormatAdapter { + readonly identity; + readonly limitations; + constructor(readonly format: "har" | "saz" | "qlog") { + this.identity = + format === "har" + ? HAR_CAPTURE_PROVIDER_IDENTITY + : format === "saz" + ? SAZ_CAPTURE_PROVIDER_IDENTITY + : QLOG_CAPTURE_PROVIDER_IDENTITY; + this.limitations = + format === "saz" + ? [ + "SAZ ordinals follow first session-member occurrence in ZIP directory order, not chronology or numeric session ID.", + "HTTP fields use byte-preserving Latin-1 text; start-line separators and header delimiters are not projected. Bodies retain stored bytes without transfer/content decoding. Absent members are null, distinct from empty bodies.", + "XML preserves node order and attribute/text values, not its original byte serialization. WebSocket and gRPC members retain opaque message-file bytes, not decoded protocol events.", + "Non-session archive members are inventoried but their content is not decoded.", + ] + : []; + } + async command(requestPath: string) { + if ( + this.format !== "har" && + !NODE_CAPTURE_HEAP_ENFORCED && + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null + ) + throw new AnalysisCapabilityUnavailableError( + this.identity.id, + "inspect_web_network_capture", + `${this.format} decoding requires an enforced decoder memory limit. Run REA with Node.js on this host.`, + ); + return { + command: process.execPath, + arguments: [ + `--max-old-space-size=${NODE_CAPTURE_HEAP_LIMITS.oldGenerationMiB}`, + `--max-semi-space-size=${NODE_CAPTURE_HEAP_LIMITS.semiSpaceMiB}`, + "--v8-pool-size=1", + "--single-threaded", + fileURLToPath(new URL("./NodeCaptureProcess.js", import.meta.url)), + requestPath, + this.format, + ], + ...(NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES === null + ? {} + : { memoryLimitBytes: NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES }), + }; + } +} diff --git a/src/browser/history/HarCaptureProcess.ts b/src/browser/history/NodeCaptureProcess.ts similarity index 53% rename from src/browser/history/HarCaptureProcess.ts rename to src/browser/history/NodeCaptureProcess.ts index 1e4c66c76..ff45a869a 100644 --- a/src/browser/history/HarCaptureProcess.ts +++ b/src/browser/history/NodeCaptureProcess.ts @@ -3,7 +3,6 @@ import { z } from "zod"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { WEB_NETWORK_CAPTURE_LIMITS } from "../../domain/webNetworkCapture.js"; import { CaptureFormatError } from "./CaptureFormatError.js"; -import { decodeHarCapture, decodeHarText } from "./HarCapture.js"; const requestSchema = z.strictObject({ snapshot_path: z.string(), @@ -11,24 +10,37 @@ const requestSchema = z.strictObject({ sensitive_values: z.array(z.string().min(1)), }); -/** Decode untrusted HAR in an owned, bounded heap rather than the long-lived MCP process. */ +/** Parse untrusted captures in an owned heap and return one complete bounded reply. */ const main = async (): Promise => { + const format = z.enum(["har", "saz", "qlog"]).parse(process.argv[3]); const request = requestSchema.parse( JSON.parse(await readFile(process.argv[2] ?? "", "utf8")), ); let reply: unknown; try { - const snapshot = await readStableArtifact( - request.snapshot_path, - WEB_NETWORK_CAPTURE_LIMITS.inputBytes, - ); - reply = { - ok: true, - value: decodeHarCapture( - decodeHarText(snapshot.bytes), + let value; + if (format !== "saz") { + const { decodeCaptureText } = await import("./CaptureJson.js"); + const decoder = + format === "har" + ? (await import("./HarCapture.js")).decodeHarCapture + : (await import("./QlogCapture.js")).decodeQlogCapture; + const snapshot = await readStableArtifact( + request.snapshot_path, + WEB_NETWORK_CAPTURE_LIMITS.inputBytes, + ); + value = decoder( + decodeCaptureText(snapshot.bytes, format === "har" ? "HAR" : "qlog"), request.sensitive_values, - ), - }; + ); + } else { + const { decodeSazCapture } = await import("./SazCapture.js"); + value = await decodeSazCapture( + request.snapshot_path, + request.sensitive_values, + ); + } + reply = { ok: true, value }; } catch (cause: unknown) { reply = cause instanceof CaptureFormatError @@ -41,7 +53,7 @@ const main = async (): Promise => { : { ok: false, reason: "decoder", - message: `HAR decoder failed unexpectedly (${cause instanceof Error ? cause.name : "unknown exception"}).`, + message: `Capture decoder failed unexpectedly (${cause instanceof Error ? cause.name : "unknown exception"}).`, pointer: "", }; } @@ -50,7 +62,7 @@ const main = async (): Promise => { text = JSON.stringify({ ok: false, reason: "limit", - message: "HAR reply exceeds the complete-evidence output budget.", + message: "Capture reply exceeds the complete-evidence output budget.", pointer: "", }); await writeFile(request.reply_path, text, { flag: "wx", mode: 0o600 }); diff --git a/src/browser/history/QlogCapture.test.ts b/src/browser/history/QlogCapture.test.ts new file mode 100644 index 000000000..bd67d4e80 --- /dev/null +++ b/src/browser/history/QlogCapture.test.ts @@ -0,0 +1,259 @@ +import { expect, it } from "vitest"; +import { decodeQlogCapture } from "./QlogCapture.js"; +import { decodeCaptureText } from "./CaptureJson.js"; +import { CaptureFormatError } from "./CaptureFormatError.js"; + +// Synthetic format inputs exercise distinct parser semantics, not producer provenance. +const event = (frames: unknown[], name = "transport:packet_sent") => ({ + name, + time: 1791819895000.25, + data: { header: { packet_type: "1RTT", packet_number: 5 }, frames }, +}); +const frame = (offset: number, length: number, fin = false) => ({ + frame_type: "stream", + stream_id: 0, + offset, + length, + fin, +}); +const capture = (events: unknown[], extra: Record = {}) => + JSON.stringify({ + qlog_format: "JSON", + qlog_version: "0.3", + ...extra, + traces: [ + { + common_fields: { ODCID: "same" }, + vantage_point: { name: "aioquic", type: "server" }, + events, + }, + ], + }); +const facts = (text: string, sensitive: string[] = []) => { + const decoded = decodeQlogCapture(text, sensitive); + if (!("qlog" in decoded)) throw new Error("qlog facet required"); + return { decoded, traces: decoded.qlog.traces }; +}; + +it("derives interval unions per trace/direction while retaining event source order and extensions", () => { + const original = JSON.parse( + capture([ + event([frame(10, 10)]), + event([frame(0, 15), frame(30, 5, true)]), + event([frame(0, 4)], "transport:packet_received"), + { + name: "recovery:packet_lost", + time: 1, + data: { packet_number: 5, type: "1RTT" }, + }, + ]), + ); + original.traces.push({ + ...original.traces[0], + events: [event([frame(0, 3)])], + }); + Object.defineProperty(original, "__proto__", { + enumerable: true, + value: { ordinary: true }, + }); + original.extra = "https://example.test/path?token=ordinary"; + const { decoded, traces } = facts(JSON.stringify(original)); + expect(traces[0]?.streams[0]).toMatchObject({ + stream_id: "0", + direction: "sent", + unique_bytes: "25", + frame_length_sum: "30", + repeated_bytes: "5", + covered_ranges: [ + { start: "0", end: "20" }, + { start: "30", end: "35" }, + ], + reported_final_sizes: ["35"], + }); + expect(traces[0]?.streams[1]).toMatchObject({ + direction: "received", + unique_bytes: "4", + }); + expect(traces[1]?.streams[0]).toMatchObject({ unique_bytes: "3" }); + expect(traces[0]?.loss_declarations[0]).toMatchObject({ + confidence: "observed", + packet_number: { state: "reported", value: "5" }, + packet_number_space: "application", + }); + expect(decoded.records.at(-1)?.location).toEqual({ + kind: "json-pointer", + pointer: "/traces/1/events/0", + }); + expect(decoded.container.reported).toMatchObject({ + extra: original.extra, + ["__proto__"]: { ordinary: true }, + }); + expect(Reflect.get(Object.prototype, "ordinary")).toBeUndefined(); +}); + +it("keeps exact 62-bit integers and numeric lexemes without allocating exponent expansion", () => { + const text = capture([event([frame(0, 0, true)])]) + .replace('"stream_id":0', '"stream_id":4611686018427387903') + .replace('"offset":0', '"offset":9007199254740993') + .replace('"length":0', '"length":1e3'); + const { decoded, traces } = facts(text); + expect(traces[0]?.streams[0]).toMatchObject({ + stream_id: "4611686018427387903", + unique_bytes: "1000", + reported_final_sizes: ["9007199254741993"], + }); + expect(decoded.records[0]?.numeric_literals).toContainEqual({ + pointer: "/data/frames/0/length", + producer_type: "json-number", + literal: "1e3", + }); + expect(decoded.records[0]?.reported).toMatchObject({ + data: { frames: [{ stream_id: null, offset: null, length: 1000 }] }, + }); +}); + +it("keeps incomplete fields unknown and FIN without bytes as metadata", () => { + const { traces } = facts( + capture([ + event([{ frame_type: "stream", stream_id: 0, length: 5 }]), + event([frame(10, 0, true)]), + { name: "recovery:packet_lost", time: 1, data: {} }, + { + name: "extension:custom", + time: 0, + data: { body: "ordinary evidence" }, + }, + ]), + ); + expect(traces[0]?.incomplete_fact_records).toEqual([0]); + expect(traces[0]?.streams[0]).toMatchObject({ + unique_bytes: "0", + covered_ranges: [], + reported_final_sizes: ["10"], + }); + expect(traces[0]?.loss_declarations[0]?.packet_number.state).toBe("unknown"); +}); + +it("excludes structural auth material and explicit normalized values without guessing extension secrecy", () => { + const text = capture([ + { + name: "http:frame_parsed", + time: 1, + data: { + frame: { + frame_type: "headers", + headers: [ + { name: "authorization", value: "Bearer credential" }, + { name: ":path", value: "/?token=ordinary" }, + { name: "location", value: "https://user:pass@example.test/a" }, + ], + }, + }, + }, + { + name: "transport:parameters_set", + time: 2, + data: { stateless_reset_token: "reset-credential" }, + }, + event([ + { frame_type: "new_connection_id", reset_token: "reset-frame" }, + { frame_type: "new_token", token: "new-token" }, + frame(0, 100), + ]), + { + name: "extension:custom", + time: 3, + data: { + secret: "caller-selected ordinary value", + reset_token: "extension ordinary", + }, + }, + ]).replace('"length":100', '"length":1e2'); + const { decoded, traces } = facts(text, ["100"]); + const serialized = JSON.stringify(decoded); + for (const hidden of [ + "Bearer credential", + "reset-credential", + "reset-frame", + "new-token", + "100", + "user:pass", + ]) + expect(serialized).not.toContain(hidden); + expect(serialized).toContain("token=ordinary"); + expect(serialized).toContain("caller-selected ordinary value"); + expect(traces[0]?.streams).toEqual([]); + expect(traces[0]?.incomplete_fact_records).toContain(2); +}); + +it("hides marked ancestor keys and safe derived sums while still validating hidden subtrees", () => { + const text = capture([event([frame(0, 3), frame(3, 4)])]); + expect(facts(text, ["7"]).traces[0]?.streams).toEqual([]); + const { decoded, traces } = facts(text, ["events"]); + expect(decoded.records[0]?.reported).toBe(null); + expect(decoded.records[0]?.location.kind).toBe("unknown"); + expect(traces[0]?.location.kind).toBe("unknown"); + expect(traces[0]?.streams).toEqual([]); + expect(() => + facts(text.replace('"length":3', '"length":-3'), ["events"]), + ).toThrow(CaptureFormatError); +}); + +it.each([ + "-1", + "0.5", + "4611686018427387904", + "1e1000000", + "1e-1000000", + '"3"', + "true", +])("rejects malformed or out-of-range STREAM integer %s", (literal) => { + expect(() => + facts( + capture([event([frame(0, 3)])]).replace( + '"length":3', + `"length":${literal}`, + ), + ), + ).toThrow(CaptureFormatError); +}); + +it.each([ + '{"qlog_format":"JSON","qlog_format":"JSON","qlog_version":"0.3","traces":[]}', + capture([]).slice(0, -1), + capture([]) + " {}", + capture([{ name: "invalid", time: "1", data: {} }]), + capture([[1, "transport", "packet_sent", {}]]), + capture([event([{ ...frame(0, 1), fin: "true" }])]), + capture([event([{ ...frame(0, 1), offset: 4611686018427388000 }])]), +])( + "rejects malformed JSON/profile events with no partial success: %s", + (text) => { + expect(() => facts(text)).toThrow(CaptureFormatError); + }, +); + +it("rejects other qlog containers/versions and excessive nesting, accepts empty profiles and UTF-8 BOM", () => { + for (const extra of [{ qlog_format: "JSON-SEQ" }, { qlog_version: "0.4" }]) + expect(() => facts(capture([], extra))).toThrow("Only the aioquic"); + expect(() => + facts( + capture([], { + extension: JSON.parse("[".repeat(65) + "0" + "]".repeat(65)), + }), + ), + ).toThrow("nesting budget"); + expect( + facts('{"qlog_format":"JSON","qlog_version":"0.3","traces":[]}').traces, + ).toEqual([]); + const raw = Buffer.from(capture([])); + expect( + facts( + decodeCaptureText( + Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), raw]), + "qlog", + ), + ).decoded.total_records, + ).toBe(0); + expect(() => decodeCaptureText(Buffer.from([0xff]), "qlog")).toThrow("UTF-8"); +}); diff --git a/src/browser/history/QlogCapture.ts b/src/browser/history/QlogCapture.ts new file mode 100644 index 000000000..2e8a1f790 --- /dev/null +++ b/src/browser/history/QlogCapture.ts @@ -0,0 +1,503 @@ +import { isSafeNumber, LosslessNumber } from "lossless-json"; +import type { JsonValue } from "../../domain/jsonValue.js"; +import type { QlogCaptureFacts } from "../../domain/qlogCapture.js"; +import { + webNetworkCapturePayloadSchema, + type WebNetworkCaptureRecord, +} from "../../domain/webNetworkCapture.js"; +import type { z } from "zod"; +import { parseCaptureJson } from "./CaptureJson.js"; +import { CaptureFormatError } from "./CaptureFormatError.js"; +import { + CaptureRedaction, + captureObject, + capturePointer, +} from "./CaptureRedaction.js"; +import { QLOG_CAPTURE_PROVIDER_IDENTITY } from "./CaptureRelease.js"; + +const MAX_VARINT = (1n << 62n) - 1n; +const credentials = new Set([ + "authorization", + "proxy-authorization", + "cookie", + "set-cookie", +]); +type Projection = Pick< + WebNetworkCaptureRecord, + "reported" | "numeric_literals" | "binary_fields" | "redactions" +>; +type Trace = QlogCaptureFacts["traces"][number]; +type Stream = Trace["streams"][number]; + +/** Inspect the selected aioquic JSON profile without authenticating its producer or interpreting other qlog layouts. */ +export const decodeQlogCapture = ( + text: string, + sensitiveValues: readonly string[], +): z.output => { + const raw = parseCaptureJson(text, "qlog"); + if (!object(raw) || raw.qlog_format !== "JSON" || raw.qlog_version !== "0.3") + throw new CaptureFormatError( + "unsupported", + "Only the aioquic 1.5.0 JSON qlog 0.3 profile is supported.", + ); + if (!Array.isArray(raw.traces)) + return invalid("qlog must contain a traces array.", "/traces"); + const traces = raw.traces.map(validateTrace); + const container = project( + { ...raw, traces: traces.map((trace) => ({ ...trace, events: null })) }, + sensitiveValues, + ); + const records: WebNetworkCaptureRecord[] = []; + const facts: Trace[] = []; + const excluded = (value: string): boolean => + sensitiveValues.some((literal) => value.includes(literal)); + const ancestorsHidden = excluded("traces") || excluded("events"); + for (const [traceIndex, trace] of traces.entries()) { + const tracePointer = `/traces/${traceIndex}`; + const fact = createTraceFact( + trace, + traceIndex, + sensitiveValues, + ancestorsHidden, + ); + const streams = new Map(); + for (const [eventIndex, event] of trace.events.entries()) { + const ordinal = records.length; + const projection: Projection = ancestorsHidden + ? { + reported: null, + numeric_literals: [], + binary_fields: [], + redactions: [{ pointer: "", reason: "explicit-sensitive-value" }], + } + : project(event, sensitiveValues); + records.push({ + ordinal, + location: ancestorsHidden + ? { kind: "unknown", reason: "explicit-sensitive-value" } + : { + kind: "json-pointer", + pointer: `${tracePointer}/events/${eventIndex}`, + }, + ...projection, + limitations: [ + "Record ordinal is derived from trace/event source traversal, not global time order. Qlog lengths and FIN do not expose original HTTP body bytes or establish network completeness.", + ], + }); + collectTransportFacts(projection, ordinal, { fact, streams, excluded }); + } + for (const stream of streams.values()) { + summarizeStream(stream); + const numericValues = [ + stream.frame_length_sum, + stream.unique_bytes, + stream.repeated_bytes, + ...stream.reported_final_sizes, + ...stream.covered_ranges.flatMap((r) => [r.start, r.end]), + ]; + if (numericValues.some(excluded)) + fact.incomplete_fact_records.push( + ...stream.contributions.map((c) => c.record_ordinal), + ); + else fact.streams.push(stream); + } + fact.incomplete_fact_records = [...new Set(fact.incomplete_fact_records)]; + facts.push(fact); + } + return { + decoder: { ...QLOG_CAPTURE_PROVIDER_IDENTITY }, + container: { + reported: container.reported, + numeric_literals: container.numeric_literals, + redactions: container.redactions, + records_pointer: null, + }, + total_records: records.length, + records, + qlog: { + profile: "aioquic-1.5.0-json-0.3", + scope: "all-recorded-events-before-selection", + body_bytes: "not-reported", + clock: { + unit: "milliseconds", + domain: "unix-epoch", + basis: "selected-aioquic-profile-not-producer-authentication", + }, + traces: facts, + }, + }; +}; + +const createTraceFact = ( + trace: Record & { events: unknown[] }, + traceIndex: number, + sensitiveValues: readonly string[], + ancestorsHidden: boolean, +): Trace => { + const tracePointer = `/traces/${traceIndex}`; + const metadata = project( + { ...trace, events: null }, + sensitiveValues, + ).reported; + const meta = !ancestorsHidden && object(metadata) ? metadata : null; + const common = + meta !== null && object(meta.common_fields) ? meta.common_fields : null; + const vantage = + meta !== null && object(meta.vantage_point) + ? meta.vantage_point.type + : null; + return { + trace_index: traceIndex, + location: ancestorsHidden + ? { kind: "unknown", reason: "explicit-sensitive-value" } + : { kind: "json-pointer", pointer: tracePointer }, + event_count: trace.events.length, + odcid: typeof common?.ODCID === "string" ? common.ODCID : null, + vantage_point: + vantage === "client" || vantage === "server" ? vantage : null, + loss_declarations: [], + streams: [], + incomplete_fact_records: [], + }; +}; + +const validateTrace = ( + trace: unknown, + index: number, +): Record & { events: unknown[] } => { + const pointer = `/traces/${index}`; + if (!object(trace) || !Array.isArray(trace.events)) + return invalid("qlog trace must contain an events array.", pointer); + for (const [eventIndex, event] of trace.events.entries()) { + const eventPointer = `${pointer}/events/${eventIndex}`; + if ( + !object(event) || + typeof event.name !== "string" || + !(event.time instanceof LosslessNumber) || + !Number.isFinite(Number(event.time.value)) || + !object(event.data) + ) + invalid( + "qlog events must be objects with name, finite numeric time and object data.", + eventPointer, + ); + // Validate interpretable fields on ORIGINAL values even when a declaration + // subsequently hides them. Missing fields remain meaningful unknowns. + if (event.name === "recovery:packet_lost") + unsigned(event.data.packet_number, `${eventPointer}/data/packet_number`); + if (packetEvent(event.name) && Array.isArray(event.data.frames)) { + for (const [frameIndex, frame] of event.data.frames.entries()) { + if (object(frame) && frame.frame_type === "stream") { + validateStreamFrame( + frame, + `${eventPointer}/data/frames/${frameIndex}`, + ); + } + } + } + } + return { ...trace, events: trace.events }; +}; + +const validateStreamFrame = ( + frame: Record, + p: string, +): void => { + unsigned(frame.stream_id, `${p}/stream_id`); + const offset = unsigned(frame.offset, `${p}/offset`); + const length = unsigned(frame.length, `${p}/length`); + if (offset !== null && length !== null && offset + length > MAX_VARINT) + invalid("qlog stream final offset exceeds the QUIC varint range.", p); + if ( + frame.fin !== undefined && + frame.fin !== null && + typeof frame.fin !== "boolean" + ) + invalid("qlog STREAM fin must be boolean when reported.", `${p}/fin`); +}; + +const collectTransportFacts = ( + projection: Projection, + ordinal: number, + state: { + fact: Trace; + streams: Map; + excluded: (value: string) => boolean; + }, +): void => { + const { fact, streams, excluded } = state; + if (!object(projection.reported) || !object(projection.reported.data)) { + fact.incomplete_fact_records.push(ordinal); + return; + } + const visible = projection.reported; + const data = visible.data; + if (!object(data)) return; + const literals = new Map( + projection.numeric_literals.map((n) => [n.pointer, n.literal]), + ); + const read = (value: unknown, pointer: string): bigint | null => { + const literal = literals.get(pointer); + const number = unsigned( + literal === undefined ? value : new LosslessNumber(literal), + pointer, + ); + return number !== null && excluded(number.toString()) ? null : number; + }; + if (visible.name === "recovery:packet_lost") { + fact.loss_declarations.push(lossDeclaration(data, ordinal, read)); + } + if (!packetEvent(visible.name)) return; + if (!Array.isArray(data.frames)) { + fact.incomplete_fact_records.push(ordinal); + return; + } + for (const [frameIndex, frame] of data.frames.entries()) { + if ( + !object(frame) || + frame.frame_type === undefined || + frame.frame_type === null + ) { + fact.incomplete_fact_records.push(ordinal); + continue; + } + if (frame.frame_type !== "stream") continue; + const p = `/data/frames/${frameIndex}`; + const id = read(frame.stream_id, `${p}/stream_id`), + offset = read(frame.offset, `${p}/offset`), + length = read(frame.length, `${p}/length`); + if (id === null || offset === null || length === null) { + fact.incomplete_fact_records.push(ordinal); + continue; + } + const direction = + visible.name === "transport:packet_sent" ? "sent" : "received"; + const key = `${direction}/${id}`; + let stream = streams.get(key); + if (stream === undefined) { + stream = { + stream_id: id.toString(), + direction, + confidence: "derived", + scope: "observed-stream-frame-ranges", + contributions: [], + covered_ranges: [], + unique_bytes: "0", + frame_length_sum: "0", + repeated_bytes: "0", + reported_final_sizes: [], + }; + streams.set(key, stream); + } + stream.contributions.push({ + record_ordinal: ordinal, + frame_index: frameIndex, + offset: offset.toString(), + length: length.toString(), + fin: typeof frame.fin === "boolean" ? frame.fin : null, + }); + } +}; + +const lossDeclaration = ( + data: Record, + ordinal: number, + read: (value: unknown, pointer: string) => bigint | null, +): Trace["loss_declarations"][number] => { + const pn = read(data.packet_number, "/data/packet_number"); + const type = typeof data.type === "string" ? data.type : null; + return { + record_ordinal: ordinal, + confidence: "observed", + packet_number: + pn === null + ? { + state: "unknown", + reason: "omitted-null-or-redacted", + } + : { state: "reported", value: pn.toString() }, + packet_type: type, + packet_number_space: + type === "initial" + ? "initial" + : type === "handshake" + ? "handshake" + : type === "0RTT" || type === "1RTT" + ? "application" + : null, + }; +}; + +const summarizeStream = (stream: Stream): void => { + const spans = stream.contributions + .map( + (c) => [BigInt(c.offset), BigInt(c.offset) + BigInt(c.length)] as const, + ) + .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)); + const merged: { start: bigint; end: bigint }[] = []; + for (const [start, end] of spans) { + if (start === end) continue; + const last = merged.at(-1); + if (last !== undefined && start <= last.end) + last.end = end > last.end ? end : last.end; + else merged.push({ start, end }); + } + const sum = stream.contributions.reduce((s, c) => s + BigInt(c.length), 0n); + const unique = merged.reduce((s, r) => s + r.end - r.start, 0n); + stream.covered_ranges = merged.map((r) => ({ + start: r.start.toString(), + end: r.end.toString(), + })); + stream.frame_length_sum = sum.toString(); + stream.unique_bytes = unique.toString(); + stream.repeated_bytes = (sum - unique).toString(); + stream.reported_final_sizes = [ + ...new Set( + stream.contributions + .filter((c) => c.fin === true) + .map((c) => (BigInt(c.offset) + BigInt(c.length)).toString()), + ), + ]; +}; + +const packetEvent = (name: unknown): boolean => + name === "transport:packet_sent" || name === "transport:packet_received"; +const object = (value: unknown): value is Record => + captureObject(value) && !(value instanceof LosslessNumber); +const invalid = (message: string, pointer: string): never => { + throw new CaptureFormatError("format", message, pointer); +}; + +/** Canonicalize JSON integer notation exactly, checking expansion before allocation. */ +const unsigned = (value: unknown, pointer: string): bigint | null => { + if (value === undefined || value === null) return null; + const literal = + value instanceof LosslessNumber + ? value.value + : typeof value === "number" + ? String(value) + : ""; + const m = /^(-?)([0-9]+)(?:\.([0-9]+))?(?:[eE]([+-]?[0-9]+))?$/u.exec( + literal, + ); + if (m === null) + return invalid("qlog QUIC integer must be a JSON number.", pointer); + const digits = `${m[2]}${m[3] ?? ""}`.replace(/^0+/u, ""); + if (digits === "") return 0n; + const exponent = m[4] === undefined ? 0 : Number(m[4]); + const shift = exponent - (m[3]?.length ?? 0); + const count = digits.length + shift; + if (m[1] === "-" || !Number.isSafeInteger(shift) || count > 19 || count <= 0) + return invalid( + "qlog QUIC integer is negative, fractional or outside the 62-bit range.", + pointer, + ); + if (shift < 0 && /[1-9]/u.test(digits.slice(count))) + return invalid("qlog QUIC integer is fractional.", pointer); + const canonical = + shift < 0 ? digits.slice(0, count) : digits + "0".repeat(shift); + const result = BigInt(canonical); + if (result > MAX_VARINT) + return invalid("qlog QUIC integer exceeds the 62-bit range.", pointer); + return result; +}; + +/** Preserve JSON values/lexemes and structurally exclude only transport credentials and declared values. */ +const project = ( + value: unknown, + sensitiveValues: readonly string[], +): Projection => { + const redactor = new CaptureRedaction(sensitiveValues); + const numeric_literals: Projection["numeric_literals"] = []; + const eventName = object(value) ? value.name : null; + const visit = ( + item: unknown, + pointer: string, + parent?: Record, + ): JsonValue => { + const header = + (eventName === "http:frame_created" || + eventName === "http:frame_parsed") && + /^\/data\/frame\/headers\/\d+\/value$/u.test(pointer) && + typeof parent?.name === "string"; + if ( + (header && credentials.has(String(parent?.name).toLowerCase())) || + qlogToken(eventName, pointer, parent) + ) + return redactor.credential(pointer); + if (item instanceof LosslessNumber) { + if ( + redactor.text(item.value, pointer) === null || + (isSafeNumber(item.value) && + redactor.text(String(Number(item.value)), pointer) === null) + ) + return null; + numeric_literals.push({ + pointer, + producer_type: "json-number", + literal: item.value, + }); + return isSafeNumber(item.value) ? Number(item.value) : null; + } + if (typeof item === "string") + return redactor.text( + item, + pointer, + header && + ["location", "referer", "origin"].includes( + String(parent?.name).toLowerCase(), + ), + ); + if (item === null || typeof item === "boolean") return item; + if (Array.isArray(item)) + return item.map((child, index) => + visit(child, capturePointer(pointer, String(index))), + ); + if (object(item)) + return Object.fromEntries( + Object.entries(item).flatMap(([key, child]) => { + if (sensitiveValues.some((literal) => key.includes(literal))) { + redactor.redactions.push({ + pointer, + reason: "explicit-sensitive-value", + scope: "property-name", + }); + return []; + } + return [[key, visit(child, capturePointer(pointer, key), item)]]; + }), + ); + return invalid("qlog parser returned a non-JSON value.", pointer); + }; + return { + reported: visit(value, ""), + numeric_literals, + binary_fields: [], + redactions: redactor.redactions, + }; +}; + +const qlogToken = ( + eventName: unknown, + pointer: string, + parent?: Record, +): boolean => { + if ( + packetEvent(eventName) && + /^\/data\/frames\/\d+\/reset_token$/u.test(pointer) && + parent?.frame_type === "new_connection_id" + ) + return true; + if ( + packetEvent(eventName) && + /^\/data\/frames\/\d+\/token$/u.test(pointer) && + parent?.frame_type === "new_token" + ) + return true; + if ( + eventName === "transport:parameters_set" && + pointer === "/data/stateless_reset_token" + ) + return true; + return false; +}; diff --git a/src/browser/history/SazCapture.ts b/src/browser/history/SazCapture.ts new file mode 100644 index 000000000..0d597eb5a --- /dev/null +++ b/src/browser/history/SazCapture.ts @@ -0,0 +1,174 @@ +import { ZipArtifactReader } from "../../artifacts/ZipArtifactReader.js"; +import { + ArtifactReaderFailure, + type ArtifactEntry, +} from "../../artifacts/ArtifactReader.js"; +import { + WEB_NETWORK_CAPTURE_LIMITS, + type WebNetworkCaptureRecord, +} from "../../domain/webNetworkCapture.js"; +import { SAZ_CAPTURE_PROVIDER_IDENTITY } from "./CaptureRelease.js"; +import { CaptureFormatError } from "./CaptureFormatError.js"; +import { decodeSazHttp } from "./SazHttp.js"; +import { decodeSazMetadata } from "./SazMetadata.js"; +import { projectSazRecord, type SazValue } from "./SazProjection.js"; + +/** Decode native SAZ sessions without extracting files, running Fiddler or converting to HAR. */ +export const decodeSazCapture = async ( + snapshotPath: string, + sensitiveValues: readonly string[], +) => { + const reader = new ZipArtifactReader( + snapshotPath, + "zip", + WEB_NETWORK_CAPTURE_LIMITS.inputBytes, + ); + try { + const groups = new Map(); + const inventory: SazValue[] = []; + const paths = new Set(); + let declaredBytes = 0; + for await (const entry of reader.entries()) { + if (paths.has(entry.path)) + throw new CaptureFormatError( + "format", + "SAZ contains duplicate archive member names.", + ); + paths.add(entry.path); + if (entry.encrypted) + throw new CaptureFormatError( + "unsupported", + "Encrypted SAZ archives are unsupported; export an unencrypted copy from Fiddler Everywhere.", + ); + if (entry.kind !== "file" && entry.kind !== "directory") + throw new CaptureFormatError( + "unsupported", + "SAZ archive links are unsupported.", + ); + if (entry.declaredSize !== null) { + if (!Number.isSafeInteger(entry.declaredSize) || entry.declaredSize < 0) + throw new CaptureFormatError("format", "SAZ member size is invalid."); + declaredBytes += entry.declaredSize; + } + if (declaredBytes > WEB_NETWORK_CAPTURE_LIMITS.inputBytes) + throw new CaptureFormatError( + "limit", + "SAZ expanded members exceed the 32 MiB complete-evidence budget.", + ); + inventory.push({ + path: entry.path, + kind: entry.kind, + bytes: entry.declaredSize, + }); + if (entry.kind !== "file") continue; + const match = /^raw\/(\d+)_(c\.txt|s\.txt|m\.xml|w\.txt|g\.txt)$/.exec( + entry.path, + ); + if (match?.[1] !== undefined) { + const group = groups.get(match[1]) ?? []; + group.push(entry); + groups.set(match[1], group); + } else if (entry.path.startsWith("raw/")) { + throw new CaptureFormatError( + "unsupported", + "SAZ contains an unrecognized raw session member.", + ); + } + } + if (groups.size === 0) + throw new CaptureFormatError( + "format", + "Archive contains no SAZ session members.", + ); + const records: WebNetworkCaptureRecord[] = []; + for (const [session_id, entries] of groups) { + const source: Record = { + session_id, + request: null, + response: null, + metadata: null, + websocket: null, + grpc: null, + }; + for (const entry of entries) { + const stream = await reader.open(entry); + const chunks: Buffer[] = []; + let length = 0; + for await (const chunk of stream) { + if (!Buffer.isBuffer(chunk)) + throw new CaptureFormatError( + "format", + "SAZ member stream returned non-byte data.", + ); + length += chunk.length; + if (length > (entry.declaredSize ?? 0)) + throw new CaptureFormatError( + "format", + "SAZ member exceeds its declared size.", + ); + chunks.push(chunk); + } + if (length !== entry.declaredSize) + throw new CaptureFormatError( + "format", + "SAZ member does not match its declared size.", + ); + const bytes = Buffer.concat(chunks, length); + if (entry.path.endsWith("_c.txt")) + source.request = { + member: entry.path, + ...decodeSazHttp(bytes, true), + }; + else if (entry.path.endsWith("_s.txt")) + source.response = { + member: entry.path, + ...decodeSazHttp(bytes, false), + }; + else if (entry.path.endsWith("_m.xml")) + source.metadata = { + member: entry.path, + document: decodeSazMetadata(bytes), + }; + else + source[entry.path.endsWith("_w.txt") ? "websocket" : "grpc"] = { + member: entry.path, + messages: bytes, + }; + } + records.push({ + ordinal: records.length, + location: { + kind: "archive-members", + members: entries.map((entry) => entry.path), + }, + ...projectSazRecord(source, sensitiveValues), + limitations: [], + }); + } + const container = projectSazRecord({ members: inventory }, sensitiveValues); + return { + decoder: { ...SAZ_CAPTURE_PROVIDER_IDENTITY }, + container: { + reported: container.reported, + numeric_literals: container.numeric_literals, + redactions: container.redactions, + records_pointer: null, + }, + total_records: records.length, + records, + }; + } catch (cause: unknown) { + if (cause instanceof CaptureFormatError) throw cause; + if (cause instanceof ArtifactReaderFailure && cause.reason === "limit") + throw new CaptureFormatError( + "limit", + "SAZ archive exceeds the ZIP reader's resource budget.", + ); + throw new CaptureFormatError( + "format", + "SAZ archive or session data is malformed or fails ZIP integrity validation.", + ); + } finally { + await reader.close(); + } +}; diff --git a/src/browser/history/SazHttp.ts b/src/browser/history/SazHttp.ts new file mode 100644 index 000000000..246dd6164 --- /dev/null +++ b/src/browser/history/SazHttp.ts @@ -0,0 +1,72 @@ +import { CaptureFormatError } from "./CaptureFormatError.js"; + +/** Preserve ordered HTTP fields and the stored body; never dechunk, decompress or fetch. */ +export const decodeSazHttp = (bytes: Buffer, request: boolean) => { + const crlfSplit = bytes.indexOf("\r\n\r\n"); + // Once a CRLF separator is found, only an earlier LF separator can win. + // Avoid searching an otherwise unrelated large body a second time. + const lfSplit = bytes + .subarray(0, crlfSplit < 0 ? bytes.length : crlfSplit) + .indexOf("\n\n"); + // The first separator ends the headers. Later separators belong to the + // stored body, which may use different line endings or contain binary data. + const split = + crlfSplit >= 0 && (lfSplit < 0 || crlfSplit < lfSplit) ? crlfSplit : -1; + const boundary = split < 0 ? lfSplit : split; + if (boundary < 0) + throw new CaptureFormatError( + "format", + "SAZ HTTP message has no header/body separator.", + ); + const lines = bytes + .subarray(0, boundary) + .toString("latin1") + .split(split < 0 ? "\n" : "\r\n"); + const first = lines.shift() ?? ""; + const fields = request + ? /^(\S+) +(\S+) +(HTTP\/\d+(?:\.\d+)?)$/.exec(first) + : /^(HTTP\/\d+(?:\.\d+)?) +(\d{3})(?: (.*))?$/.exec(first); + if (fields === null) + throw new CaptureFormatError("format", "SAZ HTTP start line is malformed."); + const headers: { name: string; value: string }[] = []; + for (const line of lines) { + if (/^[ \t]/.test(line)) { + const previous = headers.at(-1); + if (previous === undefined) + throw new CaptureFormatError( + "format", + "SAZ HTTP header continuation has no field.", + ); + previous.value += `${split < 0 ? "\n" : "\r\n"}${line}`; + continue; + } + const colon = line.indexOf(":"); + // HTTP/2 pseudo-headers use the second colon as the delimiter. + const delimiter = colon === 0 ? line.indexOf(":", 1) : colon; + if (delimiter < 1) + throw new CaptureFormatError("format", "SAZ HTTP header is malformed."); + const name = line.slice(0, delimiter); + if (!/^:?[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) + throw new CaptureFormatError( + "format", + "SAZ HTTP header name is malformed.", + ); + headers.push({ name, value: line.slice(delimiter + 1) }); + } + const start = request + ? { + method: fields[1] ?? "", + url: fields[2] ?? "", + http_version: fields[3] ?? "", + } + : { + http_version: fields[1] ?? "", + status: fields[2] ?? "", + reason: fields[3] ?? "", + }; + return { + ...start, + headers, + body: bytes.subarray(boundary + (split < 0 ? 2 : 4)), + }; +}; diff --git a/src/browser/history/SazMetadata.ts b/src/browser/history/SazMetadata.ts new file mode 100644 index 000000000..6e311f8e6 --- /dev/null +++ b/src/browser/history/SazMetadata.ts @@ -0,0 +1,83 @@ +import { DOMParser, ParseError, type Node } from "@xmldom/xmldom"; +import type { JsonValue } from "../../domain/jsonValue.js"; +import { WEB_NETWORK_CAPTURE_LIMITS } from "../../domain/webNetworkCapture.js"; +import { CaptureFormatError } from "./CaptureFormatError.js"; + +/** Preserve XML node order, attribute names and text without interpreting producer-specific flags. */ +export const decodeSazMetadata = (bytes: Buffer): JsonValue => { + let xml: string; + try { + const encoding = + bytes[0] === 0xff && bytes[1] === 0xfe + ? "utf-16le" + : bytes[0] === 0xfe && bytes[1] === 0xff + ? "utf-16be" + : "utf-8"; + xml = new TextDecoder(encoding, { fatal: true }).decode(bytes); + } catch { + throw new CaptureFormatError( + "unsupported", + "SAZ metadata must use UTF-8 or BOM-marked UTF-16.", + ); + } + let parseFailed = false; + let document: ReturnType; + try { + document = new DOMParser({ + normalizeLineEndings: (source) => source, + onError: () => { + parseFailed = true; + }, + }).parseFromString(xml, "application/xml"); + } catch (cause: unknown) { + if (!(cause instanceof ParseError)) throw cause; + throw new CaptureFormatError( + "format", + "SAZ metadata is not well-formed XML.", + ); + } + // The pinned parser does not resolve external or DTD-defined entities. + // Inspect its parsed node; text inside comments/CDATA is ordinary evidence. + if (document.doctype !== null) + throw new CaptureFormatError( + "unsupported", + "SAZ metadata DTDs are unsupported.", + ); + if (parseFailed) + throw new CaptureFormatError( + "format", + "SAZ metadata is not well-formed XML.", + ); + if (document.documentElement?.tagName !== "Session") + throw new CaptureFormatError( + "format", + "SAZ metadata must have a Session document element.", + ); + const visit = (node: Node, depth: number): JsonValue => { + if (depth > WEB_NETWORK_CAPTURE_LIMITS.depth) + throw new CaptureFormatError( + "input-limit", + "SAZ metadata exceeds the complete-evidence nesting budget.", + ); + const children: JsonValue[] = []; + for (let child = node.firstChild; child !== null; child = child.nextSibling) + children.push(visit(child, depth + 1)); + const attributes: JsonValue[] = []; + if (node.nodeType === 1) { + const element = node as import("@xmldom/xmldom").Element; + for (let i = 0; i < element.attributes.length; i++) { + const attribute = element.attributes.item(i); + if (attribute !== null) + attributes.push({ name: attribute.name, value: attribute.value }); + } + } + return { + name: node.nodeName, + type: node.nodeType, + value: node.nodeValue, + attributes, + children, + }; + }; + return visit(document, 0); +}; diff --git a/src/browser/history/SazProjection.ts b/src/browser/history/SazProjection.ts new file mode 100644 index 000000000..eba813628 --- /dev/null +++ b/src/browser/history/SazProjection.ts @@ -0,0 +1,131 @@ +import { createHash } from "node:crypto"; +import { isUtf8 } from "node:buffer"; +import type { JsonValue } from "../../domain/jsonValue.js"; +import { + WEB_NETWORK_CAPTURE_LIMITS, + type WebNetworkCaptureRecord, +} from "../../domain/webNetworkCapture.js"; +import { CaptureRedaction, capturePointer } from "./CaptureRedaction.js"; +import { CaptureFormatError } from "./CaptureFormatError.js"; + +export type SazValue = + | JsonValue + | Buffer + | { readonly [key: string]: SazValue } + | readonly SazValue[]; + +/** Project native byte fields with the same credential and explicit-literal exclusions as HAR. */ +export const projectSazRecord = ( + source: SazValue, + sensitiveValues: readonly string[], +) => { + const redactor = new CaptureRedaction(sensitiveValues); + const binary_fields: WebNetworkCaptureRecord["binary_fields"] = []; + const visit = ( + value: SazValue, + pointer: string, + depth: number, + parent?: Readonly>, + ): JsonValue => { + if (depth > WEB_NETWORK_CAPTURE_LIMITS.depth) + throw new CaptureFormatError( + "input-limit", + "SAZ projection exceeds the complete-evidence nesting budget.", + pointer, + ); + if (parent !== undefined && redactor.harCredential(pointer, parent)) + return redactor.credential(pointer); + if (Buffer.isBuffer(value)) { + const base64 = value.toString("base64"); + const sha256 = createHash("sha256").update(value).digest("hex"); + const hidden = + redactor.sensitiveBytes(value) || + sensitiveValues.some( + (literal) => + base64.includes(literal) || + sha256.includes(literal) || + String(value.length).includes(literal), + ); + if (hidden) { + binary_fields.push({ + pointer, + representation: "producer-bytes", + state: "redacted", + content_base64: null, + bytes: null, + sha256: null, + }); + redactor.redactions.push({ + pointer, + reason: "explicit-sensitive-value", + }); + return null; + } + binary_fields.push({ + pointer, + representation: "producer-bytes", + state: "retained", + content_base64: base64, + bytes: value.length, + sha256, + }); + return isUtf8(value) ? value.toString("utf8") : null; + } + if (typeof value === "string") { + // HTTP fields are Latin-1 views of bytes. A UTF-8 declaration must also + // exclude its byte spelling, even when its display is mojibake. + if ( + /^\/(request|response)\//.test(pointer) && + !pointer.endsWith("/member") && + redactor.sensitiveBytes(Buffer.from(value, "latin1")) + ) { + redactor.redactions.push({ + pointer, + reason: "explicit-sensitive-value", + }); + return null; + } + return redactor.text( + value, + pointer, + redactor.harTransportUrl(pointer, parent), + ); + } + if (value === null || typeof value === "boolean") return value; + if (typeof value === "number") + return redactor.text(String(value), pointer) === null ? null : value; + if (Array.isArray(value)) + return value.map((child: SazValue, i: number) => + visit(child, capturePointer(pointer, String(i)), depth + 1), + ); + return Object.fromEntries( + Object.entries(value).flatMap(([key, child]) => { + if (sensitiveValues.some((literal) => key.includes(literal))) { + redactor.redactions.push({ + pointer, + reason: "explicit-sensitive-value", + scope: "property-name", + }); + return []; + } + return [ + [ + key, + visit( + child, + capturePointer(pointer, key), + depth + 1, + value as Readonly>, + ), + ], + ]; + }), + ); + }; + return { + reported: visit(source, "", 0), + binary_fields, + numeric_literals: [], + redactions: redactor.redactions, + }; +}; diff --git a/src/browser/modules/WebModuleArtifacts.ts b/src/browser/modules/WebModuleArtifacts.ts index 287e6e8de..928025f09 100644 --- a/src/browser/modules/WebModuleArtifacts.ts +++ b/src/browser/modules/WebModuleArtifacts.ts @@ -4,6 +4,7 @@ import type { } from "../../application/WebModulePorts.js"; import type { WebScriptArtifactPort } from "../../application/WebScriptArtifactPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; +import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { jsonObjectSchema } from "../../domain/jsonValue.js"; import { err, ok } from "../../domain/result.js"; import type { WebModuleTraceInput } from "../../domain/webModuleTrace.js"; @@ -15,14 +16,64 @@ import { /** Add an explicitly selected import map to a verified captured-script source. */ export class LocalWebModuleArtifacts implements WebModuleArtifactPort { + readonly scripts: WebScriptArtifactPort; + readonly #resources: ArtifactResourceScope; + constructor( - readonly scripts: WebScriptArtifactPort = new LocalWebScriptArtifacts( - "trace_web_module_imports", - ), - ) {} + scripts?: WebScriptArtifactPort, + resources = scripts instanceof LocalWebScriptArtifacts + ? scripts.resources + : new ArtifactResourceScope(), + ) { + this.#resources = resources; + this.scripts = + scripts ?? + new LocalWebScriptArtifacts("trace_web_module_imports", resources); + } + + async close(): Promise { + const closeScript = + this.scripts instanceof LocalWebScriptArtifacts && + this.scripts.resources === this.#resources + ? undefined + : this.scripts.close?.bind(this.scripts); + const results = await Promise.allSettled([ + Promise.resolve().then(() => this.#resources.close()), + ...(closeScript === undefined + ? [] + : [Promise.resolve().then(closeScript)]), + ]); + const failures = results.flatMap((result) => + result.status === "rejected" ? [result.reason] : [], + ); + if (failures.length > 0) + throw new AggregateError(failures, "Web module artifact cleanup failed"); + } /** Read selected source and optional map without website requests. */ async load(input: WebModuleTraceInput, options?: ExecutionOptions) { + try { + return await this.#resources.run(() => this.#load(input, options)); + } catch (cause: unknown) { + return err( + webArtifactReadError( + cause, + { + operation: "trace_web_module_imports", + field: + input.import_map === undefined + ? ["manifest_path"] + : ["import_map", "path"], + targetPath: input.import_map?.path ?? input.manifest_path, + callerSelected: input.import_map !== undefined, + }, + options?.signal, + ), + ); + } + } + + async #load(input: WebModuleTraceInput, options?: ExecutionOptions) { const loaded = await this.scripts.load(input, options); if (!loaded.ok) return loaded; if (input.import_map === undefined) @@ -33,6 +84,7 @@ export class LocalWebModuleArtifacts implements WebModuleArtifactPort { selected.path, 4 * 1024 * 1024, options?.signal, + this.#resources, ); const importMap: WebModuleArtifacts["importMap"] = { file: { diff --git a/src/captures/TsharkCaptureProvider.ts b/src/captures/TsharkCaptureProvider.ts index 13cadd774..d22515929 100644 --- a/src/captures/TsharkCaptureProvider.ts +++ b/src/captures/TsharkCaptureProvider.ts @@ -1,3 +1,12 @@ +import { + type InspectPacketFieldsInput, + packetFieldsCatalogSchema, +} from "../domain/captures/packetFields.js"; +import { + parseFieldDiscovery, + FieldDiscoveryBudgetError, + FIELD_RECORD_BUDGET, +} from "./parseFieldDiscovery.js"; import { readLinuxResourceLimits, type LinuxResourceLimits, @@ -91,17 +100,31 @@ export class TsharkCaptureProvider implements PacketCapturePort { options?: ExecutionOptions, ): Promise> { return this.#resources.run( - () => this.#inspect(input, options), + () => this.#executeRequest(input, options), options?.signal, ); } + inspectFields( + input: InspectPacketFieldsInput, + options?: ExecutionOptions, + ): Promise> { + return this.#resources.run( + () => this.#executeRequest(input, options), + options?.signal, + "inspect_packet_fields", + ); + } close(): Promise { return this.#resources.close(); } - async #inspect( - input: InspectPacketCaptureInput, + async #executeRequest( + input: InspectPacketCaptureInput | InspectPacketFieldsInput, options?: ExecutionOptions, ): Promise> { + const operation = "path" in input ? OPERATION : "inspect_packet_fields"; + // TShark 4.6.9 emits a 22.3 MB glossary; keep capture output capped at 4 MiB. + const limits = + "path" in input ? LIMITS : { ...LIMITS, output_bytes: 32 * 1024 * 1024 }; let phase: | "configuration" | "artifact" @@ -109,12 +132,12 @@ export class TsharkCaptureProvider implements PacketCapturePort { | "producer" | "integrity" = "configuration"; let capturedOutput: AnalysisCapturedOutput | undefined; - let resourcePath = input.path; + let resourcePath = "path" in input ? input.path : "TShark field glossary"; let effectiveLimits: LinuxResourceLimits | undefined; let root: ArtifactAnalysisRuntime | undefined; let result: Result; try { - if (options?.signal?.aborted) throw new AnalysisCancelledError(OPERATION); + if (options?.signal?.aborted) throw new AnalysisCancelledError(operation); await this.#resources.release(); if (this.platform !== "linux") throw new Error( @@ -141,7 +164,7 @@ export class TsharkCaptureProvider implements PacketCapturePort { 64 * 1024 * 1024, options?.signal, ); - effectiveLimits = await this.#resources.readLimits(LIMITS); + effectiveLimits = await this.#resources.readLimits(limits); const limitArguments = [ `--as=${effectiveLimits.address_space_bytes}:${effectiveLimits.address_space_bytes}`, `--fsize=${effectiveLimits.file_bytes}:${effectiveLimits.file_bytes}`, @@ -152,7 +175,7 @@ export class TsharkCaptureProvider implements PacketCapturePort { ]; phase = "workspace"; root = await this.createRuntime(); - this.#resources.retain(root, undefined); + this.#resources.retain(root, undefined, operation); const snapshotPath = join(root.path, "capture"); const configurationPath = join(root.path, "configuration"); await mkdir(configurationPath, { mode: 0o700 }); @@ -170,8 +193,8 @@ export class TsharkCaptureProvider implements PacketCapturePort { }, }, { - timeoutMs: LIMITS.command_timeout_ms, - diagnosticBytes: LIMITS.output_bytes, + timeoutMs: limits.command_timeout_ms, + diagnosticBytes: limits.output_bytes, acceptNonZeroExit: true, }, { @@ -200,24 +223,24 @@ export class TsharkCaptureProvider implements PacketCapturePort { ); if (currentLimiter.sha256 !== limiterIdentity.sha256) throw new AnalysisArtifactChangedError( - OPERATION, + operation, limiter, "Configured resource limiter changed during analysis.", { capturedOutput }, ); if (current.sha256 !== tool.sha256) throw new AnalysisArtifactChangedError( - OPERATION, + operation, command, "Configured TShark executable changed during analysis.", { capturedOutput }, ); phase = previousPhase; - resourcePath = input.path; + resourcePath = "path" in input ? input.path : command; if (output.exitCode !== 0) throw new ProviderAdapterError( TSHARK_PROVIDER_IDENTITY.id, - OPERATION, + operation, { diagnostics: { exit_code: output.exitCode ?? null, @@ -238,86 +261,15 @@ export class TsharkCaptureProvider implements PacketCapturePort { throw new Error( "Expected TShark 4.x; inspect the selected installation.", ); - phase = "artifact"; - const selected = await this.#resources.read( - input.path, - LIMITS.input_bytes, - options?.signal, - ); - phase = "workspace"; - await writeFile(snapshotPath, selected.bytes, { - flag: "wx", - mode: 0o400, - }); - phase = "producer"; - const args = [ - "-n", - "-r", - "capture", - "-T", - "json", - "--no-duplicate-keys", - "--temp-dir=.", - ...(input.two_pass ? ["-2"] : []), - ...(input.packet_limit === null - ? [] - : ["-c", String(input.packet_limit)]), - ...(input.display_filter === null ? [] : ["-Y", input.display_filter]), - ...input.decode_as.flatMap((value) => ["-d", value]), - ...[...new Set(["frame.number", ...input.fields])].flatMap((field) => [ - "-e", - field, - ]), - ]; - const output = await execute(args); - phase = "integrity"; - resourcePath = snapshotPath; - if ( - (await this.#resources.read(snapshotPath, LIMITS.input_bytes)) - .sha256 !== selected.sha256 - ) - throw new AnalysisArtifactChangedError( - OPERATION, - snapshotPath, - "TShark changed the private capture copy.", - capturedOutput === undefined ? {} : { capturedOutput }, - ); - phase = "producer"; - resourcePath = input.path; - const matchingPackets = parsePacketOutput( - output.stdout.text, - input.fields, - ); - const start = Math.min(input.match_offset, matchingPackets.length); - const end = - input.match_limit === null - ? matchingPackets.length - : start + Math.min(input.match_limit, matchingPackets.length - start); - const packets = matchingPackets.slice(start, end); - const report = packetCaptureSchema.parse({ - artifact: { - path: input.path, - sha256: selected.sha256, - bytes: selected.bytes.length, - }, - selection: input, - packets, - output_window: { - matching_packets: matchingPackets.length, - returned_packets: packets.length, - has_more: end < matchingPackets.length, - }, - read_scope: - input.packet_limit === null ? "to-eof" : "up-to-input-packet-limit", - configuration: "private-empty-personal-profile", - diagnostics: output.stderr.text, + const metadata = (args: readonly string[], diagnostics: string) => ({ + diagnostics, tool: { configured_path: configured, path: command, sha256: tool.sha256, version_banner: version.stdout.text, version_diagnostics: version.stderr.text, - arguments: args, + arguments: [...args], }, resource_limiter: { configured_path: configuredLimiter, @@ -325,33 +277,136 @@ export class TsharkCaptureProvider implements PacketCapturePort { sha256: limiterIdentity.sha256, arguments: limitArguments, }, - limits: { ...LIMITS, ...effectiveLimits }, - hardware_acquisition: "not-performed", + limits: { ...limits, ...effectiveLimits }, + hardware_acquisition: "not-performed" as const, }); - result = ok( - createAnalysisExecution(report, TSHARK_PROVIDER_IDENTITY, { - subject: { + if (!("path" in input)) { + phase = "producer"; + const args = ["-G", "fields"]; + const output = await execute(args); + const report = packetFieldsCatalogSchema.parse({ + selection: input, + ...parseFieldDiscovery(output.stdout.text, input), + ...metadata(args, output.stderr.text), + limits: { + ...limits, + ...effectiveLimits, + record_budget_bytes: FIELD_RECORD_BUDGET, + }, + configuration: "private-empty-personal-profile", + }); + result = ok( + createAnalysisExecution(report, TSHARK_PROVIDER_IDENTITY, { + subject: { path: command, sha256: tool.sha256, format: "file" }, + limitations: [ + "Protocol and field registrations describe the selected installation, not traffic observed in a capture. Duplicate abbreviations remain distinct producer records with source line numbers.", + "Each request probes again without caching. The private empty personal profile does not fingerprint or isolate installed libraries, global configuration or plugins; they remain trusted.", + "No capture file, interface or device is opened. Resource ceilings do not constitute an OS sandbox. Glossary output is capped at 32 MiB and selected record representation at 8 MiB before expansion.", + ], + }), + ); + } else { + phase = "artifact"; + const selected = await this.#resources.read( + input.path, + LIMITS.input_bytes, + options?.signal, + ); + phase = "workspace"; + await writeFile(snapshotPath, selected.bytes, { + flag: "wx", + mode: 0o400, + }); + phase = "producer"; + const args = [ + "-n", + "-r", + "capture", + "-T", + "json", + "--no-duplicate-keys", + "--temp-dir=.", + ...(input.two_pass ? ["-2"] : []), + ...(input.packet_limit === null + ? [] + : ["-c", String(input.packet_limit)]), + ...(input.display_filter === null + ? [] + : ["-Y", input.display_filter]), + ...input.decode_as.flatMap((value) => ["-d", value]), + ...[...new Set(["frame.number", ...input.fields])].flatMap( + (field) => ["-e", field], + ), + ]; + const output = await execute(args); + phase = "integrity"; + resourcePath = snapshotPath; + if ( + (await this.#resources.read(snapshotPath, LIMITS.input_bytes)) + .sha256 !== selected.sha256 + ) + throw new AnalysisArtifactChangedError( + operation, + snapshotPath, + "TShark changed the private capture copy.", + capturedOutput === undefined ? {} : { capturedOutput }, + ); + phase = "producer"; + resourcePath = "path" in input ? input.path : command; + const matchingPackets = parsePacketOutput( + output.stdout.text, + input.fields, + ); + const start = Math.min(input.match_offset, matchingPackets.length); + const end = + input.match_limit === null + ? matchingPackets.length + : start + + Math.min(input.match_limit, matchingPackets.length - start); + const packets = matchingPackets.slice(start, end); + const report = packetCaptureSchema.parse({ + artifact: { path: input.path, sha256: selected.sha256, - format: "file", + bytes: selected.bytes.length, }, - locations: [{ kind: "artifact-path", path: input.path }], - limitations: [ - "Fields are TShark dissector observations under the selected filter/decode-as/pass settings, not independently verified protocol semantics. Missing fields are absent from the producer output, not known zero or empty values.", - "Packet limits count input packets before display filtering. Filtered results do not establish whole-capture or device traffic absence. Two-pass reassembly cannot recover bytes missing from the recording or beyond the read limit.", - "Repeated field values remain ordered string arrays; raw packet bytes are included only when explicitly selected as a supported field. Export index/score metadata are omitted. All stderr, including warnings on exit zero, is retained.", - "A private empty personal configuration is used. Installed libraries, global configuration and dissector plugins are trusted and not fully fingerprinted. File-only analysis and disabled name resolution do not constitute an OS sandbox.", - "Linux prlimit enforces soft and hard ceilings before execution, preserving stricter inherited limits: at most 1 GiB address space per process, 64 MiB per file, 30 CPU seconds and no core dumps. Effective limits are reported. Resident input is capped at 32 MiB, each command at 30 wall-clock seconds and combined output at 4 MiB. Output overflow fails. These are per-process/per-file limits, not aggregate memory or filesystem quotas; caller-supplied tools and the limiter are trusted.", - ], - }), - ); + selection: input, + packets, + output_window: { + matching_packets: matchingPackets.length, + returned_packets: packets.length, + has_more: end < matchingPackets.length, + }, + read_scope: + input.packet_limit === null ? "to-eof" : "up-to-input-packet-limit", + configuration: "private-empty-personal-profile", + ...metadata(args, output.stderr.text), + }); + result = ok( + createAnalysisExecution(report, TSHARK_PROVIDER_IDENTITY, { + subject: { + path: input.path, + sha256: selected.sha256, + format: "file", + }, + locations: [{ kind: "artifact-path", path: input.path }], + limitations: [ + "Fields are TShark dissector observations under the selected filter/decode-as/pass settings, not independently verified protocol semantics. Missing fields are absent from the producer output, not known zero or empty values.", + "Packet limits count input packets before display filtering. Filtered results do not establish whole-capture or device traffic absence. Two-pass reassembly cannot recover bytes missing from the recording or beyond the read limit.", + "Repeated field values remain ordered string arrays; raw packet bytes are included only when explicitly selected as a supported field. Export index/score metadata are omitted. All stderr, including warnings on exit zero, is retained.", + "A private empty personal configuration is used. Installed libraries, global configuration and dissector plugins are trusted and not fully fingerprinted. File-only analysis and disabled name resolution do not constitute an OS sandbox.", + "Linux prlimit enforces soft and hard ceilings before execution, preserving stricter inherited limits: at most 1 GiB address space per process, 64 MiB per file, 30 CPU seconds and no core dumps. Effective limits are reported. Resident input is capped at 32 MiB, each command at 30 wall-clock seconds and combined output at 4 MiB. Output overflow fails. These are per-process/per-file limits, not aggregate memory or filesystem quotas; caller-supplied tools and the limiter are trusted.", + ], + }), + ); + } } catch (cause) { if ( root !== undefined && cause instanceof OwnedCommandFailure && cause.cleanupOwner !== undefined ) - this.#resources.retain(root, cause.cleanupOwner); + this.#resources.retain(root, cause.cleanupOwner, operation); result = err( this.#failure( cause, @@ -360,18 +415,23 @@ export class TsharkCaptureProvider implements PacketCapturePort { root?.path ?? null, effectiveLimits, capturedOutput, + operation, + limits, ), ); } - return this.#resources.finish(result, (execution) => - createEvidence(execution.subject ?? undefined, execution.provider, { - operation: OPERATION, - parameters: input, - result: execution.result, - confidence: "observed", - locations: execution.locations, - limitations: execution.limitations, - }), + return this.#resources.finish( + result, + (execution) => + createEvidence(execution.subject ?? undefined, execution.provider, { + operation, + parameters: input, + result: execution.result, + confidence: "observed", + locations: execution.locations, + limitations: execution.limitations, + }), + operation, ); } #failure( @@ -386,6 +446,11 @@ export class TsharkCaptureProvider implements PacketCapturePort { workspacePath: string | null, effectiveLimits: LinuxResourceLimits | undefined, observedOutput: AnalysisCapturedOutput | undefined, + operation = OPERATION, + limits: { + readonly output_bytes: number; + readonly command_timeout_ms: number; + } = LIMITS, ): AnalysisError { if (cause instanceof AnalysisError) return cause; if (cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined) @@ -393,15 +458,34 @@ export class TsharkCaptureProvider implements PacketCapturePort { cause.cleanup, cause, observedOutput, + operation, ); if ( (cause instanceof Error && cause.name === "AbortError") || (cause instanceof ArtifactReaderFailure && cause.reason === "cancelled") ) - return new AnalysisCancelledError(OPERATION, { cause }); + return new AnalysisCancelledError(operation, { cause }); + if (cause instanceof FieldDiscoveryBudgetError) + return new AnalysisResourceConstraintError( + operation, + "memory", + cause.message, + { record_budget_bytes: FIELD_RECORD_BUDGET }, + { + cause, + ...(observedOutput === undefined + ? {} + : { capturedOutput: observedOutput }), + }, + ); const reason = cause instanceof Error ? cause.message : String(cause); if (cause instanceof OwnedCommandFailure) - return this.#resources.commandFailure(cause, LIMITS, effectiveLimits); + return this.#resources.commandFailure( + cause, + limits, + effectiveLimits, + operation, + ); if (phase === "workspace") { const code = cause instanceof Error && @@ -411,13 +495,13 @@ export class TsharkCaptureProvider implements PacketCapturePort { : null; if (code === "ENOSPC" || code === "EDQUOT" || code === "EFBIG") return new AnalysisResourceConstraintError( - OPERATION, + operation, "file-size", `Private analysis workspace failed (${code}): ${reason}`, { workspace_path: workspacePath, system_code: code }, { cause }, ); - return new ProviderAdapterError(TSHARK_PROVIDER_IDENTITY.id, OPERATION, { + return new ProviderAdapterError(TSHARK_PROVIDER_IDENTITY.id, operation, { cause, userMessage: `Cannot prepare the private analysis workspace: ${reason}`, diagnostics: { @@ -440,12 +524,12 @@ export class TsharkCaptureProvider implements PacketCapturePort { ["limit", "integrity", "path"].includes(cause.reason) ) return new AnalysisArtifactChangedError( - OPERATION, + operation, path, `Post-run identity verification failed for ${path}: ${reason}`, detail, ); - return new ProviderAdapterError(TSHARK_PROVIDER_IDENTITY.id, OPERATION, { + return new ProviderAdapterError(TSHARK_PROVIDER_IDENTITY.id, operation, { ...detail, diagnostics: { stage: "integrity", resource_path: path, reason }, }); @@ -453,10 +537,13 @@ export class TsharkCaptureProvider implements PacketCapturePort { if (phase === "configuration") return new AnalysisCapabilityUnavailableError( TSHARK_PROVIDER_IDENTITY.id, - OPERATION, + operation, reason, { cause, + ...(observedOutput === undefined + ? {} + : { capturedOutput: observedOutput }), userMessage: `${reason} On Linux, configure TShark 4.x through REA_TSHARK_COMMAND and util-linux prlimit through REA_TSHARK_PRLIMIT_COMMAND (default /usr/bin/prlimit).`, }, ); @@ -466,14 +553,14 @@ export class TsharkCaptureProvider implements PacketCapturePort { cause.reason === "limit" ) return new AnalysisResourceConstraintError( - OPERATION, + operation, "file-size", reason, { input_bytes: LIMITS.input_bytes }, { cause }, ); if (cause instanceof ArtifactReaderFailure && cause.reason === "integrity") - return new AnalysisArtifactChangedError(OPERATION, path, reason, { + return new AnalysisArtifactChangedError(operation, path, reason, { cause, }); if ( @@ -482,13 +569,18 @@ export class TsharkCaptureProvider implements PacketCapturePort { "code" in cause && (cause.code === "EACCES" || cause.code === "EPERM") ) - return new AnalysisAccessDeniedError(OPERATION, path, cause.code, { + return new AnalysisAccessDeniedError(operation, path, cause.code, { cause, }); if (phase === "artifact") - return new AnalysisInputError(OPERATION, { cause }, [ + return new AnalysisInputError(operation, { cause }, [ { path: ["path"], reason: "invalid_value", message: reason }, ]); - return new AnalysisOutputError(OPERATION, reason, { cause }); + return new AnalysisOutputError(operation, reason, { + cause, + ...(observedOutput === undefined + ? {} + : { capturedOutput: observedOutput }), + }); } } diff --git a/src/captures/parseFieldDiscovery.ts b/src/captures/parseFieldDiscovery.ts new file mode 100644 index 000000000..6498e56dc --- /dev/null +++ b/src/captures/parseFieldDiscovery.ts @@ -0,0 +1,92 @@ +import type { + InspectPacketFieldsInput, + PacketFieldRecord, +} from "../domain/captures/packetFields.js"; + +export class FieldDiscoveryBudgetError extends Error {} +export const FIELD_RECORD_BUDGET = 8 * 1024 * 1024; + +/** TShark -G fields: P/name/abbreviation or F/name/abbreviation/type/parent/base/mask/blurb. */ +export const parseFieldDiscovery = ( + text: string, + input: InspectPacketFieldsInput, +) => { + const copy = (value: string) => + Buffer.from(value, "utf16le").toString("utf16le"); + const query = input.query.toLowerCase(); + const records: PacketFieldRecord[] = []; + let examined = 0, + matching = 0, + sourceLine = 0, + budget = 0; + // Walk the bounded text once; allocate record objects only for the requested page. + for (let start = 0; start < text.length;) { + const end = text.indexOf("\n", start); + let line = text.slice(start, end < 0 ? text.length : end); + start = end < 0 ? text.length : end + 1; + sourceLine++; + if (line.endsWith("\r")) line = line.slice(0, -1); + const columns = line.split("\t", 9); + const [tag, name, abbreviation] = columns; + if ( + !( + (tag === "P" && columns.length === 3) || + (tag === "F" && columns.length === 8) + ) || + name === undefined || + abbreviation === undefined || + abbreviation === "" + ) + throw new Error( + `Malformed TShark field glossary record at line ${sourceLine}`, + ); + if ((input.kind === "protocols") !== (tag === "P")) continue; + examined++; + if ( + input.protocol !== null && + (tag === "P" ? abbreviation : columns[4]) !== input.protocol + ) + continue; + if ( + ![name, abbreviation, ...(tag === "F" ? [columns[7] ?? ""] : [])].some( + (value) => value.toLowerCase().includes(query), + ) + ) + continue; + matching++; + if ( + matching <= input.offset || + records.length >= (input.limit ?? Number.MAX_SAFE_INTEGER) + ) + continue; + // Six bytes per source byte covers worst-case JSON escaping, plus record bookkeeping. + budget += Buffer.byteLength(line, "utf8") * 6 + 512; + if (budget > FIELD_RECORD_BUDGET) + throw new FieldDiscoveryBudgetError( + "Selected glossary records exceed the 8 MiB representation budget; narrow the query or page size", + ); + // Detach retained fields from the much larger producer string. + records.push({ + source_line: sourceLine, + kind: tag === "P" ? "protocol" : "field", + name: copy(name), + abbreviation: copy(abbreviation), + field_type: tag === "F" ? copy(columns[3] ?? "") : null, + parent_protocol: tag === "F" ? copy(columns[4] ?? "") : null, + display_base: tag === "F" ? copy(columns[5] ?? "") : null, + bitmask: tag === "F" ? copy(columns[6] ?? "") : null, + description: tag === "F" ? copy(columns[7] ?? "") : null, + }); + } + if (sourceLine === 0) + throw new Error("TShark returned an empty field glossary"); + return { + records, + output_window: { + examined, + matching, + returned: records.length, + has_more: Math.max(0, matching - input.offset) > records.length, + }, + }; +}; diff --git a/src/cli.ts b/src/cli.ts index 0b545c0ba..d1bdf2912 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -24,6 +24,7 @@ import { registerManagedCommands } from "./cli/managedCommands.js"; import { registerFirmwareCommands } from "./cli/firmwareCommands.js"; import { registerAndroidCommands } from "./cli/androidCommands.js"; import { registerApktoolCommands } from "./cli/apktoolCommands.js"; +import { registerPcapCommands } from "./cli/pcapCommands.js"; import { registerFlutterCommands } from "./cli/flutterCommands.js"; import { registerJebCommands } from "./cli/jebCommands.js"; import { registerAdbCommands } from "./cli/adbCommands.js"; @@ -105,6 +106,7 @@ export const createCli = ( registerManagedCommands(cli, logger, analysis.runProviderAnalysis); registerAndroidCommands(cli, logger, environment); registerApktoolCommands(cli, logger, environment); + registerPcapCommands(cli, logger, environment); registerFlutterCommands(cli, logger); registerJebCommands(cli, logger, environment); registerAdbCommands(cli, logger, environment); diff --git a/src/cli/apktoolCommands.ts b/src/cli/apktoolCommands.ts index d7b30a617..c7795f9d4 100644 --- a/src/cli/apktoolCommands.ts +++ b/src/cli/apktoolCommands.ts @@ -62,15 +62,17 @@ export const registerApktoolCommands = ( .describe( "Project strings from res/values- instead of the default", ), - "no-strings": z + strings: z .boolean() - .default(false) - .describe("Skip projecting string resources"), + .default(true) + .describe( + "Include string resources; use --no-strings to skip projecting them", + ), }), run: ({ args, options }) => execute(CLI_COMMANDS.decodeAndroidResources, "decode_android_resources", { path: args.path, - include_strings: !options["no-strings"], + include_strings: options.strings, ...(options.locale === undefined ? {} : { locale: options.locale }), }), }); diff --git a/src/cli/binaryDiagnosticsCommands.ts b/src/cli/binaryDiagnosticsCommands.ts index bddd16bed..5cb9577bd 100644 --- a/src/cli/binaryDiagnosticsCommands.ts +++ b/src/cli/binaryDiagnosticsCommands.ts @@ -7,11 +7,12 @@ import { } from "../composition/binaryDiagnostics.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import { logCliCommand } from "../cliLogging.js"; -import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; import { withCommandCancellation } from "./commandCancellation.js"; import { inspectPeResourcesInputSchema } from "../domain/native/peResources.js"; +import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; +import { finishAnalysisCommand } from "./finishAnalysisCommand.js"; /** Inspect operator-selected files through the same shared workflow as MCP. */ export const registerBinaryDiagnosticsCommands = ( @@ -19,7 +20,6 @@ export const registerBinaryDiagnosticsCommands = ( logger: Logger, environment: Readonly, ): void => { - const pe = createPeResourcesService(); cli.command(CLI_COMMANDS.inspectPeResources, { description: "Inspect PE resource identities, payload ranges, hashes and icon-group relationships", @@ -29,19 +29,28 @@ export const registerBinaryDiagnosticsCommands = ( maxEntries: inspectPeResourcesInputSchema.shape.max_entries, }), run: ({ args, options }) => - withCommandCancellation((signal) => - logCliCommand(logger, CLI_COMMANDS.inspectPeResources, async () => { - const result = await pe.inspect( - { - path: resolve(args.path), - max_file_bytes: options.maxFileBytes, - max_entries: options.maxEntries, - }, - { signal }, - ); - return result.ok ? result.value : projectAnalysisError(result.error); - }), - ), + withCommandCancellation(async (signal) => { + const pe = createPeResourcesService(); + return await logCliCommand( + logger, + CLI_COMMANDS.inspectPeResources, + async () => + finishAnalysisCommand( + () => + pe.inspect( + { + path: resolve(args.path), + max_file_bytes: options.maxFileBytes, + max_entries: options.maxEntries, + }, + { signal }, + ), + pe, + "rea-pe-resources", + "inspect_pe_resources", + ), + ); + }), }); const service = createBinaryLayoutService(environment); cli.command(CLI_COMMANDS.inspectBinaryLayout, { diff --git a/src/cli/captureCommands.ts b/src/cli/captureCommands.ts index 281be7457..542361e90 100644 --- a/src/cli/captureCommands.ts +++ b/src/cli/captureCommands.ts @@ -1,8 +1,6 @@ +import { inspectPacketFieldsInputSchema } from "../domain/captures/packetFields.js"; import { z } from "incur"; import type { PacketCaptureService } from "../application/captures/PacketCaptureService.js"; -import { AnalysisError } from "../domain/analysisErrorBase.js"; -import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; -import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import { resolve } from "node:path"; import { createPacketCaptureService } from "../composition/captures.js"; import { @@ -12,19 +10,60 @@ import { } from "../domain/captures/packetCapture.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import { logCliCommand } from "../cliLogging.js"; -import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; import { withCommandCancellation } from "./commandCancellation.js"; +import { finishAnalysisCommand } from "./finishAnalysisCommand.js"; export const registerCaptureCommands = ( cli: CliInstance, logger: Logger, environment: Readonly, service: Pick< PacketCaptureService, - "inspect" | "close" + "inspect" | "inspectFields" | "close" > = createPacketCaptureService(environment), ): void => { + cli.command(CLI_COMMANDS.inspectPacketFields, { + description: "Search installed TShark protocol and field definitions", + options: z + .object({ + ...inspectPacketFieldsInputSchema.shape, + limit: z + .number() + .int() + .positive() + .max(Number.MAX_SAFE_INTEGER) + .optional() + .describe("Maximum matching records to return; defaults to 50"), + all: z + .boolean() + .default(false) + .describe("Return all remaining matches within resource limits"), + }) + .superRefine((options, context) => { + if (options.all && options.limit !== undefined) + context.addIssue({ + code: "custom", + path: ["all"], + message: "all and limit are mutually exclusive", + }); + }), + run: ({ options: { all, ...options } }) => + withCommandCancellation((signal) => + logCliCommand(logger, CLI_COMMANDS.inspectPacketFields, async () => + finishAnalysisCommand( + () => + service.inspectFields( + { ...options, ...(all ? { limit: null } : {}) }, + { signal }, + ), + service, + "tshark-capture", + "inspect_packet_fields", + ), + ), + ), + }); cli.command(CLI_COMMANDS.inspectPacketCapture, { description: "Inspect an existing packet capture with caller-supplied TShark", @@ -60,39 +99,20 @@ export const registerCaptureCommands = ( run: ({ args, options: { all_matches, ...options } }) => withCommandCancellation((signal) => logCliCommand(logger, CLI_COMMANDS.inspectPacketCapture, async () => { - const result = await service.inspect( - { - ...options, - ...(all_matches ? { match_limit: null } : {}), - path: resolve(args.path), - }, - { signal }, + return finishAnalysisCommand( + () => + service.inspect( + { + ...options, + ...(all_matches ? { match_limit: null } : {}), + path: resolve(args.path), + }, + { signal }, + ), + service, + "tshark-capture", + "inspect_packet_capture", ); - // A one-shot command must retry retained cleanup before discarding its owner. - try { - await service.close(); - } catch (cause) { - const cleanup = - cause instanceof AnalysisError - ? cause - : new ProviderCleanupError( - "tshark-capture", - [], - { reason: String(cause) }, - { cause, operation: "inspect_packet_capture" }, - ); - if (result.ok) cleanup.retainPartialObservation(result.value); - return projectAnalysisError( - result.ok - ? cleanup - : analysisErrorWithCleanupFailure( - result.error, - cleanup, - "inspect_packet_capture", - ), - ); - } - return result.ok ? result.value : projectAnalysisError(result.error); }), ), }); diff --git a/src/cli/coreBinaryCommands.ts b/src/cli/coreBinaryCommands.ts index 70405302e..710b39181 100644 --- a/src/cli/coreBinaryCommands.ts +++ b/src/cli/coreBinaryCommands.ts @@ -137,6 +137,13 @@ const registerDecompileCommand = ( .describe( "Procedure name or address; use --procedure= for leading dashes", ), + "file-offset": z + .string() + .regex(/^0x[0-9a-fA-F]+$/u) + .optional() + .describe( + "Ghidra source-file byte offset; mapped internally to an analysis address", + ), snapshot: z .string() .min(1) @@ -152,8 +159,17 @@ const registerDecompileCommand = ( { procedure: resolveCliAnalysisSelector( args.address, - options.procedure, - "procedure", + options["file-offset"] === undefined + ? options.procedure + : resolveCliAnalysisSelector( + options.procedure, + `file-offset:${options["file-offset"]}`, + "file-offset", + "procedure_pseudo_code", + ), + options["file-offset"] === undefined + ? "procedure" + : "file-offset", "procedure_pseudo_code", ), }, diff --git a/src/cli/finishAnalysisCommand.ts b/src/cli/finishAnalysisCommand.ts new file mode 100644 index 000000000..9394ba828 --- /dev/null +++ b/src/cli/finishAnalysisCommand.ts @@ -0,0 +1,69 @@ +import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; +import { + AnalysisError, + type AnalysisPartialObservation, +} from "../domain/analysisErrorBase.js"; +import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; +import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; +import { ProviderAdapterError } from "../domain/providerAdapterError.js"; +import { ProviderCleanupError } from "../domain/providerCleanupError.js"; +import type { Result } from "../domain/result.js"; + +/** Finish a one-shot CLI operation without discarding its primary result on close failure. */ +export const finishAnalysisCommand = async < + Value extends AnalysisPartialObservation, +>( + run: () => Promise>, + service: { close(): Promise }, + providerId: string, + canonicalOperation: string, + fallbackResource?: string, +): Promise> => { + let result: Result; + try { + result = await run(); + } catch (cause) { + result = { + ok: false, + error: + cause instanceof AnalysisError + ? cause + : new ProviderAdapterError(providerId, canonicalOperation, { cause }), + }; + } + try { + await service.close(); + } catch (cause) { + let cleanup: AnalysisError; + if (cause instanceof AnalysisError) cleanup = cause; + else { + const observation = + cause instanceof ArtifactReaderFailure + ? ArtifactReaderFailure.cleanupObservation( + cause, + fallbackResource ?? `${canonicalOperation} resources`, + ) + : { + reason: cause instanceof Error ? cause.message : String(cause), + resources: [], + }; + cleanup = new ProviderCleanupError( + providerId, + observation.resources, + { reason: observation.reason }, + { cause, operation: canonicalOperation }, + ); + } + if (result.ok) cleanup.retainPartialObservation(result.value); + return projectAnalysisError( + result.ok + ? cleanup + : analysisErrorWithCleanupFailure( + result.error, + cleanup, + canonicalOperation, + ), + ); + } + return result.ok ? result.value : projectAnalysisError(result.error); +}; diff --git a/src/cli/goCommands.ts b/src/cli/goCommands.ts index d67a344e0..12b2b992a 100644 --- a/src/cli/goCommands.ts +++ b/src/cli/goCommands.ts @@ -3,14 +3,13 @@ import { resolve } from "node:path"; import { createGoBinaryService } from "../composition/go.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import { logCliCommand } from "../cliLogging.js"; -import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; import { withCommandCancellation } from "./commandCancellation.js"; +import { finishAnalysisCommand } from "./finishAnalysisCommand.js"; /** Resolve caller paths and inspect static build metadata through the shared workflow. */ export const registerGoCommands = (cli: CliInstance, logger: Logger): void => { - const service = createGoBinaryService(); cli.command(CLI_COMMANDS.inspectGoBinary, { description: "Inspect embedded Go compiler, modules and build settings without target execution", @@ -18,14 +17,19 @@ export const registerGoCommands = (cli: CliInstance, logger: Logger): void => { path: z.string().describe("Local ELF, PE or thin Mach-O image"), }), run: ({ args }) => - withCommandCancellation((signal) => - logCliCommand(logger, CLI_COMMANDS.inspectGoBinary, async () => { - const result = await service.inspect( - { path: resolve(args.path) }, - { signal }, - ); - return result.ok ? result.value : projectAnalysisError(result.error); - }), - ), + withCommandCancellation(async (signal) => { + const service = createGoBinaryService(); + return await logCliCommand( + logger, + CLI_COMMANDS.inspectGoBinary, + async () => + finishAnalysisCommand( + () => service.inspect({ path: resolve(args.path) }, { signal }), + service, + "go-build-info", + "inspect_go_binary", + ), + ); + }), }); }; diff --git a/src/cli/pcapCommands.ts b/src/cli/pcapCommands.ts new file mode 100644 index 000000000..1b53e47cc --- /dev/null +++ b/src/cli/pcapCommands.ts @@ -0,0 +1,69 @@ +import { z } from "incur"; +import { AnalysisError } from "../domain/analysisErrorBase.js"; +import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; +import { PcapAnalysisService } from "../application/pcap/PcapAnalysisService.js"; +import type { PcapAnalysisPort } from "../application/pcap/PcapAnalysisPort.js"; +import { createPcapAnalysisProvider } from "../composition/pcap.js"; +import { CLI_COMMANDS } from "../cliCommandNames.js"; +import { logCliCommand } from "../cliLogging.js"; +import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; +import type { PcapOperation } from "../domain/pcap/pcapAnalysis.js"; +import type { Logger } from "pino"; +import type { CliInstance } from "./types.js"; +import { withCommandCancellation } from "./commandCancellation.js"; + +/** Expose the same explicit pcap requests through one-shot CLI commands. */ +export const registerPcapCommands = ( + cli: CliInstance, + logger: Logger, + environment: Readonly>, + provider: PcapAnalysisPort = createPcapAnalysisProvider(environment), +): void => { + const service = new PcapAnalysisService(provider); + const execute = (name: string, operation: PcapOperation, input: unknown) => + withCommandCancellation((signal) => + logCliCommand(logger, name, async () => { + const result = await service.execute(operation, input, { signal }); + try { + await provider.close(); + } catch (cause) { + if (cause instanceof AnalysisError) { + if (result.ok) cause.retainPartialObservation(result.value); + return projectAnalysisError( + result.ok + ? cause + : analysisErrorWithCleanupFailure( + result.error, + cause, + operation, + ), + ); + } + throw cause; + } + return result.ok ? result.value : projectAnalysisError(result.error); + }), + ); + + cli.command(CLI_COMMANDS.inspectPcapClient, { + description: + "Inspect the caller-selected tshark and capinfos binaries without reading a capture", + args: z.object({}), + run: () => + execute(CLI_COMMANDS.inspectPcapClient, "inspect_pcap_client", {}), + }); + cli.command(CLI_COMMANDS.inspectPcapCapture, { + description: + "Inspect one pcap/pcapng capture: endpoints, DNS, TLS SNI, and protocol distribution", + args: z.object({ + path: z + .string() + .min(1) + .describe("Local pcap or pcapng capture file to inspect"), + }), + run: ({ args }) => + execute(CLI_COMMANDS.inspectPcapCapture, "inspect_pcap_capture", { + path: args.path, + }), + }); +}; diff --git a/src/cli/signalCommands.ts b/src/cli/signalCommands.ts index 02e5555f5..63b7d9edf 100644 --- a/src/cli/signalCommands.ts +++ b/src/cli/signalCommands.ts @@ -1,8 +1,6 @@ +import { inspectSignalDecodersInputSchema } from "../domain/signals/signalDecoders.js"; import { z } from "incur"; import type { SignalRecordingService } from "../application/signals/SignalRecordingService.js"; -import { AnalysisError } from "../domain/analysisErrorBase.js"; -import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; -import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import { resolve } from "node:path"; import { createSignalRecordingService } from "../composition/signals.js"; import { @@ -12,19 +10,62 @@ import { } from "../domain/signals/signalRecording.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import { logCliCommand } from "../cliLogging.js"; -import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; import { withCommandCancellation } from "./commandCancellation.js"; +import { finishAnalysisCommand } from "./finishAnalysisCommand.js"; export const registerSignalCommands = ( cli: CliInstance, logger: Logger, environment: Readonly, service: Pick< SignalRecordingService, - "decode" | "close" + "decode" | "inspectDecoders" | "close" > = createSignalRecordingService(environment), ): void => { + cli.command(CLI_COMMANDS.inspectSignalDecoders, { + description: "Search installed sigrok decoders or selected decoder help", + options: z + .object({ + ...inspectSignalDecodersInputSchema.shape, + limit: z + .number() + .int() + .positive() + .max(Number.MAX_SAFE_INTEGER) + .optional() + .describe( + "Maximum matching decoders or help lines to return; defaults to 50", + ), + all: z + .boolean() + .default(false) + .describe("Return all remaining matches"), + }) + .superRefine((options, context) => { + if (options.all && options.limit !== undefined) + context.addIssue({ + code: "custom", + path: ["all"], + message: "all and limit are mutually exclusive", + }); + }), + run: ({ options: { all, ...options } }) => + withCommandCancellation((signal) => + logCliCommand(logger, CLI_COMMANDS.inspectSignalDecoders, async () => + finishAnalysisCommand( + () => + service.inspectDecoders( + { ...options, ...(all ? { limit: null } : {}) }, + { signal }, + ), + service, + "sigrok-recording", + "inspect_signal_decoders", + ), + ), + ), + }); cli.command(CLI_COMMANDS.decodeSignalRecording, { description: "Decode an existing signal recording with caller-supplied sigrok", @@ -60,39 +101,20 @@ export const registerSignalCommands = ( run: ({ args, options: { all_lines, ...options } }) => withCommandCancellation((signal) => logCliCommand(logger, CLI_COMMANDS.decodeSignalRecording, async () => { - const result = await service.decode( - { - ...options, - ...(all_lines ? { line_limit: null } : {}), - path: resolve(args.path), - }, - { signal }, + return finishAnalysisCommand( + () => + service.decode( + { + ...options, + ...(all_lines ? { line_limit: null } : {}), + path: resolve(args.path), + }, + { signal }, + ), + service, + "sigrok-recording", + "decode_signal_recording", ); - // A one-shot command must retry retained cleanup before discarding its owner. - try { - await service.close(); - } catch (cause) { - const cleanup = - cause instanceof AnalysisError - ? cause - : new ProviderCleanupError( - "sigrok-recording", - [], - { reason: String(cause) }, - { cause, operation: "decode_signal_recording" }, - ); - if (result.ok) cleanup.retainPartialObservation(result.value); - return projectAnalysisError( - result.ok - ? cleanup - : analysisErrorWithCleanupFailure( - result.error, - cleanup, - "decode_signal_recording", - ), - ); - } - return result.ok ? result.value : projectAnalysisError(result.error); }), ), }); diff --git a/src/cli/webNetworkCaptureCommands.ts b/src/cli/webNetworkCaptureCommands.ts index 1b902969c..d49e39b0e 100644 --- a/src/cli/webNetworkCaptureCommands.ts +++ b/src/cli/webNetworkCaptureCommands.ts @@ -1,11 +1,12 @@ import { z } from "incur"; +import { WEB_NETWORK_CAPTURE_FORMATS } from "../domain/webNetworkCapture.js"; import { createWebNetworkCaptureService } from "../composition/webNetworkCaptures.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; import { logCliCommand } from "../cliLogging.js"; -import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; import { withCommandCancellation } from "./commandCancellation.js"; +import { finishAnalysisCommand } from "./finishAnalysisCommand.js"; /** Expose offline historical capture inspection with the same selection contract as MCP. */ export const registerWebNetworkCaptureCommands = ( @@ -16,10 +17,12 @@ export const registerWebNetworkCaptureCommands = ( const service = createWebNetworkCaptureService(environment); cli.command(CLI_COMMANDS.inspectWebNetworkCapture, { description: - "Inspect retained HAR or native mitmproxy records without fetching recorded URLs", + "Inspect retained HAR, native mitmproxy, Fiddler SAZ or aioquic qlog records without fetching recorded URLs", args: z.object({ capturePath: z.string().describe("Absolute local capture path"), - format: z.enum(["har", "mitmproxy"]).describe("Producer capture format"), + format: z + .enum(WEB_NETWORK_CAPTURE_FORMATS) + .describe("Producer capture format"), }), options: z.object({ record: z @@ -39,20 +42,24 @@ export const registerWebNetworkCaptureCommands = ( logger, CLI_COMMANDS.inspectWebNetworkCapture, async () => { - const result = await service.inspect( - { - capture_path: args.capturePath, - format: args.format, - sensitive_values: options.sensitiveValue, - ...(options.record === undefined - ? {} - : { record_ordinals: options.record }), - }, - { signal }, + return finishAnalysisCommand( + () => + service.inspect( + { + capture_path: args.capturePath, + format: args.format, + sensitive_values: options.sensitiveValue, + ...(options.record === undefined + ? {} + : { record_ordinals: options.record }), + }, + { signal }, + ), + service, + "web-network-capture", + "inspect_web_network_capture", + "Web network capture resources", ); - return result.ok - ? result.value - : projectAnalysisError(result.error); }, ), ), diff --git a/src/cliCommandNames.ts b/src/cliCommandNames.ts index 1278cbea8..d63a9a2bc 100644 --- a/src/cliCommandNames.ts +++ b/src/cliCommandNames.ts @@ -1,6 +1,8 @@ /** Canonical names used by every one-shot CLI command registration. */ export const CLI_COMMANDS = Object.freeze({ + inspectPacketFields: "inspect-packet-fields", inspectPacketCapture: "inspect-packet-capture", + inspectSignalDecoders: "inspect-signal-decoders", decodeSignalRecording: "decode-signal-recording", inspectWasmArtifact: "inspect-wasm-artifact", inspectSqliteDatabase: "inspect-sqlite-database", @@ -55,6 +57,8 @@ export const CLI_COMMANDS = Object.freeze({ inspectFirmwareRegions: "inspect-firmware-regions", extractFirmware: "extract-firmware", inspectAndroidPackage: "inspect-android-package", + inspectPcapClient: "inspect-pcap-client", + inspectPcapCapture: "inspect-pcap-capture", identifyFlutterBuild: "identify-flutter-build", inspectDartAot: "inspect-dart-aot", inspectApktoolClient: "inspect-apktool-client", diff --git a/src/composition/javascriptAnalysisWorkerProcess.ts b/src/composition/javascriptAnalysisWorkerProcess.ts index 09a9c9bc3..d1c3c134e 100644 --- a/src/composition/javascriptAnalysisWorkerProcess.ts +++ b/src/composition/javascriptAnalysisWorkerProcess.ts @@ -1,4 +1,4 @@ -import { moduleKindForJavaScriptReference } from "../application/javascript/JavaScriptArtifactPathResolution.js"; +import { moduleResolutionModeForJavaScriptReference } from "../domain/javascript/javascriptModuleResolutionMode.js"; import { parseJavaScriptSource } from "../domain/javascript/javascriptSourceParser.js"; import { analyzeParsedJavaScriptStaticSourceSteps } from "../domain/javascript/javascriptStaticAnalysis.js"; import { @@ -56,7 +56,7 @@ const analyze: JavaScriptSourceWorkerAnalyzer = async ( const ir = await completeJavaScriptAnalysisSteps( analyzeParsedJavaScriptSemanticsSteps( parsed, - moduleKindForJavaScriptReference(file.path, "static-import"), + moduleResolutionModeForJavaScriptReference(file.path, "static-import"), ), ); parsed = null; diff --git a/src/composition/pcap.ts b/src/composition/pcap.ts new file mode 100644 index 000000000..f3aaa3915 --- /dev/null +++ b/src/composition/pcap.ts @@ -0,0 +1,7 @@ +import type { PcapAnalysisPort } from "../application/pcap/PcapAnalysisPort.js"; +import { PcapProvider } from "../pcap/PcapProvider.js"; + +/** Construct one pcap provider bound to the caller-selected tools. */ +export const createPcapAnalysisProvider = ( + environment: Readonly> = process.env, +): PcapAnalysisPort => new PcapProvider({ environment }); diff --git a/src/composition/webNetworkCaptures.ts b/src/composition/webNetworkCaptures.ts index 6dc7668d4..9d9e8c6cc 100644 --- a/src/composition/webNetworkCaptures.ts +++ b/src/composition/webNetworkCaptures.ts @@ -1,6 +1,6 @@ import { WebNetworkCaptureService } from "../application/WebNetworkCaptureService.js"; import { HistoricalCaptureDecoder } from "../browser/history/HistoricalCaptureDecoder.js"; -import { HarCaptureAdapter } from "../browser/history/HarCaptureAdapter.js"; +import { NodeCaptureAdapter } from "../browser/history/NodeCaptureAdapter.js"; import { MitmproxyCaptureAdapter } from "../browser/history/MitmproxyCaptureAdapter.js"; /** Compose offline format adapters without import-time reads, installation or process startup. */ @@ -9,7 +9,12 @@ export const createWebNetworkCaptureService = ( ): WebNetworkCaptureService => new WebNetworkCaptureService( new HistoricalCaptureDecoder( - [new HarCaptureAdapter(), new MitmproxyCaptureAdapter(environment)], + [ + new NodeCaptureAdapter("har"), + new NodeCaptureAdapter("saz"), + new NodeCaptureAdapter("qlog"), + new MitmproxyCaptureAdapter(environment), + ], environment, ), ); diff --git a/src/config.test.ts b/src/config.test.ts index eb784802f..67db7e111 100644 --- a/src/config.test.ts +++ b/src/config.test.ts @@ -3,6 +3,18 @@ import { describe, expect, it } from "vitest"; import { parseConfig } from "./config/parseConfig.js"; import { projectAnalysisError } from "./domain/analysisErrorProjection.js"; +it("reports a configuration failure for a NUL in Hopper loader arguments", () => { + const result = parseConfig({ + HOPPER_LOADER_ARGS_JSON: JSON.stringify(["--option", "value\0suffix"]), + }); + if (result.ok) + throw new Error("NUL argv cannot be passed to a child process"); + expect(result.error).toMatchObject({ + settings: [{ setting: "HOPPER_LOADER_ARGS_JSON" }], + }); + expect(result.error.message).toContain("NUL"); +}); + describe("runtime configuration", () => { it("allows target-free startup and applies runtime defaults", () => { const empty = parseConfig({}); diff --git a/src/config/parsers.ts b/src/config/parsers.ts index fc842f884..52feae622 100644 --- a/src/config/parsers.ts +++ b/src/config/parsers.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { ConfigurationError } from "../domain/configurationErrors.js"; +import { nulFreeStringSchema } from "../domain/localPath.js"; import { err, ok, type Result } from "../domain/result.js"; import { safeParseJson } from "../domain/safeJson.js"; @@ -20,7 +21,8 @@ export const parseLoaderArgs = ( return parseConfiguredStringArray( encoded, "HOPPER_LOADER_ARGS_JSON", - z.string(), + nulFreeStringSchema, + "must encode an array of strings without NUL bytes", ); }; @@ -28,6 +30,7 @@ const parseConfiguredStringArray = ( encoded: string, setting: string, itemSchema: z.ZodString, + requirement = "must encode an array of strings", ): Result => { const decoded = safeParseJson(encoded); if (!decoded.ok) @@ -37,13 +40,7 @@ const parseConfiguredStringArray = ( const parsed = z.array(itemSchema).safeParse(decoded.value); return parsed.success ? ok(parsed.data) - : err( - configuredArrayError( - setting, - "must encode an array of strings", - parsed.error, - ), - ); + : err(configuredArrayError(setting, requirement, parsed.error)); }; const configuredArrayError = ( diff --git a/src/contracts/analysisViewToolContracts.ts b/src/contracts/analysisViewToolContracts.ts index 682c49e6b..7d023752d 100644 --- a/src/contracts/analysisViewToolContracts.ts +++ b/src/contracts/analysisViewToolContracts.ts @@ -9,14 +9,14 @@ import { evidenceResultOf } from "./toolOutputSchemaPrimitives.js"; const RETAINED_EXAMPLE_ID = `ev_${"a".repeat(64)}`; -/** Selected views of completed layout, JavaScript, native, inventory, WASM and web network Evidence. */ +/** Selected views of completed layout, JavaScript, native, inventory, WASM, Mach-O and web network Evidence. */ export const ANALYSIS_VIEW_TOOL_CONTRACTS = [ { name: "inspect_analysis_view", ...toolContractMetadata("inspect_analysis_view"), kind: "application", description: - 'Inspect selected views of completed binary-layout, JavaScript application, native analyze_function, inspect_artifact, inventory_artifact, inspect_wasm_artifact, inspect_evm_interface, inspect_managed_artifact or inspect_web_network_capture Evidence without repeating analysis. The api-surface view groups retained HAR requests by method, origin and format-rule path template; templated segments are inferences. It reads no headers or bodies and reports no query values. For a retained record use source: {kind: "retained-evidence", evidence_id: ""}. Use normalized_result.parent_evidence_id from a summary receipt. Source kind is required. Portable source uses {kind: "inline", evidence: }. For layout, JavaScript, native, inventory, WASM, EVM and managed artifact sources, request a summary with view: {kind: "summary"}; summary is a view kind and has no facet. The WASM summary gives validation, counts, WAT digest/length, tool profile and execution/network states without reading WAT text. Select a layout mitigations/linkage facet, one section/symbol/module, or a stable page. Module pages include assets, bundled and source modules; use node_id for ambiguous or unavailable paths. Inventory uses view: {kind: "inventory", collection: "occurrences", logical_paths: ["package.json"], offset: 0, limit: 64}. Inventory views page nodes, occurrences, edges or integrity contradictions; occurrence logical_paths matches exact recorded strings (omitted means all available, [] means none). source_complete distinguishes complete inventories from partial source records; page exhaustion does not prove absence in a partial source. WASM views use kind wasm and facet sections/imports/exports/candidates/glue/wat/headers/details/tool_profile; text facets use UTF-16 code units and source forms remain exact. EVM summary returns all inferred interface candidates, carrier/decoded identities and explicit unknowns without hex or duplicate stdout. EVM views use kind evm and facet functions/bytecode_hex/stdout/stderr; function pages preserve the original candidate rows, and text offsets/limits count UTF-16 code units (hex has two characters per decoded byte). Exhausting candidate pages does not establish global interface completeness. Managed artifact summaries preserve complete identity/classification, metadata status, module/MVID, frameworks, coverage and limitations without unrelated inventories. Managed pages use kind managed and collection references/resources/attributes, retaining source coverage and build-local token scope; page exhaustion does not establish complete metadata. Native views select procedure, pseudocode, assembly, basic blocks, comments, callers/callees, references, unresolved calls, referenced strings/names, native API and high-pcode. Use nonnegative offset and a positive caller-selected limit (defaults 0 and 64); pseudocode uses UTF-16 code units, other native pages use rows. Returns artifact identity, parent Evidence ID, a distinct view digest, coverage, limitations and unknowns. Actual serialized size determines MCP transport admission; choose a smaller page or export the complete retained Evidence if needed.', + 'Inspect selected views of completed binary-layout, JavaScript application, native analyze_function, inspect_artifact, inventory_artifact, inspect_wasm_artifact, inspect_macho, inspect_evm_interface, inspect_managed_artifact, inspect_android_package, inspect_dart_aot or inspect_web_network_capture Evidence without repeating analysis. Historical capture summaries return identity and counts without bodies or archive inventories. Capture views page retained records: view {kind: "capture", detail: "preview" | "complete", offset: 0, limit: 20}; preview selects recorded headline fields and binary descriptors, complete returns exact records with all sidecars. Offsets follow the selected parent record order, preserving original producer ordinals. Paging never reopens the source or reruns the decoder. For inspect_pcap_capture parents, kind pcap pages endpoints, dns-queries, tls-sni, protocols, http-uris or unattributed-addresses. Select an exact query for dns-addresses, or a tshark/capinfos stream for UTF-16 diagnostics text. Page totals count retained facts; source coverage remains explicit. Qlog summaries keep profile/scope and counts; kind qlog pages traces, streams, loss-declarations, incomplete-records, contributions, ranges or final-sizes. Except traces, select trace_index; stream-specific facets also require exact stream_id and direction. Facts retain all-recorded-events-before-selection scope, and interval overlap or endpoint loss declarations do not prove retransmission or network loss. The api-surface view groups retained HAR requests by method, origin and format-rule path template; templated segments are inferences. It reads no headers or bodies and reports no query values. For a retained record use source: {kind: "retained-evidence", evidence_id: ""}. Use normalized_result.parent_evidence_id from a summary receipt. Source kind is required. Portable source uses {kind: "inline", evidence: }. For layout, JavaScript, inventory, WASM, Mach-O, EVM, managed artifact, Android package and Dart AOT sources, request a summary with view: {kind: "summary"}; summary is a view kind and has no facet. The WASM summary gives validation, counts, WAT digest/length, tool profile and execution/network states without reading WAT text. Select a layout mitigations/linkage facet, one section/symbol/module, or a stable page. Module pages include assets, bundled and source modules; use node_id for ambiguous or unavailable paths. Inventory uses view: {kind: "inventory", collection: "occurrences", logical_paths: ["package.json"], offset: 0, limit: 64}. Inventory views page nodes, occurrences, edges or integrity contradictions; occurrence logical_paths matches exact recorded strings (omitted means all available, [] means none). source_complete distinguishes complete inventories from partial source records; page exhaustion does not prove absence in a partial source. WASM views use kind wasm and facet sections/imports/exports/candidates/glue/wat/headers/details/tool_profile; text facets use UTF-16 code units and source forms remain exact. Mach-O views use kind macho and facet entrypoints/architectures/build_metadata/load_commands/dependencies/imports/exports/segments/provenance; source_exhaustive false means unreturned rows may exist. EVM summary returns all inferred interface candidates, carrier/decoded identities and explicit unknowns without hex or duplicate stdout. EVM views use kind evm and facet functions/bytecode_hex/stdout/stderr; function pages preserve the original candidate rows, and text offsets/limits count UTF-16 code units (hex has two characters per decoded byte). Exhausting candidate pages does not establish global interface completeness. Managed artifact summaries preserve complete identity/classification, metadata status, module/MVID, frameworks, coverage and limitations without unrelated inventories. Managed pages use kind managed and collection references/resources/attributes, retaining source coverage and build-local token scope; page exhaustion does not establish complete metadata. Android package summaries retain all declarations, engine identity and counts without decoded manifest text. Android manifest pages use kind android, facet manifest, offset and limit in UTF-16 code units; source_status preserves partial decoded coverage even when the retained text page is exhausted. Dart AOT summary preserves target/ABI/library identity, snapshot headers and pool lower bounds. String pages use kind dart-aot, collection package_uris/dart_uris/class_like_tokens; source coverage remains partial when the producer says partial. Native function Evidence requires kind native: view: {kind: "native", facet: "procedure"}. Facets select procedure, pseudocode, assembly, basic blocks, comments, callers/callees, references, unresolved calls, referenced strings/names, native API and high-pcode. Use nonnegative offset and a positive caller-selected limit (defaults 0 and 64); pseudocode uses UTF-16 code units, other native pages use rows. Returns artifact identity, parent Evidence ID, a distinct view digest, coverage, limitations and unknowns. Actual serialized size determines MCP transport admission; choose a smaller page or export the complete retained Evidence if needed.', inputSchema: inspectAnalysisViewInputSchema, outputSchema: evidenceResultOf(analysisViewResultSchema), examples: [ diff --git a/src/contracts/android/androidToolContracts.ts b/src/contracts/android/androidToolContracts.ts index df2cccf59..b555fcbea 100644 --- a/src/contracts/android/androidToolContracts.ts +++ b/src/contracts/android/androidToolContracts.ts @@ -1,7 +1,10 @@ +import { z } from "zod"; import { androidInputSchemas, + androidPackageInspectionInputSchema, androidResultSchemas, } from "../../domain/android/androidAnalysis.js"; +import { androidPackageSummaryViewResultSchema } from "../../domain/analysisView/analysisView.js"; import type { ToolContract } from "../toolContractTypes.js"; import { evidenceResultOf } from "../toolOutputSchemaPrimitives.js"; import { toolContractMetadata } from "../toolEffects.js"; @@ -12,14 +15,21 @@ export const ANDROID_TOOL_CONTRACTS = [ name: "inspect_android_package", ...toolContractMetadata("inspect_android_package"), description: - "Inspect a local APK's package, SDK and permission declarations, decoded manifest and class/resource counts. Does not execute the APK or verify signatures. Requires a caller-supplied JADX MCP JAR and JDK; uses one worker in an isolated temporary workspace.", + 'Inspect a local APK\'s package, SDK and permission declarations, decoded manifest and class/resource counts. Omitted or complete detail preserves the complete result. Select detail: "summary" for all declarations, engine identity and counts without decoded manifest text or duplicate raw calls; retains the complete source and returns a distinct linked inspect_analysis_view summary. Read the exact retained manifest with view kind android, facet manifest, offset and limit (UTF-16 code units), using normalized_result.parent_evidence_id. Does not execute the APK or verify signatures. Requires a caller-supplied JADX MCP JAR and JDK; uses one worker in an isolated temporary workspace.', kind: "android-provider", - inputSchema: androidInputSchemas.inspect_android_package, + inputSchema: androidPackageInspectionInputSchema, outputSchema: evidenceResultOf( - androidResultSchemas.inspect_android_package, + z.union([ + androidResultSchemas.inspect_android_package, + androidPackageSummaryViewResultSchema, + ]), ), examples: [ { title: "Inspect an APK", input: { path: "/tmp/Example.apk" } }, + { + title: "Inspect APK declarations with retained manifest", + input: { path: "/tmp/Example.apk", detail: "summary" }, + }, ], }, { diff --git a/src/contracts/applicationToolContracts.ts b/src/contracts/applicationToolContracts.ts index 9a592b536..ade29e960 100644 --- a/src/contracts/applicationToolContracts.ts +++ b/src/contracts/applicationToolContracts.ts @@ -218,7 +218,7 @@ export const APPLICATION_TOOL_CONTRACTS = [ name: "evaluate_reconstruction_coverage", ...toolContractMetadata("evaluate_reconstruction_coverage"), description: - "Evaluate inline evidence-backed reconstruction coverage against one named boundary. Missing ownership or inventory is partial; stale, weak, truncated, skipped, or unresolved proof is unknown; contradictions, failed proof, missing owners, and authority routing fail closed.", + "Evaluate inline evidence-backed reconstruction coverage against one named boundary. Missing ownership or inventory is partial; stale, weak, truncated, skipped, unresolved, or conflicting tied verifier proof is unknown; contradictions, failed proof, missing owners, and authority routing fail closed.", kind: "application", inputSchema: reconstructionCoverageEvaluationInputSchema, outputSchema: reconstructionClosureResultSchema, diff --git a/src/contracts/captures/captureToolContracts.ts b/src/contracts/captures/captureToolContracts.ts index 3e67b3b19..dca211511 100644 --- a/src/contracts/captures/captureToolContracts.ts +++ b/src/contracts/captures/captureToolContracts.ts @@ -1,3 +1,7 @@ +import { + inspectPacketFieldsInputSchema, + packetFieldsCatalogSchema, +} from "../../domain/captures/packetFields.js"; import { inspectPacketCaptureInputSchema, packetCaptureSchema, @@ -6,6 +10,22 @@ import type { ToolContract } from "../toolContractTypes.js"; import { toolContractMetadata } from "../toolEffects.js"; import { evidenceResultOf } from "../toolOutputSchemaPrimitives.js"; export const CAPTURE_TOOL_CONTRACTS = [ + { + name: "inspect_packet_fields", + ...toolContractMetadata("inspect_packet_fields"), + kind: "artifact-provider", + description: + "Discover protocols or field names/types registered in the installed TShark 4.x. kind defaults to protocols; use fields and optional exact protocol abbreviation to select field definitions. query searches name/abbreviation/description by case-insensitive literal substring. Return 50 matches by default with offset/limit paging; null requests all remaining within resource limits. Preserve type/base/bitmask/description, duplicate registrations, source line numbers, coverage, tool identity and diagnostics. Linux, REA_TSHARK_COMMAND and prlimit required. No capture file, interface or binary target needed. Registrations describe tool capabilities, not observed traffic. Each call rereads the glossary; use selected fields with inspect_packet_capture.", + inputSchema: inspectPacketFieldsInputSchema, + outputSchema: evidenceResultOf(packetFieldsCatalogSchema), + examples: [ + { title: "Find USB protocol registrations", input: { query: "usb" } }, + { + title: "Find the installed USB vendor-ID field", + input: { kind: "fields", protocol: "usb", query: "idVendor" }, + }, + ], + }, { name: "inspect_packet_capture", ...toolContractMetadata("inspect_packet_capture"), diff --git a/src/contracts/flutter/flutterToolContracts.ts b/src/contracts/flutter/flutterToolContracts.ts index 9a663d492..9ade1057b 100644 --- a/src/contracts/flutter/flutterToolContracts.ts +++ b/src/contracts/flutter/flutterToolContracts.ts @@ -1,7 +1,10 @@ +import { z } from "zod"; import { flutterInputSchemas, + dartAotInspectionInputSchema, flutterResultSchemas, } from "../../domain/flutter/flutterBuildAnalysis.js"; +import { dartAotSummaryViewResultSchema } from "../../domain/analysisView/analysisView.js"; import type { ToolContract } from "../toolContractTypes.js"; import { evidenceResultOf } from "../toolOutputSchemaPrimitives.js"; import { toolContractMetadata } from "../toolEffects.js"; @@ -27,10 +30,15 @@ export const FLUTTER_TOOL_CONTRACTS = [ name: "inspect_dart_aot", ...toolContractMetadata("inspect_dart_aot"), description: - "Inspect one ABI's Dart AOT snapshot inside an APK: the four snapshot symbols located through the ELF dynamic symbol table with their offsets, sizes, and section headers (magic, kind, length), the snapshot hash, and a bounded string-pool projection from the isolate data section (package: source URIs, dart: SDK URIs, identifier-like tokens) exposing the app's dependency structure. String-pool entries are byte-pattern observations, not deserialized cluster semantics; typed class and function recovery needs an SDK-specific parser. No engine, no execution.", + "Inspect one ABI's Dart AOT snapshot inside an APK: the four snapshot symbols located through the ELF dynamic symbol table with their offsets, sizes, and section headers (magic, kind, length), the snapshot hash, and a bounded string-pool projection from the isolate data section (package: source URIs, dart: SDK URIs, identifier-like tokens) exposing the app's dependency structure. String-pool entries are byte-pattern observations, not deserialized cluster semantics; typed class and function recovery needs an SDK-specific parser. Omitted or complete detail returns the full observation. Select detail: \"summary\" for target/ABI/library identity, all snapshot headers, coverage and original lower-bound counts without string lists. The complete source stays retained; read returned strings via inspect_analysis_view with parent_evidence_id and kind dart-aot, collection package_uris/dart_uris/class_like_tokens, offset and limit. Exhausting pages does not imply complete pool coverage. No engine, no execution.", kind: "flutter-provider", - inputSchema: flutterInputSchemas.inspect_dart_aot, - outputSchema: evidenceResultOf(flutterResultSchemas.inspect_dart_aot), + inputSchema: dartAotInspectionInputSchema, + outputSchema: evidenceResultOf( + z.union([ + flutterResultSchemas.inspect_dart_aot, + dartAotSummaryViewResultSchema, + ]), + ), examples: [ { title: "Inspect the preferred ABI's AOT snapshot", @@ -40,6 +48,10 @@ export const FLUTTER_TOOL_CONTRACTS = [ title: "Inspect one ABI explicitly", input: { path: "/targets/Example.apk", abi: "arm64-v8a" }, }, + { + title: "Inspect snapshot identity with retained string lists", + input: { path: "/targets/Example.apk", detail: "summary" }, + }, ], }, ] as const satisfies readonly ToolContract[]; diff --git a/src/contracts/native/nativeToolContracts.ts b/src/contracts/native/nativeToolContracts.ts index 093add61e..16101368b 100644 --- a/src/contracts/native/nativeToolContracts.ts +++ b/src/contracts/native/nativeToolContracts.ts @@ -11,6 +11,7 @@ import { jsonValueSchema } from "../../domain/jsonValue.js"; import { localPathStringSchema } from "../../domain/localPath.js"; import { toolContractMetadata } from "../toolEffects.js"; import { requireOutputSchema } from "../toolOutputSchemaPrimitives.js"; +import { analysisDetailSchema } from "../analysisDetail.js"; const examples: Readonly>>> = { inspect_macho: {}, @@ -94,8 +95,15 @@ export const NATIVE_TOOL_CONTRACTS = [ ), native( "inspect_macho", - "Inspect Mach-O slices, load commands, imports, exports, dependencies, build metadata, segments, sections, permissions, and exact command provenance without launching Hopper.", - z.object({}), + "Inspect Mach-O slices, load commands, imports, exports, dependencies, build metadata, segments, sections, permissions, and exact command provenance without launching Hopper. Large frameworks return megabytes of symbols; detail summary retains the complete Evidence and returns slice identity with per-collection counts, then page rows with inspect_analysis_view kind macho.", + z.object({ + detail: analysisDetailSchema + .unwrap() + .optional() + .describe( + "Omitted or complete returns the complete inspection Evidence. summary retains that complete Evidence in this session and returns its inspect_analysis_view summary; use normalized_result.parent_evidence_id for macho pages.", + ), + }), ), native( "inspect_signature", diff --git a/src/contracts/officialToolContracts.ts b/src/contracts/officialToolContracts.ts index f9c024fe5..82f1dc83d 100644 --- a/src/contracts/officialToolContracts.ts +++ b/src/contracts/officialToolContracts.ts @@ -181,7 +181,7 @@ export const OFFICIAL_TOOL_CONTRACTS = [ ), official( "procedure_pseudo_code", - "Decompile one analyzed procedure by symbol name or provider-normalized address. Returns provider-specific pseudocode, never original source or cross-provider text equivalence, and may return null; request procedure_assembly when instruction precision matters. Ghidra no-return assumptions may cut the analyzed body; Evidence limitations report observed terminal calls and available callee identities.", + "Decompile one analyzed procedure by symbol name or provider-normalized address. Ghidra also accepts file-offset:0x... selectors and falls back to a unique source-file mapping when a 0x-prefixed number resolves to no procedure; existing analysis addresses take precedence and ambiguous mappings fail explicitly. Returns provider-specific pseudocode, never original source or cross-provider text equivalence, and may return null; request procedure_assembly when instruction precision matters. Ghidra no-return assumptions may cut the analyzed body; Evidence limitations report observed terminal calls and available callee identities.", z.object({ procedure, document }), ), official( diff --git a/src/contracts/pcap/pcapToolContracts.ts b/src/contracts/pcap/pcapToolContracts.ts new file mode 100644 index 000000000..66f281b4e --- /dev/null +++ b/src/contracts/pcap/pcapToolContracts.ts @@ -0,0 +1,46 @@ +import { + pcapInputSchemas, + pcapResultSchemas, +} from "../../domain/pcap/pcapAnalysis.js"; +import type { ToolContract } from "../toolContractTypes.js"; +import { evidenceResultOf } from "../toolOutputSchemaPrimitives.js"; +import { toolContractMetadata } from "../toolEffects.js"; +import { + analysisDetailSchema, + analysisDetailOutputSchemaOf, +} from "../analysisDetail.js"; +import { pcapCaptureSummaryViewResultSchema } from "../../domain/analysisView/analysisView.js"; + +/** Packet-capture analysis served by caller-supplied tshark and capinfos. */ +export const PCAP_TOOL_CONTRACTS = [ + { + name: "inspect_pcap_client", + ...toolContractMetadata("inspect_pcap_client"), + description: + "Inspect the caller-selected tshark and capinfos binaries: selected commands, selection sources, and versions. Both tools must be usable. Reads no capture file. REA never installs the Wireshark suite; select binaries with REA_TSHARK_COMMAND and REA_CAPINFOS_COMMAND (absolute) or from PATH.", + kind: "pcap-provider", + inputSchema: pcapInputSchemas.inspect_pcap_client, + outputSchema: evidenceResultOf(pcapResultSchemas.inspect_pcap_client), + examples: [{ title: "Check the analysis tools", input: {} }], + }, + { + name: "inspect_pcap_capture", + ...toolContractMetadata("inspect_pcap_capture"), + description: + "Request detail summary for capture identity/counts, then page retained facts with inspect_analysis_view kind pcap. Default detail complete preserves inline delivery. Inspect one saved pcap or pcapng capture through an owned snapshot: metadata, exact packet count, SHA-256, IPv4/IPv6 address counts, DNS questions and address values from the same single-question response, TLS SNI, protocol distribution and HTTP URIs. All derived inventories are retained within declared resource budgets; unknown DNS attribution and excluded credentials remain explicit. Linux requires util-linux prlimit; Windows uses owned Job Objects. Requires caller-supplied capinfos and tshark; REA never captures traffic.", + kind: "pcap-provider", + inputSchema: pcapInputSchemas.inspect_pcap_capture.extend({ + detail: analysisDetailSchema, + }), + outputSchema: analysisDetailOutputSchemaOf( + pcapResultSchemas.inspect_pcap_capture, + pcapCaptureSummaryViewResultSchema, + ), + examples: [ + { + title: "Inspect a capture file", + input: { path: "/captures/session.pcap" }, + }, + ], + }, +] as const satisfies readonly ToolContract[]; diff --git a/src/contracts/signals/signalToolContracts.ts b/src/contracts/signals/signalToolContracts.ts index 4a055f12e..f545c452c 100644 --- a/src/contracts/signals/signalToolContracts.ts +++ b/src/contracts/signals/signalToolContracts.ts @@ -1,3 +1,7 @@ +import { + inspectSignalDecodersInputSchema, + signalDecodersSchema, +} from "../../domain/signals/signalDecoders.js"; import { decodeSignalRecordingInputSchema, signalRecordingSchema, @@ -6,6 +10,22 @@ import type { ToolContract } from "../toolContractTypes.js"; import { toolContractMetadata } from "../toolEffects.js"; import { evidenceResultOf } from "../toolOutputSchemaPrimitives.js"; export const SIGNAL_TOOL_CONTRACTS = [ + { + name: "inspect_signal_decoders", + ...toolContractMetadata("inspect_signal_decoders"), + kind: "artifact-provider", + description: + "Discover installed sigrok protocol decoders or inspect one decoder's channel/option help on Linux. Omit decoder to list ID/name pairs; supply its exact ID for literal help lines with source line numbers. query is a case-insensitive literal substring. Page matches with offset/limit (default 50; null returns all remaining). Reports tool identity, version, diagnostics and examined/matching coverage. Uses configured REA_SIGROK_COMMAND and prlimit; no recording, binary target, hardware scan or acquisition. Each call probes again; decoder modules are trusted, not fully fingerprinted. Use returned IDs/options with decode_signal_recording.", + inputSchema: inspectSignalDecodersInputSchema, + outputSchema: evidenceResultOf(signalDecodersSchema), + examples: [ + { title: "Find installed UART decoders", input: { query: "uart" } }, + { + title: "Read the installed UART baud-rate option", + input: { decoder: "uart", query: "baud" }, + }, + ], + }, { name: "decode_signal_recording", ...toolContractMetadata("decode_signal_recording"), diff --git a/src/contracts/toolContractTypes.ts b/src/contracts/toolContractTypes.ts index d7e19d37e..de5f53411 100644 --- a/src/contracts/toolContractTypes.ts +++ b/src/contracts/toolContractTypes.ts @@ -33,6 +33,7 @@ export const TOOL_KINDS = [ "browser-provider", "electron-provider", "runtime-provider", + "pcap-provider", "application", "session", ] as const; diff --git a/src/contracts/toolContracts.ts b/src/contracts/toolContracts.ts index 101cca17e..2fdac1fbe 100644 --- a/src/contracts/toolContracts.ts +++ b/src/contracts/toolContracts.ts @@ -12,6 +12,7 @@ import { MANAGED_TOOL_CONTRACTS } from "./managed/managedToolContracts.js"; import { FIRMWARE_TOOL_CONTRACTS } from "./firmware/firmwareToolContracts.js"; import { ANDROID_TOOL_CONTRACTS } from "./android/androidToolContracts.js"; import { APKTOOL_TOOL_CONTRACTS } from "./apktool/apktoolToolContracts.js"; +import { PCAP_TOOL_CONTRACTS } from "./pcap/pcapToolContracts.js"; import { FLUTTER_TOOL_CONTRACTS } from "./flutter/flutterToolContracts.js"; import { JEB_TOOL_CONTRACTS } from "./jeb/jebToolContracts.js"; import { ADB_TOOL_CONTRACTS } from "./adb/adbToolContracts.js"; @@ -46,6 +47,7 @@ export const TOOL_CONTRACTS = [ ...MANAGED_TOOL_CONTRACTS, ...ANDROID_TOOL_CONTRACTS, ...APKTOOL_TOOL_CONTRACTS, + ...PCAP_TOOL_CONTRACTS, ...FLUTTER_TOOL_CONTRACTS, ...JEB_TOOL_CONTRACTS, ...ADB_TOOL_CONTRACTS, diff --git a/src/contracts/toolEffects.test.ts b/src/contracts/toolEffects.test.ts index 836d190b1..fe18c96b3 100644 --- a/src/contracts/toolEffects.test.ts +++ b/src/contracts/toolEffects.test.ts @@ -44,6 +44,8 @@ const EXECUTION_WORDING_EXCEPTIONS: Readonly> = { search_android_classes: "states it does not execute the APK", inspect_apktool_client: "inspects the operator-selected apktool launcher; never installs it", + inspect_pcap_client: + "probes the operator-selected tshark and capinfos; never installs them", inspect_jeb_client: "talks to a caller-started JEB; never launches it", open_jeb_project: "the engine analyzes the file; REA does not execute it", inspect_adb_client: diff --git a/src/contracts/toolEffects.ts b/src/contracts/toolEffects.ts index 4b0d0b745..70a40c6a1 100644 --- a/src/contracts/toolEffects.ts +++ b/src/contracts/toolEffects.ts @@ -59,11 +59,21 @@ export const TOOL_EFFECTS: Readonly> = { writesFilesystem: true, launchesProcess: true, }), + inspect_packet_fields: effects({ + mutatesSession: true, + launchesProcess: true, + writesFilesystem: true, + }), inspect_packet_capture: effects({ mutatesSession: true, launchesProcess: true, writesFilesystem: true, }), + inspect_signal_decoders: effects({ + mutatesSession: true, + launchesProcess: true, + writesFilesystem: true, + }), decode_signal_recording: effects({ mutatesSession: true, launchesProcess: true, @@ -182,6 +192,16 @@ export const TOOL_EFFECTS: Readonly> = { launchesProcess: true, writesFilesystem: true, }), + inspect_pcap_client: effects({ + mutatesSession: true, + launchesProcess: true, + writesFilesystem: true, + }), + inspect_pcap_capture: effects({ + mutatesSession: true, + launchesProcess: true, + writesFilesystem: true, + }), identify_flutter_build: effects({ mutatesSession: true, writesFilesystem: true, diff --git a/src/contracts/toolOutputSchemaGroups.ts b/src/contracts/toolOutputSchemaGroups.ts index e828486ba..dcf7ad033 100644 --- a/src/contracts/toolOutputSchemaGroups.ts +++ b/src/contracts/toolOutputSchemaGroups.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { artifactInventorySummaryViewResultSchema, + machoSummaryViewResultSchema, managedArtifactSummaryViewResultSchema, } from "../domain/analysisView/analysisView.js"; import { evidenceBundleSummarySchema } from "../domain/evidenceRecordSummary.js"; @@ -356,18 +357,20 @@ export const enhancedOutputSchemas: Readonly> = { binary_overview: evidenceResultOf( z.object({ document: z.string(), + image_base: z.string().min(1).optional(), segments: z.array( z.object({ name: z.string(), start: z.string(), end: z.string(), length: z.number().min(0), + image_base: z.string().exactOptional(), + address_space: z.string().exactOptional(), }), ), segment_count: z.number().int().min(0), procedure_count: z.number().int().min(0), string_count: z.number().int().min(0), - image_base: z.string().min(1).optional(), }), ), analyze_function: functionDossierOutput, @@ -381,7 +384,9 @@ export const nativeOutputSchemas: Readonly> = { observe_native_ui: evidenceResultOf(nativeUiResultSchema), capture_native_ui_scenario: evidenceResultOf(nativeUiResultSchema), observe_native_calls: evidenceResultOf(nativeCallObservationResultSchema), - inspect_macho: evidenceResultOf(inspectMachoSchema), + inspect_macho: evidenceResultOf( + z.union([inspectMachoSchema, machoSummaryViewResultSchema]), + ), inspect_signature: evidenceResultOf(inspectSignatureSchema), inspect_plist: evidenceResultOf(inspectPlistSchema), list_architectures: evidenceResultOf(listArchitecturesSchema), diff --git a/src/contracts/toolOutputSchemaPrimitives.ts b/src/contracts/toolOutputSchemaPrimitives.ts index 20c5517ee..e63a79ff5 100644 --- a/src/contracts/toolOutputSchemaPrimitives.ts +++ b/src/contracts/toolOutputSchemaPrimitives.ts @@ -24,6 +24,7 @@ import { } from "../domain/providerOperationHealth.js"; import { analysisErrorProjectionSchema } from "./errorSchemas.js"; import { relationshipCoverageSchema } from "../domain/relationshipCoverage.js"; +import { ZIP_PACKAGE_FORMATS } from "../domain/zipPackageFormat.js"; /** Specialize the single normalized result inside a complete Evidence record. */ export const evidenceResultOf = (schema: Schema) => @@ -59,11 +60,7 @@ export const targetFormatSchema = z.enum([ "dos-mz", "dos-com", "raw-binary", - "zip", - "ipa", - "apk", - "msix", - "appx", + ...ZIP_PACKAGE_FORMATS, "asar", "dmg", "pkg", diff --git a/src/contracts/webNetworkCaptureToolContracts.ts b/src/contracts/webNetworkCaptureToolContracts.ts index cb919172f..592dd9b54 100644 --- a/src/contracts/webNetworkCaptureToolContracts.ts +++ b/src/contracts/webNetworkCaptureToolContracts.ts @@ -4,7 +4,11 @@ import { } from "../domain/webNetworkCapture.js"; import type { ToolContract } from "./toolContractTypes.js"; import { toolContractMetadata } from "./toolEffects.js"; -import { evidenceResultOf } from "./toolOutputSchemaPrimitives.js"; +import { + analysisDetailSchema, + analysisDetailOutputSchemaOf, +} from "./analysisDetail.js"; +import { webNetworkCaptureSummaryViewResultSchema } from "../domain/analysisView/analysisView.js"; /** Historical inspection is distinct from live browser capture and runtime authority. */ export const WEB_NETWORK_CAPTURE_TOOL_CONTRACTS = [ @@ -12,11 +16,24 @@ export const WEB_NETWORK_CAPTURE_TOOL_CONTRACTS = [ name: "inspect_web_network_capture", ...toolContractMetadata("inspect_web_network_capture"), description: - "Inspect retained local HAR 1.2 or native mitmproxy capture records without contacting recorded URLs. Returns original ordinals, pointers/byte ranges, preserved producer fields, precise numeric representations and exact exposed binary bytes inline. Excludes known transport credentials and explicitly marked values. Decodes every record before optional ordinal selection; malformed or oversized captures return no partial success. Duplicate HAR members are invalid; prototype-named members such as __proto__ are preserved as ordinary own JSON members without prototype mutation. Uses pinned upstream parsers, owned temporary files and bounded offline processes. Native mitmproxy requires caller-supplied mitmdump 12.2.3 on Linux. Browser transaction IDs, runtime attribution and original bytes of HAR Unicode text remain unknown.", + "Request detail summary for capture identity and counts; then page retained records with inspect_analysis_view kind capture (preview or complete), avoiding repeated decoding. Default detail complete preserves existing inline delivery. Inspect retained local HAR 1.2, native mitmproxy, Fiddler SAZ or aioquic 1.5.0 JSON qlog 0.3 events without contacting recorded URLs. Returns original ordinals, pointers/byte ranges/archive member names, preserved producer fields, precise numeric representations and exact exposed binary bytes inline. Excludes known transport credentials and explicitly marked values. Decodes every record before optional ordinal selection; malformed or oversized captures return no partial success. Duplicate JSON members are invalid; prototype-named members such as __proto__ are preserved as ordinary own JSON members without prototype mutation. Qlog reports trace-scoped STREAM interval unions and endpoint loss declarations; it does not recover bodies, prove network loss or correlate PCAP. Other qlog layouts are unsupported. Uses pinned upstream parsers, owned temporary files and bounded offline processes. SAZ preserves HTTP fields, XML metadata and encoded body/message bytes without replay or HAR conversion; encrypted archives are unsupported. Native mitmproxy requires caller-supplied mitmdump 12.2.3 on Linux. Browser transaction IDs, runtime attribution and original bytes of HAR Unicode text remain unknown.", kind: "browser-provider", - inputSchema: inspectWebNetworkCaptureInputSchema, - outputSchema: evidenceResultOf(webNetworkCaptureSchema), + inputSchema: inspectWebNetworkCaptureInputSchema.extend({ + detail: analysisDetailSchema, + }), + outputSchema: analysisDetailOutputSchemaOf( + webNetworkCaptureSchema, + webNetworkCaptureSummaryViewResultSchema, + ), examples: [ + { + title: "Inspect retained aioquic qlog events", + input: { + capture_path: "/captures/origin.qlog", + format: "qlog", + record_ordinals: [0, 2], + }, + }, { title: "Inspect historical HAR entries", input: { diff --git a/src/domain/adb/adbDeviceAnalysis.ts b/src/domain/adb/adbDeviceAnalysis.ts index 17cdc223e..c524ebd02 100644 --- a/src/domain/adb/adbDeviceAnalysis.ts +++ b/src/domain/adb/adbDeviceAnalysis.ts @@ -30,6 +30,25 @@ const packageNameSchema = z "Package name must be dot-separated Java identifiers", ); +/** Text states emitted by adb's ConnectionState formatter. */ +export const ADB_DEVICE_STATES = [ + "no permissions", + "unauthorized", + "authorizing", + "offline", + "recovery", + "sideload", + "connecting", + "bootloader", + "device", + "unknown", + "host", + "rescue", + "detached", +] as const; +export const adbDeviceStateSchema = z.enum(ADB_DEVICE_STATES); +export type AdbDeviceState = (typeof ADB_DEVICE_STATES)[number]; + const keyStringSchema = z.string().min(1).max(256); const keyPattern = /^[A-Za-z0-9._\x2d]+$/u; @@ -412,7 +431,7 @@ const client = z.strictObject({ const device = z.strictObject({ serial: z.string().min(1), - state: z.string().min(1), + state: adbDeviceStateSchema, transport: z.enum(["usb", "tcp", "unknown"]), product: z.string().nullable(), model: z.string().nullable(), diff --git a/src/domain/analysisErrorCore.ts b/src/domain/analysisErrorCore.ts index 9e08f29a3..50db91ccd 100644 --- a/src/domain/analysisErrorCore.ts +++ b/src/domain/analysisErrorCore.ts @@ -100,18 +100,24 @@ export class AnalysisOutputError extends AnalysisError { export class AnalysisCapabilityUnavailableError extends AnalysisError { readonly _tag = "AnalysisCapabilityUnavailableError"; override readonly userMessage: string | undefined; + /** Incomplete cleanup must settle before the operation can be retried. */ + readonly retryable: boolean; constructor( readonly providerId: string, readonly operation: string, readonly reason: string, - options?: AnalysisErrorOptions & { readonly userMessage?: string }, + options?: AnalysisErrorOptions & { + readonly userMessage?: string; + readonly retryable?: boolean; + }, ) { super( `Provider ${providerId} cannot execute ${operation}: ${reason}`, options, ); this.userMessage = options?.userMessage; + this.retryable = options?.retryable === true && !this.cleanupIncomplete; } } diff --git a/src/domain/analysisErrorPresentation.ts b/src/domain/analysisErrorPresentation.ts index 215ed40fc..19c3a9002 100644 --- a/src/domain/analysisErrorPresentation.ts +++ b/src/domain/analysisErrorPresentation.ts @@ -1,6 +1,7 @@ import { AnalysisAccessDeniedError, AnalysisArtifactChangedError, + AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisUnsupportedTargetError, AnalysisResourceConstraintError, @@ -33,6 +34,8 @@ import type { AnalysisErrorProjection } from "./analysisErrorProjection.js"; export const analysisErrorRemediationAction = ( error: AnalysisError, ): string => { + if (error instanceof AnalysisCapabilityUnavailableError && error.retryable) + return "Review details.reason, then retry the same analysis after the condition clears."; if (error instanceof EvidenceFileError && error.published !== undefined) return "Use the published file at details.published_path and resolve the reported staging cleanup failure."; if (error instanceof AnalysisSnapshotMismatchError) @@ -112,6 +115,8 @@ export const analysisErrorRemediationAction = ( export const analysisErrorCategory = ( error: AnalysisError, ): AnalysisErrorProjection["category"] => { + if (error instanceof AnalysisCapabilityUnavailableError && error.retryable) + return "unavailable"; if ( error instanceof BinaryTargetError && error.constraint === "load_selection_rejected" @@ -220,6 +225,8 @@ export const analysisErrorUserMessage = (error: AnalysisError): string => { const hopperMessage = hopperErrorUserMessage(error); if (hopperMessage !== undefined) return hopperMessage; if (error.userMessage !== undefined) return error.userMessage; + if (error instanceof AnalysisCapabilityUnavailableError && error.retryable) + return "Required runtime controls are unavailable for this attempt."; const standardMessage = standardErrorMessage(error._tag); if (standardMessage !== undefined) return standardMessage; if (error instanceof ArtifactOperationError) return artifactMessage(error); diff --git a/src/domain/analysisErrorProjection.test.ts b/src/domain/analysisErrorProjection.test.ts index 467704b98..0766ca6e0 100644 --- a/src/domain/analysisErrorProjection.test.ts +++ b/src/domain/analysisErrorProjection.test.ts @@ -25,6 +25,91 @@ import { ProviderSelectionError } from "./providerSelectionError.js"; import { analysisErrorProjectionSchema } from "../contracts/errorSchemas.js"; import { nativeCallPartialObservationSchema } from "./native/nativeCallPartialObservation.js"; +describe("capability failure retry disposition", () => { + it.each([ + { options: {}, retryable: false, category: "unsupported_provider" }, + { + options: { retryable: false }, + retryable: false, + category: "unsupported_provider", + }, + { options: { retryable: true }, retryable: true, category: "unavailable" }, + ] as const)( + "preserves the producer's $retryable disposition", + ({ options, retryable, category }) => { + const reason = "Native self-test failed with a sharing violation"; + const projected = projectAnalysisError( + new AnalysisCapabilityUnavailableError( + "fixture-provider", + "inspect", + reason, + options, + ), + ); + expect(projected).toMatchObject({ + code: "capability_unavailable", + category, + retryable, + details: { reason }, + }); + if (retryable) { + expect(projected.message).toBe( + "Required runtime controls are unavailable for this attempt.", + ); + expect(projected.remediation.action).toContain( + "retry the same analysis", + ); + } + expect(analysisErrorProjectionSchema.safeParse(projected).success).toBe( + true, + ); + }, + ); + + it("preserves a caller-selected message for a retryable failure", () => { + expect( + projectAnalysisError( + new AnalysisCapabilityUnavailableError( + "fixture-provider", + "inspect", + "temporary failure", + { + retryable: true, + userMessage: "Selected runtime diagnostic", + }, + ), + ).message, + ).toBe("Selected runtime diagnostic"); + }); + + it("retains cleanup ownership before allowing a transient operation to retry", () => { + expect( + projectAnalysisError( + new AnalysisCapabilityUnavailableError( + "fixture-provider", + "inspect", + "temporary failure", + { + retryable: true, + cleanup: { + reason: "owned handle is still live", + resources: ["native-owner"], + }, + }, + ), + ), + ).toMatchObject({ + code: "cleanup_incomplete", + retryable: false, + details: { + cleanup: "incomplete", + resources: ["native-owner"], + execution_failure: "capability_unavailable", + }, + }); + }); +}); + it("projects a published file receipt alongside retained cleanup failure", () => { const projected = projectAnalysisError( new EvidenceFileError("write", "io", { diff --git a/src/domain/analysisErrorProjection.ts b/src/domain/analysisErrorProjection.ts index 723200e18..bfdf7eb42 100644 --- a/src/domain/analysisErrorProjection.ts +++ b/src/domain/analysisErrorProjection.ts @@ -83,6 +83,8 @@ export const projectAnalysisError = ( message: analysisErrorUserMessage(error), retryable: RETRYABLE_CODES.has(code) || + (error instanceof AnalysisCapabilityUnavailableError && + error.retryable) || (code === "resource_constraint" && error instanceof AnalysisResourceConstraintError && error.resource === "capacity"), diff --git a/src/domain/analysisProfile.test.ts b/src/domain/analysisProfile.test.ts index 1fb18f0ae..a39fb389d 100644 --- a/src/domain/analysisProfile.test.ts +++ b/src/domain/analysisProfile.test.ts @@ -65,4 +65,11 @@ describe("analysis profile commitments", () => { analysisProfileSchema.parse({ ...profile, digest: "0".repeat(64) }), ).toThrow(/digest/u); }); + + it("projects known provider identity fields at construction", () => { + const liveProvider = { ...PROVIDER, transient_status: "starting" }; + const profile = createAnalysisProfile(liveProvider, { loader: "default" }); + expect(profile.provider).toEqual(PROVIDER); + expect(analysisProfileSchema.parse(profile)).toEqual(profile); + }); }); diff --git a/src/domain/analysisProfile.ts b/src/domain/analysisProfile.ts index 6719e2ccd..f6e6e0004 100644 --- a/src/domain/analysisProfile.ts +++ b/src/domain/analysisProfile.ts @@ -7,13 +7,13 @@ import { jsonObjectSchema, type JsonValue } from "./jsonValue.js"; import { digestSchema } from "./../domain/digests.js"; /** Concrete provider identity committed by an analysis profile. */ -export const committedProviderSchema = z.object({ +export const committedProviderSchema = z.strictObject({ id: z.string().min(1), name: z.string().min(1), version: z.string().min(1), }); -const unsignedAnalysisProfileSchema = z.object({ +const unsignedAnalysisProfileSchema = z.strictObject({ provider: committedProviderSchema, parameters: jsonObjectSchema, }); @@ -40,7 +40,11 @@ export const createAnalysisProfile = ( parameters: Readonly>, ): AnalysisProfileCommitment => { const unsigned = unsignedAnalysisProfileSchema.parse({ - provider, + provider: { + id: provider.id, + name: provider.name, + version: provider.version, + }, parameters, }); return analysisProfileSchema.parse({ diff --git a/src/domain/analysisView/analysisView.test.ts b/src/domain/analysisView/analysisView.test.ts index 631f9d506..f1aa3e829 100644 --- a/src/domain/analysisView/analysisView.test.ts +++ b/src/domain/analysisView/analysisView.test.ts @@ -1,6 +1,5 @@ import { expect, it } from "vitest"; -import { resolveJavaScriptSourceMapReference } from "../javascript/javascriptSourceMapPaths.js"; import { functionDossierSchema } from "../hopperValues.js"; import { ghidraFunctionDossier } from "../ghidraValues.fixture.js"; import { JAVASCRIPT_APPLICATION_EVIDENCE_EXAMPLE } from "../../contracts/javascript/javascriptRuntimeReconciliationExample.js"; @@ -24,13 +23,14 @@ import { completeWithinViewCoverage, pageViewCoverage, } from "./analysisViewCoverage.js"; +import { sourceMapReference } from "../javascript/javascriptApplicationGraph.fixture.js"; import { javascriptModulePath } from "./javascriptApplicationView.js"; - import { inspectAnalysisViewInputSchema, projectAnalysisView, type AnalysisViewParent, } from "./analysisView.js"; + const layoutParent = (): AnalysisViewParent => { const evidence = analysisViewLayoutEvidence(); return { @@ -532,7 +532,7 @@ it("pages actual modules, including unknown and empty paths, without unrelated r observations: original.observations.map((observation) => ({ ...(kind === "source-module" ? { - source_map_reference: resolveJavaScriptSourceMapReference( + source_map_reference: sourceMapReference( "", null, "renderer.js", diff --git a/src/domain/analysisView/analysisView.ts b/src/domain/analysisView/analysisView.ts index 4ab9c77da..7f985f349 100644 --- a/src/domain/analysisView/analysisView.ts +++ b/src/domain/analysisView/analysisView.ts @@ -55,7 +55,43 @@ import { wasmViewItemSchema, wasmSummarySchema, } from "./wasmArtifactView.js"; +import { + machoSummarySchema, + machoViewContextSchema, + machoViewItemSchema, + machoViewRequestSchema, + projectMachoView, +} from "./machoView.js"; +import { + projectWebNetworkCaptureView, + captureViewRequestSchema, + captureViewItemsSchema, + captureSummarySchema, +} from "./webNetworkCaptureView.js"; import type { WebNetworkApiSurfaceAccumulator } from "./WebNetworkApiSurfaceAccumulator.js"; +import { + pcapViewRequestSchema, + pcapViewPageSchema, + pcapSummarySchema, + projectPcapCaptureView, +} from "./pcapCaptureView.js"; +import { + qlogViewRequestSchema, + qlogViewPageSchema, + qlogViewContextSchema, +} from "./qlogCaptureView.js"; +import { + projectAndroidPackageView, + androidPackageSummarySchema, + androidViewRequestSchema, + androidManifestViewItemSchema, +} from "./androidPackageView.js"; +import { + projectDartAotView, + dartAotSummarySchema, + dartAotViewRequestSchema, + dartAotViewContextSchema, +} from "./dartAotView.js"; /** Public name of the selected-view workflow. */ export const INSPECT_ANALYSIS_VIEW_OPERATION = "inspect_analysis_view" as const; @@ -167,9 +203,15 @@ export const analysisViewRequestSchema = z.discriminatedUnion("kind", [ nativeViewSchema, inventoryViewSchema, wasmViewRequestSchema, + machoViewRequestSchema, evmViewRequestSchema, managedViewRequestSchema, + androidViewRequestSchema, apiSurfaceViewSchema, + captureViewRequestSchema, + qlogViewRequestSchema, + pcapViewRequestSchema, + dartAotViewRequestSchema, ]); // The application owns admission and authenticated Evidence parsing. SDK and @@ -209,7 +251,7 @@ const artifactSchema = z.strictObject({ path: z .string() .describe("Exact recorded artifact path, including an empty string."), - sha256: digestSchema, + sha256: digestSchema.nullable(), }); const layoutSummarySchema = z.strictObject({ @@ -281,8 +323,13 @@ const viewResultBase = { "inspect_artifact", "inventory_artifact", "inspect_wasm_artifact", + "inspect_macho", "inspect_evm_interface", "inspect_managed_artifact", + "inspect_web_network_capture", + "inspect_android_package", + "inspect_pcap_capture", + "inspect_dart_aot", ]), parent_digest: digestSchema, view_digest: digestSchema, @@ -326,6 +373,13 @@ export const wasmArtifactSummaryViewResultSchema = z.strictObject({ summary: wasmSummarySchema, }); +/** Exact slice identity and collection counts for Mach-O's selected delivery. */ +export const machoSummaryViewResultSchema = z.strictObject({ + ...summaryViewResultBase, + parent_operation: z.literal("inspect_macho"), + summary: machoSummarySchema, +}); + /** Exact inferred-interface summary for EVM's caller-selected delivery. */ export const evmInterfaceSummaryViewResultSchema = z.strictObject({ ...summaryViewResultBase, @@ -340,6 +394,33 @@ export const managedArtifactSummaryViewResultSchema = z.strictObject({ summary: managedSummarySchema, }); +/** Exact historical capture summary, with no body or member-inventory payload. */ +export const webNetworkCaptureSummaryViewResultSchema = z.strictObject({ + ...summaryViewResultBase, + parent_operation: z.literal("inspect_web_network_capture"), + summary: captureSummarySchema, +}); + +/** Exact package declarations with retained decoded manifest text. */ +export const androidPackageSummaryViewResultSchema = z.strictObject({ + ...summaryViewResultBase, + parent_operation: z.literal("inspect_android_package"), + summary: androidPackageSummarySchema, +}); + +export const pcapCaptureSummaryViewResultSchema = z.strictObject({ + ...summaryViewResultBase, + parent_operation: z.literal("inspect_pcap_capture"), + summary: pcapSummarySchema, +}); + +/** Exact snapshot and pool-coverage carrier for selected AOT delivery. */ +export const dartAotSummaryViewResultSchema = z.strictObject({ + ...summaryViewResultBase, + parent_operation: z.literal("inspect_dart_aot"), + summary: dartAotSummarySchema, +}); + /** Projected facts for one selected view of retained analysis Evidence. */ export const analysisViewResultSchema = z.discriminatedUnion("kind", [ z.strictObject({ @@ -360,10 +441,38 @@ export const analysisViewResultSchema = z.discriminatedUnion("kind", [ javascriptSummarySchema, inventorySummarySchema, wasmSummarySchema, + machoSummarySchema, evmSummarySchema, managedSummarySchema, + captureSummarySchema, + androidPackageSummarySchema, + pcapSummarySchema, + dartAotSummarySchema, ]), }), + z.strictObject({ + kind: z.literal("capture"), + view: captureViewRequestSchema, + items: captureViewItemsSchema, + ...viewResultBase, + parent_operation: z.literal("inspect_web_network_capture"), + }), + z.strictObject({ + kind: z.literal("qlog"), + view: qlogViewRequestSchema, + page: qlogViewPageSchema, + context: qlogViewContextSchema, + ...viewResultBase, + parent_operation: z.literal("inspect_web_network_capture"), + }), + z.strictObject({ + kind: z.literal("pcap"), + view: pcapViewRequestSchema, + page: pcapViewPageSchema, + source_coverage: z.enum(["complete", "partial"]), + ...viewResultBase, + parent_operation: z.literal("inspect_pcap_capture"), + }), z.strictObject({ kind: z.literal("facet"), view: facetViewSchema, @@ -395,6 +504,14 @@ export const analysisViewResultSchema = z.discriminatedUnion("kind", [ item: wasmViewItemSchema, ...viewResultBase, }), + z.strictObject({ + kind: z.literal("macho"), + view: machoViewRequestSchema, + item: machoViewItemSchema, + ...viewResultBase, + ...machoViewContextSchema.shape, + parent_operation: z.literal("inspect_macho"), + }), z.strictObject({ kind: z.literal("evm"), view: evmViewRequestSchema, @@ -410,6 +527,21 @@ export const analysisViewResultSchema = z.discriminatedUnion("kind", [ ...managedViewContextSchema.shape, parent_operation: z.literal("inspect_managed_artifact"), }), + z.strictObject({ + kind: z.literal("android"), + view: androidViewRequestSchema, + item: androidManifestViewItemSchema, + ...viewResultBase, + parent_operation: z.literal("inspect_android_package"), + }), + z.strictObject({ + kind: z.literal("dart-aot"), + view: dartAotViewRequestSchema, + items: z.array(z.string()), + ...viewResultBase, + ...dartAotViewContextSchema.shape, + parent_operation: z.literal("inspect_dart_aot"), + }), z.strictObject({ kind: z.literal("inventory"), view: inventoryViewSchema, @@ -476,10 +608,25 @@ export type UnsignedAnalysisView = "view_digest" > | Omit, "view_digest"> + | Omit, "view_digest"> | Omit, "view_digest"> + | Omit, "view_digest"> + | Omit, "view_digest"> + | Omit< + Extract, + "view_digest" + > | Omit< Extract, "view_digest" + > + | Omit< + Extract, + "view_digest" + > + | Omit< + Extract, + "view_digest" >; /** Attach the content digest that must change when projected bytes change. */ @@ -525,7 +672,7 @@ const unsupportedParent = ( new AnalysisUnsupportedTargetError( INSPECT_ANALYSIS_VIEW_OPERATION, parentArtifactPath(parent), - `Parent Evidence operation ${JSON.stringify(parent.operation)} does not support analysis views. Use completed binary layout, JavaScript application, native function, artifact inventory/inspection, WASM, EVM, managed artifact, or web network capture Evidence.`, + `Parent Evidence operation ${JSON.stringify(parent.operation)} does not support analysis views. Use completed binary layout, JavaScript application, native function, artifact inventory/inspection, WASM, Mach-O, EVM, managed artifact, Android package, Dart AOT, or web network capture Evidence.`, ); const parentArtifactPath = (parent: AnalysisViewParent): string => { @@ -552,8 +699,11 @@ const parentArtifactPath = (parent: AnalysisViewParent): string => { /** Named source owners for views that need no extra decoder or accumulator. */ const retainedViewProjectors = new Map([ ["inspect_wasm_artifact", projectWasmArtifactView], + ["inspect_macho", projectMachoView], ["inspect_evm_interface", projectEvmInterfaceView], ["inspect_managed_artifact", projectManagedArtifactView], + ["inspect_android_package", projectAndroidPackageView], + ["inspect_dart_aot", projectDartAotView], ["inspect_artifact", projectArtifactInventoryView], ["inventory_artifact", projectArtifactInventoryView], ]); @@ -575,10 +725,7 @@ export const projectAnalysisView = ( }, ]), ); - if ( - view.kind === "api-surface" || - parent.operation === "inspect_web_network_capture" - ) { + if (view.kind === "api-surface") { const projected = projectWebNetworkApiSurfaceView( parent, view, @@ -586,6 +733,14 @@ export const projectAnalysisView = ( ); return projected.ok ? ok(sealAnalysisView(projected.value)) : projected; } + if (parent.operation === "inspect_web_network_capture") { + const projected = projectWebNetworkCaptureView(parent, view); + return projected.ok ? ok(sealAnalysisView(projected.value)) : projected; + } + if (parent.operation === "inspect_pcap_capture") { + const projected = projectPcapCaptureView(parent, view); + return projected.ok ? ok(sealAnalysisView(projected.value)) : projected; + } if (parent.operation === "inspect_binary_layout") { const layout = binaryLayoutSchema.safeParse(parent.normalizedResult); if (!layout.success) diff --git a/src/domain/analysisView/androidPackageView.ts b/src/domain/analysisView/androidPackageView.ts new file mode 100644 index 000000000..caf948c10 --- /dev/null +++ b/src/domain/analysisView/androidPackageView.ts @@ -0,0 +1,136 @@ +import { z } from "zod"; +import type { AnalysisError } from "../analysisErrorBase.js"; +import { androidResultSchemas } from "../android/androidAnalysis.js"; +import { analysisInputErrorFromIssues } from "../inputIssueProjection.js"; +import { err, ok, type Result } from "../result.js"; +import { + analysisViewInputError, + type AnalysisViewParent, + type AnalysisViewRequest, + type UnsignedAnalysisView, +} from "./analysisView.js"; +import { completeWithinViewCoverage } from "./analysisViewCoverage.js"; +import { analysisTextPage } from "./analysisViewText.js"; + +const packageSchema = androidResultSchemas.inspect_android_package; + +/** All package declarations remain inline; decoded manifest text stays retained. */ +export const androidPackageSummarySchema = packageSchema.extend({ + manifest: packageSchema.shape.manifest.omit({ text: true }).extend({ + text_code_units: z.number().int().nonnegative(), + text_included: z.literal(false), + }), +}); + +/** Exact decoded text; offsets and limits count UTF-16 code units. */ +export const androidViewRequestSchema = z.strictObject({ + kind: z.literal("android"), + facet: z.literal("manifest"), + offset: z.number().int().nonnegative().default(0), + limit: z.number().int().positive(), +}); + +export const androidManifestViewItemSchema = z.strictObject({ + text: z.string(), + unit: z.literal("utf16-code-units"), + source_status: packageSchema.shape.manifest.shape.status, + reported_total_bytes: packageSchema.shape.manifest.shape.reported_total_bytes, +}); + +/** Project an authenticated package record without reopening the APK or engine. */ +export const projectAndroidPackageView = ( + parent: AnalysisViewParent, + view: AnalysisViewRequest, +): Result => { + if (view.kind !== "summary" && view.kind !== "android") + return err( + analysisViewInputError([ + { + path: ["view"], + reason: "invalid_value", + message: + "Android package Evidence supports summary and manifest views.", + }, + ]), + ); + const parsed = packageSchema.safeParse(parent.normalizedResult); + if (!parsed.success) + return err( + analysisInputErrorFromIssues( + "inspect_analysis_view", + parsed.error.issues.map((issue) => ({ + ...issue, + path: ["source", "normalized_result", ...issue.path], + })), + { source: { normalized_result: parent.normalizedResult } }, + { cause: parsed.error }, + ), + ); + // Engine artifact_sha256 identifies the JAR, never the APK. A missing + // authenticated APK subject cannot be repaired using the engine identity. + if (parent.subject == null) + return err( + analysisViewInputError([ + { + path: ["source", "subject"], + reason: "invalid_value", + message: + "Android package views require the recorded APK subject identity.", + }, + ]), + ); + const report = parsed.data; + const shared = { + parent_evidence_id: parent.evidenceId, + parent_operation: "inspect_android_package" as const, + parent_digest: parent.evidenceId.slice(3), + artifact: { + path: parent.subject.local_path, + sha256: parent.subject.digest.sha256, + }, + limitations: [...parent.limitations], + unknowns: [ + "APK signatures were not verified; package declarations do not establish authenticity or runtime behavior.", + ...(report.manifest.status === "partial" + ? [ + "The decoded manifest is partial; exhausting retained text does not establish complete manifest coverage.", + ] + : []), + ], + }; + if (view.kind === "summary") { + const { text, ...manifest } = report.manifest; + return ok({ + kind: "summary", + view, + ...shared, + summary: { + ...report, + manifest: { + ...manifest, + text_code_units: text.length, + text_included: false, + }, + }, + coverage: completeWithinViewCoverage(1, 1), + }); + } + const page = analysisTextPage( + report.manifest.text, + view.offset, + view.limit, + "Manifest", + ); + if (!page.ok) return page; + return ok({ + kind: "android", + view, + ...shared, + item: { + ...page.value.item, + source_status: report.manifest.status, + reported_total_bytes: report.manifest.reported_total_bytes, + }, + coverage: page.value.coverage, + }); +}; diff --git a/src/domain/analysisView/dartAotView.ts b/src/domain/analysisView/dartAotView.ts new file mode 100644 index 000000000..4d66aa190 --- /dev/null +++ b/src/domain/analysisView/dartAotView.ts @@ -0,0 +1,123 @@ +import { z } from "zod"; +import type { AnalysisError } from "../analysisErrorBase.js"; +import { flutterResultSchemas } from "../flutter/flutterBuildAnalysis.js"; +import { analysisInputErrorFromIssues } from "../inputIssueProjection.js"; +import { err, ok, type Result } from "../result.js"; +import { + analysisViewInputError, + type AnalysisViewParent, + type AnalysisViewRequest, + type UnsignedAnalysisView, +} from "./analysisView.js"; +import { + completeWithinViewCoverage, + pageViewCoverage, +} from "./analysisViewCoverage.js"; + +const aotSchema = flutterResultSchemas.inspect_dart_aot; + +/** Snapshot identity and original coverage, without unrelated string inventories. */ +export const dartAotSummarySchema = aotSchema.extend({ + string_pool: aotSchema.shape.string_pool + .omit({ package_uris: true, dart_uris: true, class_like_tokens: true }) + .extend({ + returned_counts: z.strictObject({ + package_uris: z.number().int().nonnegative(), + dart_uris: z.number().int().nonnegative(), + class_like_tokens: z.number().int().nonnegative(), + }), + }), +}); + +/** Pages of the producer-returned strings, preserving original order and scope. */ +export const dartAotViewRequestSchema = z.strictObject({ + kind: z.literal("dart-aot"), + collection: z.enum(["package_uris", "dart_uris", "class_like_tokens"]), + offset: z.number().int().nonnegative().default(0), + limit: z.number().int().positive().default(64), +}); + +export const dartAotViewContextSchema = z.strictObject({ + abi: aotSchema.shape.abi, + libapp: aotSchema.shape.libapp, + source_coverage: aotSchema.shape.coverage, + string_pool: dartAotSummarySchema.shape.string_pool, +}); + +/** Reuse authenticated AOT Evidence without opening the APK or rescanning its ELF. */ +export const projectDartAotView = ( + parent: AnalysisViewParent, + view: AnalysisViewRequest, +): Result => { + if (view.kind !== "summary" && view.kind !== "dart-aot") + return err( + analysisViewInputError([ + { + path: ["view"], + reason: "invalid_value", + message: "Dart AOT Evidence supports summary and string-pool pages.", + }, + ]), + ); + const parsed = aotSchema.safeParse(parent.normalizedResult); + if (!parsed.success) + return err( + analysisInputErrorFromIssues( + "inspect_analysis_view", + parsed.error.issues.map((issue) => ({ + ...issue, + path: ["source", "normalized_result", ...issue.path], + })), + { source: { normalized_result: parent.normalizedResult } }, + { cause: parsed.error }, + ), + ); + const report = parsed.data; + const { package_uris, dart_uris, class_like_tokens, ...pool } = + report.string_pool; + const string_pool = { + ...pool, + returned_counts: { + package_uris: package_uris.length, + dart_uris: dart_uris.length, + class_like_tokens: class_like_tokens.length, + }, + }; + const shared = { + parent_evidence_id: parent.evidenceId, + parent_operation: "inspect_dart_aot" as const, + parent_digest: parent.evidenceId.slice(3), + artifact: { path: report.target.path, sha256: report.target.sha256 }, + limitations: [...parent.limitations], + unknowns: [ + "String-pool entries are byte-pattern observations, not recovered typed classes or functions.", + "Counts ending in _at_least remain lower bounds; exhausting returned strings does not establish a complete snapshot inventory.", + ...(parent.subject == null + ? [ + "The parent has no recorded subject; its normalized target identity cannot be cross-checked against a subject digest.", + ] + : []), + ], + }; + if (view.kind === "summary") + return ok({ + kind: "summary", + view, + ...shared, + summary: { ...report, string_pool }, + coverage: completeWithinViewCoverage(1, 1), + }); + const collection = report.string_pool[view.collection]; + const items = collection.slice(view.offset, view.offset + view.limit); + return ok({ + kind: "dart-aot", + view, + ...shared, + items, + abi: report.abi, + libapp: report.libapp, + source_coverage: report.coverage, + string_pool, + coverage: pageViewCoverage(view.offset, items.length, collection.length), + }); +}; diff --git a/src/domain/analysisView/evmInterfaceView.ts b/src/domain/analysisView/evmInterfaceView.ts index a7b343291..d9f3994d4 100644 --- a/src/domain/analysisView/evmInterfaceView.ts +++ b/src/domain/analysisView/evmInterfaceView.ts @@ -76,6 +76,7 @@ export const projectEvmInterfaceView = ( const report = parsed.data; if ( parent.subject == null || + parent.subject.format !== "file" || parent.subject.local_path !== report.artifact.path || parent.subject.digest.sha256 !== report.artifact.sha256 ) diff --git a/src/domain/analysisView/javascriptApplicationView.ts b/src/domain/analysisView/javascriptApplicationView.ts index 5e5f9bb88..41a22f8d9 100644 --- a/src/domain/analysisView/javascriptApplicationView.ts +++ b/src/domain/analysisView/javascriptApplicationView.ts @@ -241,22 +241,14 @@ export const projectJavaScriptApplicationView = ( analysis: JavaScriptApplicationAnalysisResult, view: Exclude, ): Result => { + if (view.kind !== "summary" && view.kind !== "item" && view.kind !== "page") + return err( + jsIncompatible( + "JavaScript application Evidence supports summary, module item or module page views.", + ), + ); const shared = parentFields(parent, analysis); const modules = moduleEntries(analysis.graph.nodes); - if (view.kind === "native") - return err( - jsIncompatible("Native views require analyze_function Evidence."), - ); - if (view.kind === "inventory") - return err(jsIncompatible("Inventory views require artifact Evidence.")); - if (view.kind === "wasm") - return err( - jsIncompatible("WASM views require inspect_wasm_artifact Evidence."), - ); - if (view.kind === "evm") - return err( - jsIncompatible("EVM views require inspect_evm_interface Evidence."), - ); if (view.kind === "summary") return ok({ kind: "summary", @@ -291,12 +283,6 @@ export const projectJavaScriptApplicationView = ( coverage: completeCoverage(modules.length, analysis.graph.nodes.length), ...shared, }); - if (view.kind === "facet") - return err( - jsIncompatible( - "facet views apply to inspect_binary_layout Evidence (mitigations or linkage).", - ), - ); if (view.kind === "item") { if (view.collection !== "modules") return err( @@ -314,7 +300,7 @@ export const projectJavaScriptApplicationView = ( ...shared, }); } - if (view.collection !== "modules") + if (view.kind !== "page" || view.collection !== "modules") return err( jsIncompatible( "Section and symbol collections apply to inspect_binary_layout Evidence.", diff --git a/src/domain/analysisView/machoView.test.ts b/src/domain/analysisView/machoView.test.ts new file mode 100644 index 000000000..2018438be --- /dev/null +++ b/src/domain/analysisView/machoView.test.ts @@ -0,0 +1,246 @@ +import { describe, expect, it } from "vitest"; + +import { + projectAnalysisView, + type AnalysisViewParent, +} from "./analysisView.js"; + +const symbol = (name: string) => ({ + name, + address: null, + weak: null, + reexport: null, + source: "libSystem", +}); +const coverage = (items: T[], exhaustive = true) => ({ + items, + total: exhaustive ? items.length : null, + exhaustive, + limitations: exhaustive ? [] : ["nm output may omit stripped symbols."], +}); +const report = { + format: "mach-o", + selected_architecture: { name: "arm64", container_file_offset: 0 }, + endian: null, + word_size: 64, + file_type: "2", + flags: ["0x00200085"], + uuid: "4C4C44E9-5555-3144-A1E9-D858E24A1CCE", + entrypoints: coverage([{ file_offset: 16384 }]), + architectures: coverage([ + { + name: "arm64", + cpu_type: "16777228", + cpu_subtype: "0", + file_offset: 0, + size: 4096, + alignment: 14, + }, + ]), + build_metadata: coverage([ + { platform: "1", minimum_os: "14.0", sdk: "15.0", tools: [] }, + ]), + load_commands: coverage([{ index: 0, kind: "LC_MAIN", fields: {} }]), + dependencies: coverage([ + { + path: "/usr/lib/libSystem.B.dylib", + kind: "LC_LOAD_DYLIB", + current_version: "1351.0.0", + compatibility_version: "1.0.0", + }, + ]), + imports: coverage( + ["_malloc", "_free", "_open"].map((name) => symbol(name)), + false, + ), + exports: coverage([symbol("__mh_execute_header")]), + segments: coverage([ + { + name: "__TEXT", + vm_address: "0x100000000", + vm_size: 16384, + file_offset: 0, + file_size: 16384, + maximum_permissions: { + read: true, + write: false, + execute: true, + raw: "5", + }, + initial_permissions: { + read: true, + write: false, + execute: true, + raw: "5", + }, + sections: coverage([]), + }, + ]), + provenance: [ + { + tool: "nm", + command: ["/usr/bin/nm", "$ARTIFACT"], + tool_version: null, + version_reason: "fixture", + executable_sha256: "a".repeat(64), + exit: { code: 0, signal: null }, + stdout_bytes: 10, + stderr_bytes: 0, + }, + ], + limitations: ["Imports and exports combine dyld_info and nm."], +}; +const parent = ( + normalizedResult: unknown = report, + subject: AnalysisViewParent["subject"] = { + name: "tool", + digest: { sha256: "b".repeat(64) }, + format: "mach-o", + architecture: "arm64", + local_path: "/bin/tool", + }, +): AnalysisViewParent => ({ + evidenceId: `ev_${"c".repeat(64)}`, + operation: "inspect_macho", + normalizedResult, + subject, + limitations: ["Parent limitation."], +}); + +describe("Mach-O analysis views", () => { + it("summarizes slice identity and collection counts without rows", () => { + const projected = projectAnalysisView(parent(), { kind: "summary" }); + if (!projected.ok) throw projected.error; + expect(projected.value).toMatchObject({ + kind: "summary", + parent_operation: "inspect_macho", + artifact: { path: "/bin/tool", sha256: "b".repeat(64) }, + summary: { + selected_architecture: { name: "arm64", container_file_offset: 0 }, + uuid: report.uuid, + collections: { + imports: { returned: 3, total: null, exhaustive: false }, + exports: { returned: 1, total: 1, exhaustive: true }, + segments: { returned: 1, total: 1, exhaustive: true }, + }, + provenance_count: 1, + limitation_count: 3, + }, + coverage: { status: "complete-within-view", examined: 10, total: 10 }, + limitations: [ + "Imports and exports combine dyld_info and nm.", + "Parent limitation.", + "nm output may omit stripped symbols.", + ], + unknowns: [expect.stringContaining("exhaustive imports;")], + }); + expect(JSON.stringify(projected.value)).not.toContain("_malloc"); + }); + + it("pages original rows with the producer's own coverage", () => { + const first = projectAnalysisView(parent(), { + kind: "macho", + facet: "imports", + offset: 1, + limit: 1, + }); + if (!first.ok) throw first.error; + expect(first.value).toMatchObject({ + kind: "macho", + item: [symbol("_free")], + source_total: null, + source_exhaustive: false, + coverage: { status: "page", examined: 1, total: 3, next_offset: 2 }, + }); + expect(first.value.limitations).toContain( + "nm output may omit stripped symbols.", + ); + // Rows whose keys include an earlier row shape's keys stay whole. + for (const facet of ["architectures", "segments"] as const) { + const page = projectAnalysisView(parent(), { + kind: "macho", + facet, + offset: 0, + limit: 64, + }); + if (!page.ok) throw page.error; + expect(page.value.kind === "macho" && page.value.item).toEqual( + report[facet].items, + ); + } + const provenance = projectAnalysisView(parent(), { + kind: "macho", + facet: "provenance", + offset: 0, + limit: 64, + }); + if (!provenance.ok) throw provenance.error; + expect(provenance.value).toMatchObject({ + item: report.provenance, + source_total: 1, + source_exhaustive: true, + coverage: { exhausted: true, next_offset: null }, + }); + const past = projectAnalysisView(parent(), { + kind: "macho", + facet: "exports", + offset: 5, + limit: 64, + }); + if (!past.ok) throw past.error; + expect(past.value.coverage).toMatchObject({ + status: "empty", + exhausted: true, + }); + }); + + it("keeps a missing subject unknown instead of inventing identity", () => { + const projected = projectAnalysisView(parent(report, null), { + kind: "summary", + }); + if (!projected.ok) throw projected.error; + expect(projected.value.artifact).toEqual({ path: "", sha256: null }); + expect(projected.value.unknowns).toContain( + "The parent has no recorded subject, so the inspected artifact path and SHA-256 are unknown.", + ); + }); + + it("rejects other view kinds and malformed retained results", () => { + const wrongKind = projectAnalysisView(parent(), { + kind: "wasm", + facet: "exports", + offset: 0, + limit: 64, + }); + if (wrongKind.ok) throw new Error("expected a view-kind refusal"); + expect(wrongKind.error).toMatchObject({ + _tag: "AnalysisInputError", + issues: [ + { + path: ["view"], + message: "Mach-O inspection supports summary and macho views.", + }, + ], + }); + const contradictory = projectAnalysisView( + parent(report, { + name: "tool", + digest: { sha256: "b".repeat(64) }, + format: "elf", + architecture: null, + local_path: "/bin/tool", + }), + { kind: "summary" }, + ); + if (contradictory.ok) throw new Error("expected a subject refusal"); + expect(contradictory.error).toMatchObject({ + issues: [{ path: ["source", "subject"] }], + }); + const malformed = projectAnalysisView( + parent({ ...report, imports: { items: "x" } }), + { kind: "summary" }, + ); + expect(malformed.ok).toBe(false); + if (!malformed.ok) expect(malformed.error._tag).toBe("AnalysisInputError"); + }); +}); diff --git a/src/domain/analysisView/machoView.ts b/src/domain/analysisView/machoView.ts new file mode 100644 index 000000000..1a64d23aa --- /dev/null +++ b/src/domain/analysisView/machoView.ts @@ -0,0 +1,247 @@ +import { z } from "zod"; +import type { AnalysisError } from "../analysisErrorBase.js"; +import { uniqueSorted } from "../canonicalOrdering.js"; +import { isMachOFormat } from "../binaryTargetTypes.js"; +import { analysisInputErrorFromIssues } from "../inputIssueProjection.js"; +import { inspectMachoSchema } from "../native/nativeInspection.js"; +import { err, ok, type Result } from "../result.js"; +import { + analysisViewInputError, + type AnalysisViewParent, + type AnalysisViewRequest, + type UnsignedAnalysisView, +} from "./analysisView.js"; +import { + completeWithinViewCoverage, + pageViewCoverage, +} from "./analysisViewCoverage.js"; + +const MACHO_COLLECTIONS = [ + "entrypoints", + "architectures", + "build_metadata", + "load_commands", + "dependencies", + "imports", + "exports", + "segments", +] as const; +type MachoCollection = (typeof MACHO_COLLECTIONS)[number]; + +/** Original inspect_macho rows; offsets count rows in the retained collection. */ +export const machoViewRequestSchema = z.strictObject({ + kind: z.literal("macho"), + facet: z.enum([...MACHO_COLLECTIONS, "provenance"]), + offset: z.number().int().nonnegative().default(0), + limit: z.number().int().positive().default(64), +}); + +const { shape } = inspectMachoSchema; +/** + * Union members are tried in order and plain objects drop unknown keys, so a + * segment or architecture row would otherwise match the entrypoint row and + * lose every field but file_offset. Exact key sets keep each page's rows whole. + */ +const exactRows = ( + rows: z.ZodArray>, +) => z.array(z.strictObject(rows.element.shape)); +export const machoViewItemSchema = z.union([ + exactRows(shape.entrypoints.shape.items), + exactRows(shape.architectures.shape.items), + exactRows(shape.build_metadata.shape.items), + exactRows(shape.load_commands.shape.items), + exactRows(shape.dependencies.shape.items), + // Imports and exports share one row shape. + exactRows(shape.imports.shape.items), + exactRows(shape.segments.shape.items), + exactRows(shape.provenance), +]); + +/** The producer's own coverage of the paged collection, not of this page. */ +export const machoViewContextSchema = z.strictObject({ + source_total: z.number().int().nonnegative().nullable(), + source_exhaustive: z.boolean(), +}); + +const collectionCountSchema = z.strictObject({ + returned: z.number().int().nonnegative(), + total: z.number().int().nonnegative().nullable(), + exhaustive: z.boolean(), +}); + +/** Slice identity and per-collection counts without the collections themselves. */ +export const machoSummarySchema = z.strictObject({ + format: shape.format, + selected_architecture: shape.selected_architecture, + endian: shape.endian, + word_size: shape.word_size, + file_type: shape.file_type, + flags: shape.flags, + uuid: shape.uuid, + collections: z.strictObject( + Object.fromEntries( + MACHO_COLLECTIONS.map((name) => [name, collectionCountSchema]), + ) as Record, + ), + provenance_count: z.number().int().nonnegative(), + limitation_count: z.number().int().nonnegative(), +}); + +type MachoReport = z.output; + +/** Admit a well-formed report whose recorded subject, if any, is a Mach-O. */ +const parseMachoReport = ( + parent: AnalysisViewParent, +): Result => { + const parsed = inspectMachoSchema.safeParse(parent.normalizedResult); + if (!parsed.success) + return err( + analysisInputErrorFromIssues( + "inspect_analysis_view", + parsed.error.issues.map((issue) => ({ + ...issue, + path: ["source", "normalized_result", ...issue.path], + })), + { source: { normalized_result: parent.normalizedResult } }, + { cause: parsed.error }, + ), + ); + if (parent.subject != null && !isMachOFormat(parent.subject.format)) + return err( + analysisViewInputError([ + { + path: ["source", "subject"], + reason: "invalid_value", + message: + "Mach-O parent Evidence subject must identify a thin or universal Mach-O.", + }, + ]), + ); + return ok(parsed.data); +}; + +/** Counts replace rows; every collection caveat stays in the limitations. */ +const summarizeMacho = ( + report: MachoReport, + parentLimitations: readonly string[], +) => { + const limitations = uniqueSorted([ + ...parentLimitations, + ...report.limitations, + ...MACHO_COLLECTIONS.flatMap((name) => report[name].limitations), + ]); + const collections = Object.fromEntries( + MACHO_COLLECTIONS.map((name) => [ + name, + { + returned: report[name].items.length, + total: report[name].total, + exhaustive: report[name].exhaustive, + }, + ]), + ) as Record>; + return { + limitations, + returned: MACHO_COLLECTIONS.reduce( + (sum, name) => sum + report[name].items.length, + 0, + ), + summary: { + format: report.format, + selected_architecture: report.selected_architecture, + endian: report.endian, + word_size: report.word_size, + file_type: report.file_type, + flags: report.flags, + uuid: report.uuid, + collections, + provenance_count: report.provenance.length, + limitation_count: limitations.length, + }, + }; +}; + +/** Project retained inspect_macho Evidence without rerunning native tools. */ +export const projectMachoView = ( + parent: AnalysisViewParent, + view: AnalysisViewRequest, +): Result => { + if (view.kind !== "summary" && view.kind !== "macho") + return err( + analysisViewInputError([ + { + path: ["view"], + reason: "invalid_value", + message: "Mach-O inspection supports summary and macho views.", + }, + ]), + ); + const parsed = parseMachoReport(parent); + if (!parsed.ok) return parsed; + const report = parsed.value; + const incomplete = MACHO_COLLECTIONS.filter( + (name) => !report[name].exhaustive, + ); + const shared = { + parent_evidence_id: parent.evidenceId, + parent_operation: "inspect_macho" as const, + parent_digest: parent.evidenceId.slice(3), + artifact: + parent.subject == null + ? { path: "", sha256: null } + : { + path: parent.subject.local_path, + sha256: parent.subject.digest.sha256, + }, + unknowns: [ + ...(incomplete.length === 0 + ? [] + : [ + `Native tools did not report exhaustive ${incomplete.join(", ")}; page exhaustion does not establish absence of unreturned rows.`, + ]), + ...(parent.subject == null + ? [ + "The parent has no recorded subject, so the inspected artifact path and SHA-256 are unknown.", + ] + : []), + ], + }; + if (view.kind === "summary") { + const { summary, limitations, returned } = summarizeMacho( + report, + parent.limitations, + ); + return ok({ + kind: "summary", + view, + ...shared, + limitations, + summary, + coverage: completeWithinViewCoverage(returned, returned), + }); + } + const source = + view.facet === "provenance" + ? { + items: report.provenance, + total: report.provenance.length, + exhaustive: true, + limitations: [], + } + : report[view.facet]; + const item = source.items.slice(view.offset, view.offset + view.limit); + return ok({ + kind: "macho", + view, + item, + ...shared, + limitations: uniqueSorted([ + ...parent.limitations, + ...report.limitations, + ...source.limitations, + ]), + source_total: source.total, + source_exhaustive: source.exhaustive, + coverage: pageViewCoverage(view.offset, item.length, source.items.length), + }); +}; diff --git a/src/domain/analysisView/pcapCaptureView.ts b/src/domain/analysisView/pcapCaptureView.ts new file mode 100644 index 000000000..a28398d44 --- /dev/null +++ b/src/domain/analysisView/pcapCaptureView.ts @@ -0,0 +1,327 @@ +import { z } from "zod"; +import { pcapResultSchemas } from "../pcap/pcapAnalysis.js"; +import { analysisInputErrorFromIssues } from "../inputIssueProjection.js"; +import type { AnalysisError } from "../analysisErrorBase.js"; +import { err, ok, type Result } from "../result.js"; +import { + analysisViewInputError, + type AnalysisViewParent, + type AnalysisViewRequest, + type UnsignedAnalysisView, +} from "./analysisView.js"; +import { + completeWithinViewCoverage, + pageViewCoverage, +} from "./analysisViewCoverage.js"; + +const captureSchema = pcapResultSchemas.inspect_pcap_capture; +const fields = captureSchema.shape; +const pageShape = { + kind: z.literal("pcap"), + offset: z.number().int().nonnegative().default(0), + limit: z.number().int().positive().default(64), +}; +export const pcapViewRequestSchema = z.discriminatedUnion("facet", [ + z.strictObject({ + ...pageShape, + facet: z.enum([ + "endpoints", + "dns-queries", + "tls-sni", + "protocols", + "http-uris", + "unattributed-addresses", + ]), + }), + z.strictObject({ + ...pageShape, + facet: z.literal("dns-addresses"), + query: z.string().min(1), + }), + z.strictObject({ + ...pageShape, + facet: z.literal("diagnostics"), + stream: z.enum(["tshark", "capinfos"]), + }), +]); +export const pcapViewPageSchema = z.discriminatedUnion("facet", [ + z.strictObject({ facet: z.literal("endpoints"), items: fields.endpoints }), + z.strictObject({ + facet: z.literal("dns-queries"), + items: z.array( + fields.dns_queries.element.omit({ response_addresses: true }).extend({ + retained_response_address_count: z.number().int().nonnegative(), + }), + ), + }), + z.strictObject({ facet: z.literal("tls-sni"), items: fields.tls_sni_values }), + z.strictObject({ + facet: z.literal("protocols"), + items: fields.protocol_distribution, + }), + z.strictObject({ + facet: z.literal("http-uris"), + items: fields.http_request_uris, + }), + z.strictObject({ + facet: z.literal("unattributed-addresses"), + items: fields.unattributed_dns_addresses, + }), + z.strictObject({ + facet: z.literal("dns-addresses"), + items: fields.unattributed_dns_addresses, + }), + z.strictObject({ + facet: z.literal("diagnostics"), + text: z.string(), + status: z.enum(["retained", "unknown"]), + }), +]); +export const pcapSummarySchema = captureSchema + .omit({ + endpoints: true, + dns_queries: true, + tls_sni_values: true, + protocol_distribution: true, + http_request_uris: true, + unattributed_dns_addresses: true, + diagnostics: true, + }) + .extend({ + retained_counts: z.strictObject({ + endpoints: z.number().int().nonnegative(), + dns_queries: z.number().int().nonnegative(), + tls_sni_values: z.number().int().nonnegative(), + protocol_distribution: z.number().int().nonnegative(), + http_request_uris: z.number().int().nonnegative(), + unattributed_dns_addresses: z.number().int().nonnegative(), + }), + diagnostics_code_units: z + .strictObject({ + tshark: z.number().int().nonnegative(), + capinfos: z.number().int().nonnegative(), + }) + .nullable(), + }); +type Capture = z.output; +type PcapView = z.output; +type Page = z.output; + +const parseParent = ( + parent: AnalysisViewParent, +): Result => { + const parsed = captureSchema.safeParse(parent.normalizedResult); + if (!parsed.success) + return err( + analysisInputErrorFromIssues( + "inspect_analysis_view", + parsed.error.issues, + parent.normalizedResult, + { cause: parsed.error }, + ), + ); + if ( + parent.subject?.local_path !== parsed.data.target.path || + parent.subject.digest.sha256 !== parsed.data.target.sha256 + ) + return err( + analysisViewInputError([ + { + path: ["source", "subject"], + reason: "invalid_value", + message: + "Packet parent subject must identify the report's exact path and SHA-256.", + }, + ]), + ); + return ok(parsed.data); +}; +const summarize = ({ + endpoints, + dns_queries, + tls_sni_values, + protocol_distribution, + http_request_uris, + unattributed_dns_addresses, + diagnostics, + ...metadata +}: Capture) => ({ + ...metadata, + retained_counts: { + endpoints: endpoints.length, + dns_queries: dns_queries.length, + tls_sni_values: tls_sni_values.length, + protocol_distribution: protocol_distribution.length, + http_request_uris: http_request_uris.length, + unattributed_dns_addresses: unattributed_dns_addresses.length, + }, + diagnostics_code_units: + diagnostics === undefined + ? null + : { + tshark: diagnostics.tshark_stderr.length, + capinfos: diagnostics.capinfos_stderr.length, + }, +}); + +const selectRows = ( + capture: Capture, + view: Exclude, +): Result< + { page: Exclude; total: number }, + AnalysisError +> => { + const slice = (items: readonly T[]) => + items.slice(view.offset, view.offset + view.limit); + switch (view.facet) { + case "endpoints": + return ok({ + page: { facet: view.facet, items: slice(capture.endpoints) }, + total: capture.endpoints.length, + }); + case "dns-queries": + return ok({ + page: { + facet: view.facet, + items: slice(capture.dns_queries).map( + ({ response_addresses, ...query }) => ({ + ...query, + retained_response_address_count: response_addresses.length, + }), + ), + }, + total: capture.dns_queries.length, + }); + case "tls-sni": + return ok({ + page: { facet: view.facet, items: slice(capture.tls_sni_values) }, + total: capture.tls_sni_values.length, + }); + case "protocols": + return ok({ + page: { + facet: view.facet, + items: slice(capture.protocol_distribution), + }, + total: capture.protocol_distribution.length, + }); + case "http-uris": + return ok({ + page: { facet: view.facet, items: slice(capture.http_request_uris) }, + total: capture.http_request_uris.length, + }); + case "unattributed-addresses": + return ok({ + page: { + facet: view.facet, + items: slice(capture.unattributed_dns_addresses), + }, + total: capture.unattributed_dns_addresses.length, + }); + case "dns-addresses": { + const matches = capture.dns_queries.filter( + (query) => query.query === view.query, + ); + if (matches.length !== 1) + return err( + analysisViewInputError([ + { + path: ["view", "query"], + reason: "invalid_value", + message: "Select one unambiguous exact retained DNS question.", + }, + ]), + ); + return ok({ + page: { + facet: view.facet, + items: slice(matches[0]!.response_addresses), + }, + total: matches[0]!.response_addresses.length, + }); + } + } +}; + +/** Historical packet facts are paged without reopening the source or rerunning Wireshark. */ +export const projectPcapCaptureView = ( + parent: AnalysisViewParent, + view: AnalysisViewRequest, +): Result => { + if (view.kind !== "summary" && view.kind !== "pcap") + return err( + analysisViewInputError([ + { + path: ["view"], + reason: "invalid_value", + message: + "Packet summary parents support summary and pcap fact pages.", + }, + ]), + ); + const parsed = parseParent(parent); + if (!parsed.ok) return parsed; + const capture = parsed.value; + const shared = { + parent_evidence_id: parent.evidenceId, + parent_operation: "inspect_pcap_capture" as const, + parent_digest: parent.evidenceId.slice(3), + artifact: { path: capture.target.path, sha256: capture.target.sha256 }, + limitations: [ + ...parent.limitations, + "Page totals count retained rows or UTF-16 diagnostic code units. Exhaustion does not prove whole-network completeness; source coverage and examined counts remain separate.", + ], + unknowns: [ + "Saved packet observations do not establish process identity, causality, encrypted payload contents or traffic missing from the recording.", + ], + }; + if (view.kind === "summary") + return ok({ + kind: "summary", + view, + ...shared, + summary: summarize(capture), + coverage: completeWithinViewCoverage(1, 1), + }); + if (view.facet === "diagnostics") { + const value = + view.stream === "tshark" + ? capture.diagnostics?.tshark_stderr + : capture.diagnostics?.capinfos_stderr; + const text = value?.slice(view.offset, view.offset + view.limit) ?? ""; + return ok({ + kind: "pcap", + view, + ...shared, + source_coverage: capture.coverage, + page: { + facet: "diagnostics", + text, + status: value === undefined ? "unknown" : "retained", + }, + coverage: pageViewCoverage(view.offset, text.length, value?.length ?? 0), + unknowns: + value === undefined + ? [ + ...shared.unknowns, + "The parent did not retain diagnostics; an empty text page does not establish their absence.", + ] + : shared.unknowns, + }); + } + const selected = selectRows(capture, view); + return selected.ok + ? ok({ + kind: "pcap", + view, + ...shared, + source_coverage: capture.coverage, + page: selected.value.page, + coverage: pageViewCoverage( + view.offset, + selected.value.page.items.length, + selected.value.total, + ), + }) + : selected; +}; diff --git a/src/domain/analysisView/qlogCaptureView.ts b/src/domain/analysisView/qlogCaptureView.ts new file mode 100644 index 000000000..a3bdf88c3 --- /dev/null +++ b/src/domain/analysisView/qlogCaptureView.ts @@ -0,0 +1,248 @@ +import { z } from "zod"; +import { + qlogCaptureFactsSchema, + type QlogCaptureFacts, +} from "../qlogCapture.js"; +import { err, ok, type Result } from "../result.js"; +import type { AnalysisError } from "../analysisErrorBase.js"; +import { analysisViewInputError } from "./analysisView.js"; +import { pageViewCoverage } from "./analysisViewCoverage.js"; + +const traceSchema = qlogCaptureFactsSchema.shape.traces.element; +const streamSchema = traceSchema.shape.streams.element; +export const qlogViewContextSchema = qlogCaptureFactsSchema.omit({ + traces: true, +}); +export const qlogSummarySchema = qlogViewContextSchema.extend({ + trace_count: z.number().int().nonnegative(), + retained_stream_count: z.number().int().nonnegative(), + loss_declaration_count: z.number().int().nonnegative(), + incomplete_fact_record_count: z.number().int().nonnegative(), +}); + +/** Select retained trace facts without copying event inventories or every contribution. */ +const pageRequestShape = { + kind: z.literal("qlog"), + offset: z.number().int().nonnegative().default(0), + limit: z.number().int().positive().default(64), +}; +const traceSelectorShape = { trace_index: z.number().int().nonnegative() }; +const streamSelectorShape = { + ...traceSelectorShape, + stream_id: streamSchema.shape.stream_id, + direction: streamSchema.shape.direction, +}; +export const qlogViewRequestSchema = z.discriminatedUnion("facet", [ + z.strictObject({ ...pageRequestShape, facet: z.literal("traces") }), + z.strictObject({ + ...pageRequestShape, + ...traceSelectorShape, + facet: z.literal("streams"), + }), + z.strictObject({ + ...pageRequestShape, + ...traceSelectorShape, + facet: z.literal("loss-declarations"), + }), + z.strictObject({ + ...pageRequestShape, + ...traceSelectorShape, + facet: z.literal("incomplete-records"), + }), + z.strictObject({ + ...pageRequestShape, + ...streamSelectorShape, + facet: z.literal("contributions"), + }), + z.strictObject({ + ...pageRequestShape, + ...streamSelectorShape, + facet: z.literal("ranges"), + }), + z.strictObject({ + ...pageRequestShape, + ...streamSelectorShape, + facet: z.literal("final-sizes"), + }), +]); +export type QlogViewRequest = z.output; + +const traceSummarySchema = traceSchema + .omit({ + streams: true, + loss_declarations: true, + incomplete_fact_records: true, + }) + .extend({ + stream_count: z.number().int().nonnegative(), + loss_declaration_count: z.number().int().nonnegative(), + incomplete_fact_record_count: z.number().int().nonnegative(), + }); +const streamSummarySchema = streamSchema + .omit({ + contributions: true, + covered_ranges: true, + reported_final_sizes: true, + }) + .extend({ + contribution_count: z.number().int().nonnegative(), + covered_range_count: z.number().int().nonnegative(), + reported_final_size_count: z.number().int().nonnegative(), + }); +/** Each page advertises exactly the retained item contract for its facet. */ +export const qlogViewPageSchema = z.discriminatedUnion("facet", [ + z.strictObject({ + facet: z.literal("traces"), + items: z.array(traceSummarySchema), + }), + z.strictObject({ + facet: z.literal("streams"), + items: z.array(streamSummarySchema), + }), + z.strictObject({ + facet: z.literal("loss-declarations"), + items: traceSchema.shape.loss_declarations, + }), + z.strictObject({ + facet: z.literal("incomplete-records"), + items: traceSchema.shape.incomplete_fact_records, + }), + z.strictObject({ + facet: z.literal("contributions"), + items: streamSchema.shape.contributions, + }), + z.strictObject({ + facet: z.literal("ranges"), + items: streamSchema.shape.covered_ranges, + }), + z.strictObject({ + facet: z.literal("final-sizes"), + items: streamSchema.shape.reported_final_sizes, + }), +]); +type QlogViewPage = z.output; + +export const summarizeQlogCapture = (qlog: QlogCaptureFacts) => { + const { traces, ...context } = qlog; + return { + ...context, + trace_count: traces.length, + retained_stream_count: traces.reduce( + (sum, trace) => sum + trace.streams.length, + 0, + ), + loss_declaration_count: traces.reduce( + (sum, trace) => sum + trace.loss_declarations.length, + 0, + ), + incomplete_fact_record_count: traces.reduce( + (sum, trace) => sum + trace.incomplete_fact_records.length, + 0, + ), + }; +}; + +const summarizeTrace = ({ + streams, + loss_declarations, + incomplete_fact_records, + ...trace +}: QlogCaptureFacts["traces"][number]) => ({ + ...trace, + stream_count: streams.length, + loss_declaration_count: loss_declarations.length, + incomplete_fact_record_count: incomplete_fact_records.length, +}); +const summarizeStream = ({ + contributions, + covered_ranges, + reported_final_sizes, + ...stream +}: QlogCaptureFacts["traces"][number]["streams"][number]) => ({ + ...stream, + contribution_count: contributions.length, + covered_range_count: covered_ranges.length, + reported_final_size_count: reported_final_sizes.length, +}); + +/** Array offsets refer to retained facts, whose scope remains all recorded events. */ +export const projectQlogCapturePage = ( + qlog: QlogCaptureFacts, + view: QlogViewRequest, +): Result< + { + context: z.output; + page: QlogViewPage; + coverage: ReturnType; + }, + AnalysisError +> => { + const invalid = (field: string, message: string) => + err( + analysisViewInputError([ + { path: ["view", field], reason: "invalid_value", message }, + ]), + ); + const slice = (items: readonly T[]) => + items.slice(view.offset, view.offset + view.limit); + let page: QlogViewPage; + let total: number; + if (view.facet === "traces") { + total = qlog.traces.length; + page = { + facet: "traces", + items: slice(qlog.traces).map(summarizeTrace), + }; + } else { + const matches = qlog.traces.filter( + (trace) => trace.trace_index === view.trace_index, + ); + if (matches.length !== 1) + return invalid( + "trace_index", + "Select one unambiguous retained trace index.", + ); + const trace = matches[0]!; + if (view.facet === "streams") { + total = trace.streams.length; + page = { + facet: "streams", + items: slice(trace.streams).map(summarizeStream), + }; + } else if (view.facet === "loss-declarations") { + total = trace.loss_declarations.length; + page = { facet: view.facet, items: slice(trace.loss_declarations) }; + } else if (view.facet === "incomplete-records") { + total = trace.incomplete_fact_records.length; + page = { facet: view.facet, items: slice(trace.incomplete_fact_records) }; + } else { + const matches = trace.streams.filter( + (stream) => + stream.stream_id === view.stream_id && + stream.direction === view.direction, + ); + if (matches.length !== 1) + return invalid( + "stream_id", + "Select one unambiguous retained stream ID and direction within the trace.", + ); + const stream = matches[0]!; + if (view.facet === "contributions") { + total = stream.contributions.length; + page = { facet: view.facet, items: slice(stream.contributions) }; + } else if (view.facet === "ranges") { + total = stream.covered_ranges.length; + page = { facet: view.facet, items: slice(stream.covered_ranges) }; + } else { + total = stream.reported_final_sizes.length; + page = { facet: view.facet, items: slice(stream.reported_final_sizes) }; + } + } + } + const { traces: _traces, ...context } = qlog; + return ok({ + context, + page, + coverage: pageViewCoverage(view.offset, page.items.length, total), + }); +}; diff --git a/src/domain/analysisView/wasmArtifactView.ts b/src/domain/analysisView/wasmArtifactView.ts index 111078600..dc3036b26 100644 --- a/src/domain/analysisView/wasmArtifactView.ts +++ b/src/domain/analysisView/wasmArtifactView.ts @@ -103,6 +103,7 @@ export const projectWasmArtifactView = ( : { path: parent.subject.local_path, sha256: parent.subject.digest.sha256, + format: parent.subject.format, }, ) ) diff --git a/src/domain/analysisView/webNetworkApiSurfaceView.test.ts b/src/domain/analysisView/webNetworkApiSurfaceView.test.ts index f13e392ff..b57d54b59 100644 --- a/src/domain/analysisView/webNetworkApiSurfaceView.test.ts +++ b/src/domain/analysisView/webNetworkApiSurfaceView.test.ts @@ -85,11 +85,13 @@ it("pages groups independently of record completeness and preserves null digests }); it("rejects native captures and malformed parents with typed errors", () => { const capture = analysisViewCaptureFixture(); - capture.format = "mitmproxy"; - expect(project(capture)).toMatchObject({ - ok: false, - error: { _tag: "AnalysisUnsupportedTargetError" }, - }); + for (const format of ["mitmproxy", "saz"] as const) { + capture.format = format; + expect(project(capture)).toMatchObject({ + ok: false, + error: { _tag: "AnalysisUnsupportedTargetError" }, + }); + } expect( projectAnalysisView( { diff --git a/src/domain/analysisView/webNetworkCaptureView.test.ts b/src/domain/analysisView/webNetworkCaptureView.test.ts new file mode 100644 index 000000000..ff73b29a6 --- /dev/null +++ b/src/domain/analysisView/webNetworkCaptureView.test.ts @@ -0,0 +1,176 @@ +import { expect, it } from "vitest"; +import { createHash } from "node:crypto"; +import { createEvidence } from "../evidence.js"; +import { webNetworkCaptureSchema } from "../webNetworkCapture.js"; +import { projectAnalysisView } from "./analysisView.js"; + +const capture = () => { + const body = Buffer.from("original body"); + const artifact = { + path: "/recordings/input.saz", + sha256: "b".repeat(64), + bytes: 100, + }; + const decoder = { id: "fixture", name: "Fixture", version: "1" }; + const report = webNetworkCaptureSchema.parse({ + artifact, + decoder, + format: "saz", + runtime_attribution: "unknown", + limitations: [], + container: { + reported: { members: [] }, + numeric_literals: [], + redactions: [], + records_pointer: null, + }, + total_records: 9, + records: [7, 2].map((ordinal) => ({ + ordinal, + location: { kind: "archive-members", members: [`raw/${ordinal}_c.txt`] }, + reported: { + session_id: String(ordinal), + time: null, + request: { + method: "POST", + url: "https://example.invalid/a", + body: body.toString(), + }, + }, + binary_fields: [ + { + pointer: "/request/body", + representation: "producer-bytes", + state: "retained", + content_base64: body.toString("base64"), + bytes: body.length, + sha256: createHash("sha256").update(body).digest("hex"), + }, + ], + numeric_literals: [ + { + pointer: "/time", + producer_type: "json-number", + literal: "9007199254740993", + }, + ], + redactions: [], + limitations: [], + })), + }); + const evidence = createEvidence({ ...artifact, format: "file" }, decoder, { + operation: "inspect_web_network_capture", + parameters: { record_ordinals: [7, 2] }, + result: report, + confidence: "observed", + authority: "historical-reference", + }); + return { + report, + parent: { + evidenceId: evidence.evidence_id, + operation: evidence.operation, + normalizedResult: report, + subject: evidence.subject, + limitations: evidence.limitations, + }, + }; +}; + +it("keeps selected-record page coverage distinct from capture coverage and unsafe number absence", () => { + const { parent, report } = capture(); + const summary = projectAnalysisView(parent, { kind: "summary" }); + expect(summary.ok && summary.value).toMatchObject({ + summary: { total_records: 9, retained_records: 2 }, + coverage: { examined: 2, total: 2 }, + }); + const preview = projectAnalysisView(parent, { + kind: "capture", + detail: "preview", + offset: 0, + limit: 1, + }); + expect(preview.ok && preview.value).toMatchObject({ + items: [ + { + ordinal: 7, + reported: { time: null }, + numeric_literals: [{ pointer: "/time", literal: "9007199254740993" }], + }, + ], + coverage: { total: 2, examined: 1, next_offset: 1, exhausted: false }, + }); + expect(JSON.stringify(preview)).not.toContain("original body"); + expect(JSON.stringify(preview)).not.toContain("content_base64"); + const complete = projectAnalysisView(parent, { + kind: "capture", + detail: "complete", + offset: 1, + limit: 1, + }); + expect(complete.ok && complete.value).toMatchObject({ + items: [report.records[1]], + coverage: { total: 2, examined: 1, next_offset: null, exhausted: true }, + }); + const empty = projectAnalysisView(parent, { + kind: "capture", + detail: "preview", + offset: 50, + limit: 1, + }); + expect(empty.ok && empty.value).toMatchObject({ + items: [], + coverage: { + status: "empty", + total: 2, + examined: 0, + next_offset: null, + exhausted: true, + }, + }); +}); + +it("retains explicitly unknown digests and rejects a different subject path", () => { + const { parent, report } = capture(); + const unknown = projectAnalysisView( + { + ...parent, + subject: null, + normalizedResult: { + ...report, + artifact: { ...report.artifact, sha256: null }, + }, + }, + { kind: "summary" }, + ); + expect(unknown.ok && unknown.value).toMatchObject({ + artifact: { sha256: null }, + }); + expect(unknown.ok && unknown.value.unknowns.join(" ")).toContain( + "excluded artifact digest", + ); + if (parent.subject === null) throw new Error("Expected fixture subject"); + const mismatched = projectAnalysisView( + { + ...parent, + subject: { ...parent.subject, local_path: "/different/source.saz" }, + }, + { kind: "summary" }, + ); + expect(mismatched.ok).toBe(false); +}); + +it("rejects invalid ordinal coverage in a borrowed parent", () => { + const { parent, report } = capture(); + const result = projectAnalysisView( + { + ...parent, + normalizedResult: { + ...report, + records: [report.records[0], report.records[0]], + }, + }, + { kind: "summary" }, + ); + expect(result.ok).toBe(false); +}); diff --git a/src/domain/analysisView/webNetworkCaptureView.ts b/src/domain/analysisView/webNetworkCaptureView.ts new file mode 100644 index 000000000..b335e9241 --- /dev/null +++ b/src/domain/analysisView/webNetworkCaptureView.ts @@ -0,0 +1,264 @@ +import { z } from "zod"; +import type { AnalysisError } from "../analysisErrorBase.js"; +import { analysisInputErrorFromIssues } from "../inputIssueProjection.js"; +import type { JsonValue } from "../jsonValue.js"; +import { err, ok, type Result } from "../result.js"; +import { + webNetworkCaptureRecordSchema, + webNetworkCaptureBinaryDescriptorSchema, + webNetworkCaptureSchema, + webNetworkCaptureArtifactSchema, + webNetworkCaptureDecoderSchema, + WEB_NETWORK_CAPTURE_FORMATS, + type WebNetworkCaptureRecord, + type WebNetworkCapture, +} from "../webNetworkCapture.js"; +import { + analysisViewInputError, + type AnalysisViewParent, + type AnalysisViewRequest, + type UnsignedAnalysisView, +} from "./analysisView.js"; +import { + completeWithinViewCoverage, + pageViewCoverage, +} from "./analysisViewCoverage.js"; +import { + qlogSummarySchema, + summarizeQlogCapture, + projectQlogCapturePage, +} from "./qlogCaptureView.js"; + +/** Offsets page the parent's retained record order, preserving producer ordinals. */ +export const captureViewRequestSchema = z.strictObject({ + kind: z.literal("capture"), + detail: z.enum(["preview", "complete"]).default("preview"), + offset: z.number().int().nonnegative().default(0), + limit: z.number().int().positive().default(64), +}); + +const previewSchema = webNetworkCaptureRecordSchema.extend({ + binary_fields: z.array(webNetworkCaptureBinaryDescriptorSchema), +}); +export const captureViewItemsSchema = z.array( + z.union([webNetworkCaptureRecordSchema, previewSchema]), +); + +/** Count/identity overview; bodies and the archive member inventory stay in the parent. */ +export const captureSummarySchema = z.strictObject({ + artifact: webNetworkCaptureArtifactSchema, + decoder: webNetworkCaptureDecoderSchema, + format: z.enum(WEB_NETWORK_CAPTURE_FORMATS), + total_records: z.number().int().nonnegative(), + retained_records: z.number().int().nonnegative(), + runtime_attribution: z.literal("unknown"), + qlog: qlogSummarySchema.optional(), +}); + +const object = ( + value: JsonValue, +): Readonly> | null => + value !== null && typeof value === "object" && !Array.isArray(value) + ? value + : null; + +/** Select already parsed producer facts without interpreting HTTP or payload bytes again. */ +const preview = (record: WebNetworkCaptureRecord) => { + const source = object(record.reported); + const reported: Record = {}; + const selectedPointers = new Set(); + if (source !== null) { + for (const key of ["session_id", "name", "time", "startedDateTime", "type"]) + if (Object.hasOwn(source, key) && source[key] !== undefined) { + reported[key] = source[key]; + selectedPointers.add(`/${key}`); + } + for (const key of ["request", "response"]) { + const value = source[key]; + if (!Object.hasOwn(source, key) || value === undefined) continue; + const fields = object(value); + if (fields === null) { + // Preserve a reported null/scalar instead of inventing HTTP fields. + reported[key] = value; + continue; + } + const selected: Record = {}; + for (const field of [ + "method", + "url", + "httpVersion", + "http_version", + "status", + "statusText", + "reason", + ]) + if (Object.hasOwn(fields, field) && fields[field] !== undefined) { + selected[field] = fields[field]; + selectedPointers.add(`/${key}/${field}`); + } + reported[key] = selected; + } + } + return { + ...record, + reported: source === null ? record.reported : reported, + binary_fields: record.binary_fields.map( + ({ content_base64: _content, ...field }) => field, + ), + numeric_literals: + source === null + ? record.numeric_literals + : record.numeric_literals.filter(({ pointer }) => + selectedPointers.has(pointer), + ), + }; +}; + +/** Authenticate the retained report and its subject at one owning boundary. */ +const parseCaptureParent = ( + parent: AnalysisViewParent, +): Result => { + const parsed = webNetworkCaptureSchema.safeParse(parent.normalizedResult); + if (!parsed.success) + return err( + analysisInputErrorFromIssues( + "inspect_analysis_view", + parsed.error.issues.map((issue) => ({ + ...issue, + path: ["source", "normalized_result", ...issue.path], + })), + { source: { normalized_result: parent.normalizedResult } }, + { cause: parsed.error }, + ), + ); + const report = parsed.data; + if ( + report.artifact.sha256 !== null && + (parent.subject == null || + parent.subject.local_path !== report.artifact.path || + parent.subject.digest.sha256 !== report.artifact.sha256) + ) + return err( + analysisViewInputError([ + { + path: ["source", "subject"], + reason: "invalid_value", + message: + "Capture parent subject must identify the report's exact path and SHA-256.", + }, + ]), + ); + return ok(report); +}; + +/** Page immutable retained facts; no capture file, provider or network is consulted. */ +export const projectWebNetworkCaptureView = ( + parent: AnalysisViewParent, + view: AnalysisViewRequest, +): Result => { + if ( + view.kind !== "summary" && + view.kind !== "capture" && + view.kind !== "qlog" + ) + return err( + analysisViewInputError([ + { + path: ["view"], + reason: "invalid_value", + message: + "Historical captures support summary, capture record pages, qlog fact pages and admitted api-surface views.", + }, + ]), + ); + const parsed = parseCaptureParent(parent); + if (!parsed.ok) return parsed; + const report = parsed.value; + const shared = { + parent_evidence_id: parent.evidenceId, + parent_operation: "inspect_web_network_capture" as const, + parent_digest: parent.evidenceId.slice(3), + artifact: { path: report.artifact.path, sha256: report.artifact.sha256 }, + limitations: [ + ...new Set([ + ...parent.limitations, + ...report.limitations, + "Capture record pages cover the records selected into the parent Evidence, in that selected order; total_records counts the original decoded capture.", + ]), + ], + unknowns: [ + "Historical records do not establish live runtime attribution or deployment authenticity.", + ...(report.artifact.sha256 === null + ? ["The explicitly excluded artifact digest remains unknown."] + : []), + ], + }; + if (view.kind === "summary") + return ok({ + kind: "summary", + view, + ...shared, + summary: { + artifact: report.artifact, + decoder: report.decoder, + format: report.format, + total_records: report.total_records, + retained_records: report.records.length, + runtime_attribution: report.runtime_attribution, + ...(report.format === "qlog" + ? { qlog: summarizeQlogCapture(report.qlog) } + : {}), + }, + coverage: completeWithinViewCoverage( + report.records.length, + report.records.length, + ), + }); + if (view.kind === "qlog") { + if (report.format !== "qlog") + return err( + analysisViewInputError([ + { + path: ["view", "kind"], + reason: "invalid_value", + message: "Qlog fact views require retained qlog Evidence.", + }, + ]), + ); + const projected = projectQlogCapturePage(report.qlog, view); + return projected.ok + ? ok({ + kind: "qlog", + view, + ...shared, + ...projected.value, + limitations: [ + ...shared.limitations, + "Qlog fact pages retain all-recorded-events-before-selection scope. Exhausting a page does not establish network completeness, body recovery, retransmission or actual loss.", + ], + }) + : projected; + } + const records = report.records.slice(view.offset, view.offset + view.limit); + return ok({ + kind: "capture", + view, + ...shared, + items: captureViewItemsSchema.parse( + view.detail === "complete" ? records : records.map(preview), + ), + coverage: pageViewCoverage( + view.offset, + records.length, + report.records.length, + ), + limitations: [ + ...shared.limitations, + ...(view.detail === "preview" + ? [ + "Preview selects recorded headline fields and byte descriptors; headers, XML, bodies, message data and other fields remain in complete record pages. Missing preview fields do not establish their absence from the producer record.", + ] + : []), + ], + }); +}; diff --git a/src/domain/android/androidAnalysis.ts b/src/domain/android/androidAnalysis.ts index e27be2b20..ca4d6db59 100644 --- a/src/domain/android/androidAnalysis.ts +++ b/src/domain/android/androidAnalysis.ts @@ -45,6 +45,12 @@ export const androidInputSchemas = { }), } as const; +/** Optional retained delivery is separate from the engine's APK request. */ +export const androidPackageInspectionInputSchema = + androidInputSchemas.inspect_android_package.extend({ + detail: z.enum(["complete", "summary"]).optional(), + }); + /** Supported static Android operations. */ export type AndroidOperation = keyof typeof androidInputSchemas; /** Validated Android requests carry their selected operation. */ diff --git a/src/domain/apple/dylibResolution.test.ts b/src/domain/apple/dylibResolution.test.ts index 2d63ce393..13bb7c4f6 100644 --- a/src/domain/apple/dylibResolution.test.ts +++ b/src/domain/apple/dylibResolution.test.ts @@ -597,6 +597,136 @@ describe("dyld load order", () => { }); }); +describe("loader-relative dylib resolution", () => { + it("does not reuse already loaded images by install name for @loader_path dependencies", async () => { + const pluginA = "Contents/PlugIns/A/pluginA.dylib"; + const helperA = "Contents/PlugIns/A/libhelper.dylib"; + const pluginB = "Contents/PlugIns/B/pluginB.dylib"; + const trace = await traceDylibLoading( + memoryView({ + [MAIN]: executable({ + dependencies: [ + dependency("@executable_path/../PlugIns/A/pluginA.dylib"), + dependency("@executable_path/../PlugIns/B/pluginB.dylib"), + ], + }), + [pluginA]: parsed( + slice({ + dependencies: [dependency("@loader_path/libhelper.dylib")], + }), + ), + [helperA]: parsed( + slice({ + install_name: "@loader_path/libhelper.dylib", + }), + ), + [pluginB]: parsed( + slice({ + dependencies: [dependency("@loader_path/libhelper.dylib")], + }), + ), + }), + { roots: [MAIN] }, + ); + + const edgeA = edgeFor(trace, pluginA, "@loader_path/libhelper.dylib"); + expect(edgeA.resolution).toEqual({ + status: "resolved", + image: helperA, + }); + expect(edgeA.candidates).toEqual([ + expect.objectContaining({ + source: "loader_path", + outcome: "resolved", + resolved_path: helperA, + }), + ]); + + const edgeB = edgeFor(trace, pluginB, "@loader_path/libhelper.dylib"); + expect(edgeB.resolution).toEqual({ + status: "unresolved", + image: null, + }); + expect(edgeB.candidates).toEqual([ + expect.objectContaining({ + path: "Contents/PlugIns/B/libhelper.dylib", + source: "loader_path", + outcome: "absent", + resolved_path: null, + }), + ]); + expect(trace.findings).toContainEqual( + expect.objectContaining({ + kind: "required-load-unresolved", + image: pluginB, + }), + ); + }); + + it("resolves @loader_path dependencies to the loader's own directory when multiple helpers exist", async () => { + const pluginA = "Contents/PlugIns/A/pluginA.dylib"; + const helperA = "Contents/PlugIns/A/libhelper.dylib"; + const pluginB = "Contents/PlugIns/B/pluginB.dylib"; + const helperB = "Contents/PlugIns/B/libhelper.dylib"; + const trace = await traceDylibLoading( + memoryView({ + [MAIN]: executable({ + dependencies: [ + dependency("@executable_path/../PlugIns/A/pluginA.dylib"), + dependency("@executable_path/../PlugIns/B/pluginB.dylib"), + ], + }), + [pluginA]: parsed( + slice({ + dependencies: [dependency("@loader_path/libhelper.dylib")], + }), + ), + [helperA]: parsed( + slice({ + install_name: "@loader_path/libhelper.dylib", + }), + ), + [pluginB]: parsed( + slice({ + dependencies: [dependency("@loader_path/libhelper.dylib")], + }), + ), + [helperB]: parsed( + slice({ + install_name: "@loader_path/libhelper.dylib", + }), + ), + }), + { roots: [MAIN] }, + ); + + expect( + edgeFor(trace, pluginA, "@loader_path/libhelper.dylib"), + ).toMatchObject({ + resolution: { status: "resolved", image: helperA }, + candidates: [ + expect.objectContaining({ + source: "loader_path", + outcome: "resolved", + resolved_path: helperA, + }), + ], + }); + expect( + edgeFor(trace, pluginB, "@loader_path/libhelper.dylib"), + ).toMatchObject({ + resolution: { status: "resolved", image: helperB }, + candidates: [ + expect.objectContaining({ + source: "loader_path", + outcome: "resolved", + resolved_path: helperB, + }), + ], + }); + }); +}); + describe("dyld slice compatibility and coverage", () => { it("lets an x86_64h process load generic x86_64 but not arm64e load arm64", async () => { const files = { diff --git a/src/domain/apple/dylibResolution.ts b/src/domain/apple/dylibResolution.ts index 00077efa1..cf10c4b78 100644 --- a/src/domain/apple/dylibResolution.ts +++ b/src/domain/apple/dylibResolution.ts @@ -16,6 +16,7 @@ import { import { DYLIB_RESOLUTION_LIMITATIONS, deriveFindings, + type TracedRootSlice, } from "./dylibResolutionFindings.js"; /** @@ -427,7 +428,9 @@ const resolveDependency = async ( ): Promise => { const current = context.loaded.get(loader); const chain = current?.chain ?? [loader]; - const loaded = context.byInstallName.get(dependency.install_name); + const loaded = dependency.install_name.startsWith("@rpath/") + ? context.byInstallName.get(dependency.install_name) + : undefined; const candidates: Candidate[] = []; if (loaded !== undefined) candidates.push({ @@ -506,7 +509,10 @@ const traceProcess = async ( chain: [context.root], conditional: false, }); - if (rootSlice.install_name !== null) + if ( + rootSlice.install_name !== null && + rootSlice.install_name.startsWith("@rpath/") + ) context.byInstallName.set(rootSlice.install_name, context.root); const pending = [context.root]; while (pending.length > 0) { @@ -537,6 +543,7 @@ const traceProcess = async ( }); if ( slice.install_name !== null && + slice.install_name.startsWith("@rpath/") && !context.byInstallName.has(slice.install_name) ) context.byInstallName.set(slice.install_name, image); @@ -562,6 +569,7 @@ export const traceDylibLoading = async ( for (const path of request.unclassified ?? []) images.set(path, await view.image(path)); const roots: DylibTrace["roots"][number][] = []; + const rootSlices: TracedRootSlice[] = []; const edges: Edge[] = []; const withoutArchitecture: string[] = []; const environmentRoots = new Set(); @@ -591,6 +599,7 @@ export const traceDylibLoading = async ( ) environmentRoots.add(root); roots.push({ image: root, architecture: slice.architecture }); + rootSlices.push({ image: root, slice }); edges.push( ...(await traceProcess( { @@ -635,7 +644,7 @@ export const traceDylibLoading = async ( facts.status === "parsed" ? facts.slices.map(withoutDependencies) : [], })), edges, - findings: deriveFindings(edges, roots, images), + findings: deriveFindings(edges, rootSlices), coverage: { status: unparsed.length === 0 && diff --git a/src/domain/apple/dylibResolutionFindings.ts b/src/domain/apple/dylibResolutionFindings.ts index e4cc1ddf2..eac488143 100644 --- a/src/domain/apple/dylibResolutionFindings.ts +++ b/src/domain/apple/dylibResolutionFindings.ts @@ -1,14 +1,18 @@ import type { DylibEdge as Edge, DylibFinding as Finding, - DylibTrace, - MachoImageFacts, + MachoSlice, } from "./dylibResolution.js"; +/** One traced process root with the exact slice it was traced from. */ +export interface TracedRootSlice { + readonly image: string; + readonly slice: MachoSlice; +} + export const deriveFindings = ( edges: readonly Edge[], - roots: DylibTrace["roots"], - images: ReadonlyMap, + roots: readonly TracedRootSlice[], ): Finding[] => { const findings: Finding[] = []; edges.forEach((edge, index) => { @@ -32,15 +36,11 @@ export const deriveFindings = ( explanation: `The modeled dyld search checks ${earlier.join(", ")} before ${edge.resolution.image ?? edge.install_name}. A compatible Mach-O placed at an earlier modeled path could take precedence over that fallback, subject to unmodeled search inputs and code-signing library validation; library validation is not evaluated here (see inspect_signature).${edge.loader_conditional ? " This loader loads only conditionally; if it never loads, this search never occurs." : ""}${edge.resolution.status === "conditional" ? " Unmodeled environment overrides or earlier unknown candidates may take precedence; placing an image at this rpath does not establish which image dyld will load." : ""}`, }); }); - for (const { image, architecture } of roots) { - const facts = images.get(image); - const slice = - facts?.status === "parsed" - ? facts.slices.find( - (candidate) => candidate.architecture === architecture, - ) - : undefined; - const environment = slice?.dyld_environment ?? []; + // Slices can share an architecture name (arm64e and arm64e.x1), so each + // finding uses the slice its root was traced from, not a name lookup. + for (const { image, slice } of roots) { + const { architecture } = slice; + const environment = slice.dyld_environment; if (environment.length > 0) findings.push({ kind: "dyld-environment-present", @@ -48,7 +48,7 @@ export const deriveFindings = ( image, basis: "derived", explanation: - slice?.file_type === "execute" + slice.file_type === "execute" ? `${image} (${architecture}) sets dyld environment variables through LC_DYLD_ENVIRONMENT (${environment.join(", ")}); any image-selection overrides they request are not modeled. Diagnostic settings alone do not alter resolution.` : `${image} (${architecture}) contains LC_DYLD_ENVIRONMENT (${environment.join(", ")}). Dyld reads these commands only from the main executable; entries in this non-executable root are observations and do not alter resolution.`, }); @@ -91,7 +91,7 @@ export const DYLIB_RESOLUTION_LIMITATIONS = [ "Slices are matched by dyld's graded architectures (an x86_64h process also loads x86_64). arm64e processes that disable pointer authentication can also load arm64 slices; that fallback is not modeled.", "Absolute install names and rpaths are outside the analyzed root and are not evaluated, including /System and /usr/lib libraries that the dyld shared cache usually provides.", "Leaf and relative install names depend on dyld fallback paths, DYLD_* variables, and the working directory; they are undetermined.", - "Load order follows dyld's dependents-first traversal in load-command order. An image reached through several chains is resolved once per process, with the rpath stack and conditionality of the first chain; a later request whose install name matches an already loaded image reuses it.", + "Load order follows dyld's dependents-first traversal in load-command order. An image reached through several chains is resolved once per process, with the rpath stack and conditionality of the first chain; a later @rpath request whose install name matches an already loaded image reuses it.", "@loader_path uses each image's symlink-resolved path within the analyzed root.", "Code-signing checks that can reject a found image, such as library validation and the hardened runtime, are not evaluated.", "Dylib compatibility versions are not compared. Apple's linker documentation describes a load-time rejection when an image's compatibility version is older than the loader requires, but dyld on macOS 26 was observed to load such an image.", diff --git a/src/domain/binaryTargetTypes.ts b/src/domain/binaryTargetTypes.ts index b4d44c110..ab5046549 100644 --- a/src/domain/binaryTargetTypes.ts +++ b/src/domain/binaryTargetTypes.ts @@ -1,3 +1,5 @@ +import type { ZipPackageFormat } from "./zipPackageFormat.js"; + /** Provider-neutral CPU families detected from supported executable headers. */ export const BINARY_ARCHITECTURES = [ "x86", @@ -167,18 +169,7 @@ export type BinaryTarget = | (BinaryTargetIdentity & NonExecutableMetadata & { readonly kind: "archive"; - readonly format: - | "zip" - | "ipa" - | "apk" - | "msix" - | "appx" - | "hap" - | "hsp" - | "app-pack" - | "asar" - | "dmg" - | "pkg"; + readonly format: ZipPackageFormat | "asar" | "dmg" | "pkg"; }) | (BinaryTargetIdentity & NonExecutableMetadata & { diff --git a/src/domain/captures/packetFields.ts b/src/domain/captures/packetFields.ts new file mode 100644 index 000000000..23b25cfcd --- /dev/null +++ b/src/domain/captures/packetFields.ts @@ -0,0 +1,100 @@ +import { z } from "zod"; +import { packetCaptureSchema } from "./packetCapture.js"; + +export const inspectPacketFieldsInputSchema = z.strictObject({ + kind: z + .enum(["protocols", "fields"]) + .default("protocols") + .describe( + "Return protocol registrations or field definitions; defaults to protocols", + ), + protocol: z + .string() + .min(1) + .max(8192) + .nullable() + .default(null) + .describe( + "Exact protocol abbreviation; selects that protocol or its registered fields", + ), + query: z + .string() + .max(8192) + .default("") + .describe( + "Case-insensitive literal substring in name, abbreviation or field description", + ), + offset: z + .number() + .int() + .nonnegative() + .max(Number.MAX_SAFE_INTEGER) + .default(0) + .describe("Number of matching records to skip; defaults to 0"), + limit: z + .number() + .int() + .positive() + .max(Number.MAX_SAFE_INTEGER) + .nullable() + .default(50) + .describe( + "Maximum matches returned; null requests all remaining within the record budget", + ), +}); +export type InspectPacketFieldsInput = z.infer< + typeof inspectPacketFieldsInputSchema +>; +export const packetFieldRecordSchema = z.strictObject({ + source_line: z.number().int().positive(), + kind: z.enum(["protocol", "field"]), + name: z.string(), + abbreviation: z.string(), + field_type: z.string().nullable(), + parent_protocol: z.string().nullable(), + display_base: z.string().nullable(), + bitmask: z.string().nullable(), + description: z.string().nullable(), +}); +export type PacketFieldRecord = z.infer; +export const packetFieldsCatalogSchema = z + .strictObject({ + selection: inspectPacketFieldsInputSchema, + records: z.array(packetFieldRecordSchema), + output_window: z.strictObject({ + examined: z.number().int().nonnegative(), + matching: z.number().int().nonnegative(), + returned: z.number().int().nonnegative(), + has_more: z.boolean(), + }), + diagnostics: z.string(), + tool: packetCaptureSchema.shape.tool, + resource_limiter: packetCaptureSchema.shape.resource_limiter, + limits: packetCaptureSchema.shape.limits.extend({ + record_budget_bytes: z.literal(8388608), + }), + configuration: z.literal("private-empty-personal-profile"), + hardware_acquisition: z.literal("not-performed"), + }) + .superRefine((report, context) => { + const w = report.output_window; + const remaining = Math.max(0, w.matching - report.selection.offset); + const expected = Math.min(remaining, report.selection.limit ?? remaining); + if ( + w.matching > w.examined || + w.returned !== expected || + report.records.length !== expected || + w.has_more !== remaining > expected || + report.records.some( + (row) => + row.kind !== + (report.selection.kind === "protocols" ? "protocol" : "field"), + ) + ) + context.addIssue({ + code: "custom", + path: ["output_window"], + message: + "Field discovery coverage must match the selected page and record kind", + }); + }); diff --git a/src/domain/changedBehavior.test.ts b/src/domain/changedBehavior.test.ts index cc19c4c50..6d99e828f 100644 --- a/src/domain/changedBehavior.test.ts +++ b/src/domain/changedBehavior.test.ts @@ -22,6 +22,9 @@ const source = (digit: string): Evidence => const left = source("1"); const right = source("2"); +const aggregate = (comparisons: readonly unknown[]) => + findChangedBehavior({ comparisons }); + const comparison = ( operation: "compare_process_captures" | "compare_artifacts", result: JsonValue, @@ -136,9 +139,9 @@ const expectInvalidSummary = (result: ChangedBehaviorResult): void => { describe("changed behavior", () => { it("accepts process comparison Evidence", () => { - const result = findChangedBehavior([ + const result = aggregate([ comparison("compare_process_captures", processResult()), - ]); + ]).result; expect(result.behavior_status).toBe("observed_unchanged"); }); @@ -152,7 +155,7 @@ describe("changed behavior", () => { }), ); - expect(findChangedBehavior([evidence])).toMatchObject({ + expect(aggregate([evidence]).result).toMatchObject({ behavior_status: "observed_changed", summary: { observed_changes: 2 }, findings: { @@ -172,7 +175,7 @@ describe("changed behavior", () => { "compare_process_captures", processResult({ status: "changed", terminal: "changed" }), ); - const result = findChangedBehavior([evidence]); + const result = aggregate([evidence]).result; expect(changedBehaviorResultSchema.parse(result)).toMatchObject({ behavior_status: "observed_changed", summary: { observed_changes: 1, static_candidates: 0 }, @@ -193,7 +196,7 @@ describe("changed behavior", () => { it("keeps static differences as candidates, never runtime observations", () => { const evidence = comparison("compare_artifacts", artifactResult()); - const result = findChangedBehavior([evidence]); + const result = aggregate([evidence]).result; expect(result).toMatchObject({ behavior_status: "unknown", summary: { observed_changes: 0, static_candidates: 1 }, @@ -217,17 +220,17 @@ describe("changed behavior", () => { "compare_process_captures", processResult({ status: "unknown", exit: "unknown" }), ); - const result = findChangedBehavior([changed, unknown]); + const result = aggregate([changed, unknown]).result; expect(result).toMatchObject({ behavior_status: "unknown", findings: { items: expect.any(Array) }, }); - expect(findChangedBehavior([changed, unknown])).toEqual(result); + expect(aggregate([changed, unknown]).result).toEqual(result); }); it("uses complete inline artifact deltas as static candidates", () => { const complete = comparison("compare_artifacts", artifactResult()); - expect(findChangedBehavior([complete]).findings.items).toEqual( + expect(aggregate([complete]).result.findings.items).toEqual( expect.arrayContaining([ expect.objectContaining({ dimension: "artifact:main.js" }), ]), @@ -236,7 +239,7 @@ describe("changed behavior", () => { it("rejects bundles, duplicate comparisons, and malformed exact results", () => { const valid = comparison("compare_process_captures", processResult()); - expect(() => findChangedBehavior([valid, valid])).toThrow( + expect(() => aggregate([valid, valid])).toThrow( /duplicate comparison Evidence/u, ); const bundle = createEvidence( @@ -252,25 +255,25 @@ describe("changed behavior", () => { evidenceLinks: [left.evidence_id, right.evidence_id], }, ); - expect(() => findChangedBehavior([bundle])).toThrow( + expect(() => aggregate([bundle])).toThrow( /requires process, artifact, or function/u, ); const malformed = comparison("compare_process_captures", { status: "unchanged", }); - expect(() => findChangedBehavior([malformed])).toThrow(); + expect(() => aggregate([malformed])).toThrow(); const contradictory = comparison( "compare_process_captures", processResult({ status: "unchanged", terminal: "changed" }), ); - expect(() => findChangedBehavior([contradictory])).toThrow( + expect(() => aggregate([contradictory])).toThrow( /contradicts its dimensions/u, ); const danglingNested = comparison( "compare_artifacts", artifactResult([`ev_${"f".repeat(64)}`, right.evidence_id]), ); - expect(() => findChangedBehavior([danglingNested])).toThrow( + expect(() => aggregate([danglingNested])).toThrow( /outside its top-level closure/u, ); }); @@ -299,10 +302,15 @@ describe("changed behavior aggregation", () => { ), ); - const result = findChangedBehavior(comparisons); + const result = aggregate(comparisons); - expect(result.summary.observed_changes).toBe(comparisons.length); - expect(result.evidence_links).toHaveLength(comparisons.length * 201 + 2); - expect(result.findings.items[0]?.evidence_links).toHaveLength(203); + expect(result.result.summary.observed_changes).toBe(comparisons.length); + expect(result.result.evidence_links).toHaveLength( + comparisons.length * 201 + 2, + ); + expect(result.result.findings.items[0]?.evidence_links).toHaveLength(203); + expect(result.comparisonEvidenceIds).toEqual( + comparisons.map(({ evidence_id }) => evidence_id), + ); }); }); diff --git a/src/domain/changedBehavior.ts b/src/domain/changedBehavior.ts index b785cdd23..56e9b6ad9 100644 --- a/src/domain/changedBehavior.ts +++ b/src/domain/changedBehavior.ts @@ -91,6 +91,22 @@ export const changedBehaviorResultSchema = z export type ChangedBehaviorResult = z.infer; type Finding = z.infer; type RuntimeStatus = z.infer["status"]; +type ParsedComparison = + | { + readonly operation: "compare_process_captures"; + readonly evidence: Evidence; + readonly result: z.infer; + } + | { + readonly operation: "compare_functions"; + readonly evidence: Evidence; + readonly result: z.infer; + } + | { + readonly operation: "compare_artifacts"; + readonly evidence: Evidence; + readonly result: z.infer; + }; const EXPECTED_PROVIDERS = { compare_process_captures: { @@ -117,24 +133,37 @@ const acceptsPredicate = ( ): boolean => expected.some((predicate) => predicate === actual); /** Find observed runtime changes and separately report static change candidates. */ -export const findChangedBehavior = ( - comparisonsInput: unknown, -): ChangedBehaviorResult => { - const parsedInput = changedBehaviorInputSchema.parse({ - comparisons: comparisonsInput, - }); - const comparisons = parsedInput.comparisons; +interface FoundChangedBehavior { + readonly result: ChangedBehaviorResult; + /** Authenticated IDs retained from the comparisons used to compute result. */ + readonly comparisonEvidenceIds: readonly string[]; +} + +export const findChangedBehavior = (input: unknown): FoundChangedBehavior => { + // The public input schema remains available to clients; this internal + // admission only checks the list shape because parseEvidence below owns + // validation and authentication of each retained Evidence item. + const { comparisons } = z + .strictObject({ comparisons: z.array(z.unknown()).min(1) }) + .parse(input); const evidence = comparisons.map(parseComparisonEvidence); assertUnique( - evidence.map(({ evidence_id: id }) => id), + evidence.map(({ evidence: { evidence_id: id } }) => id), "comparison Evidence", ); const findings = evidence.flatMap(findingsFor).sort(compareFindings); - const runtimeStatuses = evidence.flatMap(runtimeStatus); - const links = uniqueSorted( - evidence.flatMap((item) => [item.evidence_id, ...item.evidence_links]), + const runtimeStatuses = evidence.flatMap((comparison) => + comparison.operation === "compare_process_captures" + ? [comparison.result.status] + : [], ); - return changedBehaviorResultSchema.parse({ + const links = uniqueSorted( + evidence.flatMap(({ evidence: item }) => [ + item.evidence_id, + ...item.evidence_links, + ]), + ); + const result = changedBehaviorResultSchema.parse({ behavior_status: behaviorStatus(runtimeStatuses), summary: { observed_changes: count(findings, "observed_change"), @@ -147,7 +176,7 @@ export const findChangedBehavior = ( }, evidence_links: links, limitations: uniqueSorted([ - ...evidence.flatMap(({ limitations }) => limitations), + ...evidence.flatMap(({ evidence: item }) => item.limitations), ...(evidence.some( ({ operation }) => operation !== "compare_process_captures", ) @@ -160,9 +189,15 @@ export const findChangedBehavior = ( : []), ]), }); + return { + result, + comparisonEvidenceIds: evidence.map( + ({ evidence: { evidence_id } }) => evidence_id, + ), + }; }; -const parseComparisonEvidence = (input: unknown): Evidence => { +const parseComparisonEvidence = (input: unknown): ParsedComparison => { const evidence = parseEvidence(input); if (!(evidence.operation in EXPECTED_PROVIDERS)) throw new TypeError( @@ -198,12 +233,17 @@ const parseComparisonEvidence = (input: unknown): Evidence => { throw new TypeError( "Comparison Evidence must cite both selected source observations", ); - parseResult(evidence); - return evidence; + return parseResult(evidence, operation); }; -const parseResult = (evidence: Evidence): void => { - if (evidence.operation === "compare_process_captures") { +const parseResult = ( + evidence: Evidence, + operation: + | "compare_process_captures" + | "compare_artifacts" + | "compare_functions", +): ParsedComparison => { + if (operation === "compare_process_captures") { const result = processCaptureComparisonSchema.parse( evidence.normalized_result, ); @@ -214,9 +254,9 @@ const parseResult = (evidence: Evidence): void => { throw new TypeError( "Process comparison status contradicts its dimensions", ); - return; + return { operation, evidence, result }; } - if (evidence.operation === "compare_functions") { + if (operation === "compare_functions") { const result = functionComparisonResultSchema.parse( evidence.normalized_result, ); @@ -224,7 +264,7 @@ const parseResult = (evidence: Evidence): void => { evidence, result.dimensions.flatMap(({ evidence_links: links }) => links), ); - return; + return { operation, evidence, result }; } const result = artifactComparisonResultSchema.parse( evidence.normalized_result, @@ -233,6 +273,7 @@ const parseResult = (evidence: Evidence): void => { evidence, result.changes.flatMap(({ evidence_links: links }) => links), ); + return { operation, evidence, result }; }; const assertNestedLinks = ( @@ -246,18 +287,21 @@ const assertNestedLinks = ( ); }; -const findingsFor = (evidence: Evidence): Finding[] => { - if (evidence.operation === "compare_process_captures") - return processFindings(evidence); - if (evidence.operation === "compare_functions") - return functionFindings(evidence); - return artifactFindings(evidence); +const findingsFor = (comparison: ParsedComparison): Finding[] => { + if (comparison.operation === "compare_process_captures") + return processFindings(comparison); + if (comparison.operation === "compare_functions") + return functionFindings(comparison); + return artifactFindings(comparison); }; -const processFindings = (evidence: Evidence): Finding[] => { - const result = processCaptureComparisonSchema.parse( - evidence.normalized_result, - ); +const processFindings = ( + comparison: Extract< + ParsedComparison, + { readonly operation: "compare_process_captures" } + >, +): Finding[] => { + const { evidence, result } = comparison; const dimensions = [ ["terminal", result.terminal, "runtime"], ["interaction", result.interaction, "runtime"], @@ -283,10 +327,13 @@ const processFindings = (evidence: Evidence): Finding[] => { ); }; -const functionFindings = (evidence: Evidence): Finding[] => { - const result = functionComparisonResultSchema.parse( - evidence.normalized_result, - ); +const functionFindings = ( + comparison: Extract< + ParsedComparison, + { readonly operation: "compare_functions" } + >, +): Finding[] => { + const { evidence, result } = comparison; return result.dimensions.flatMap((dimension) => dimension.status === "unchanged" ? [] @@ -307,10 +354,13 @@ const functionFindings = (evidence: Evidence): Finding[] => { ); }; -const artifactFindings = (evidence: Evidence): Finding[] => { - const result = artifactComparisonResultSchema.parse( - evidence.normalized_result, - ); +const artifactFindings = ( + comparison: Extract< + ParsedComparison, + { readonly operation: "compare_artifacts" } + >, +): Finding[] => { + const { evidence, result } = comparison; const changes = result.changes.map((change) => makeFinding({ evidence, @@ -367,11 +417,6 @@ const makeFinding = (input: { limitations: uniqueSorted(input.limitations), }); -const runtimeStatus = (evidence: Evidence): RuntimeStatus[] => - evidence.operation === "compare_process_captures" - ? [processCaptureComparisonSchema.parse(evidence.normalized_result).status] - : []; - const behaviorStatus = ( statuses: readonly RuntimeStatus[], ): ChangedBehaviorResult["behavior_status"] => { diff --git a/src/domain/evidence.test.ts b/src/domain/evidence.test.ts index c5898aecc..5cdf30a27 100644 --- a/src/domain/evidence.test.ts +++ b/src/domain/evidence.test.ts @@ -52,6 +52,30 @@ it("preserves omitted relationship diagnostics and authenticates reported diagno ).toThrow("semantic identifier"); }); +it("projects known provider fields and preserves open JSON payloads", () => { + const liveProvider = { ...PROVIDER, transient_status: "starting" }; + const evidence = createEvidence(TARGET, liveProvider, { + operation: "inspect", + parameters: { caller_metadata: { note: "kept" } }, + result: { producer_extension: { value: "kept" } }, + analysisProfile: PROFILE, + environment: { + id: "fixture", + platform: "linux", + architecture: "x86_64", + isolation: "process", + }, + locations: [{ kind: "address", address: "0x1000" }], + }); + + expect(evidence.provider).toEqual(PROVIDER); + expect(evidence.parameters).toEqual({ caller_metadata: { note: "kept" } }); + expect(evidence.normalized_result).toEqual({ + producer_extension: { value: "kept" }, + }); + expect(parseEvidence(evidence)).toEqual(evidence); +}); + it("preserves identity and bytes when reusing an owned immutable result", () => { const value = { nested: { values: ["observed", 1] } }; const mutable = createEvidence(TARGET, PROVIDER, { diff --git a/src/domain/evidence.ts b/src/domain/evidence.ts index 8e21686e5..8a450f478 100644 --- a/src/domain/evidence.ts +++ b/src/domain/evidence.ts @@ -33,14 +33,14 @@ import { } from "./relationshipCoverage.js"; /** Provider identity schema shared by evidence-bearing persistence formats. */ -export const providerSchema = z.object({ +export const providerSchema = z.strictObject({ id: z.string().min(1), name: z.string().min(1), version: z.string().nullable(), }); -const subjectSchema = z.object({ +const subjectSchema = z.strictObject({ name: z.string().min(1), - digest: z.object({ sha256: digestSchema }), + digest: z.strictObject({ sha256: digestSchema }), format: z.enum([ "hopper", "analysis-database", @@ -77,15 +77,18 @@ const subjectSchema = z.object({ /** Source location attached to an evidence observation. */ /** Source-location schema shared by evidence-bearing persistence formats. */ export const evidenceLocationSchema = z.discriminatedUnion("kind", [ - z.object({ kind: z.literal("address"), address: z.string().min(1) }), - z.object({ + z.strictObject({ kind: z.literal("address"), address: z.string().min(1) }), + z.strictObject({ kind: z.literal("address-range"), start: z.string().min(1), end: z.string().min(1), }), - z.object({ kind: z.literal("artifact-path"), path: z.string().min(1) }), - z.object({ kind: z.literal("file-offset"), offset: z.number().int().min(0) }), - z.object({ + z.strictObject({ kind: z.literal("artifact-path"), path: z.string().min(1) }), + z.strictObject({ + kind: z.literal("file-offset"), + offset: z.number().int().min(0), + }), + z.strictObject({ kind: z.literal("file-offset-range"), start: z.number().int().min(0), end: z.number().int().min(0), @@ -100,7 +103,7 @@ const evidenceAuthoritySchema = z.enum([ "analyst-inference", ]); -const executionEnvironmentSchema = z.object({ +const executionEnvironmentSchema = z.strictObject({ id: z.string().min(1), platform: z.string().min(1), architecture: z.string().min(1), diff --git a/src/domain/evidenceBundle.ts b/src/domain/evidenceBundle.ts index c1fa3ce1c..7e6fd2b3b 100644 --- a/src/domain/evidenceBundle.ts +++ b/src/domain/evidenceBundle.ts @@ -16,24 +16,27 @@ import { } from "./residualUnknown.js"; import { freezeJsonSnapshot } from "./immutableJson.js"; -const artifactManifestSchema = evidenceSchema.shape.subject.unwrap().pick({ - digest: true, - format: true, - architecture: true, -}); +const artifactManifestSchema = evidenceSchema.shape.subject + .unwrap() + .pick({ + digest: true, + format: true, + architecture: true, + }) + .strict(); const providerManifestSchema = providerSchema; const environmentManifestSchema = evidenceSchema.shape.environment.unwrap(); -const scenarioManifestSchema = z.object({ +const scenarioManifestSchema = z.strictObject({ evidence_id: evidenceSchema.shape.evidence_id, operation: z.string().min(1), authority: z.literal("controlled-replay"), }); -const captureManifestSchema = z.object({ +const captureManifestSchema = z.strictObject({ evidence_id: evidenceSchema.shape.evidence_id, predicate_type: z.string().min(1), }); -export const evidenceBundleSchema = z.object({ +export const evidenceBundleSchema = z.strictObject({ artifacts: z.array(artifactManifestSchema), providers: z.array(providerManifestSchema), environments: z.array(environmentManifestSchema), diff --git a/src/domain/explicitSensitiveFailure.test.ts b/src/domain/explicitSensitiveFailure.test.ts index 68aaf9f8f..757e9887a 100644 --- a/src/domain/explicitSensitiveFailure.test.ts +++ b/src/domain/explicitSensitiveFailure.test.ts @@ -116,6 +116,24 @@ it("keeps unsupported profile reasons distinct from malformed input", () => { expect(JSON.stringify(projectAnalysisError(result))).not.toContain("private"); }); +it("preserves a retryable capability failure through explicit-value redaction", () => { + // Retryability is a semantic field of the error, not presentation: dropping + // it turns a transient admission failure into a permanent one and changes + // the remediation the caller is shown. + const error = new AnalysisCapabilityUnavailableError( + "mitmproxy", + "inspect_web_network_capture", + "Runtime admission for /targets/private/capture failed transiently", + { retryable: true }, + ); + expect(projectAnalysisError(error).retryable).toBe(true); + const result = redactExplicitFailure(error, ["private"]); + expect(result).toBeInstanceOf(AnalysisCapabilityUnavailableError); + expect((result as AnalysisCapabilityUnavailableError).retryable).toBe(true); + expect(projectAnalysisError(result).retryable).toBe(true); + expect(JSON.stringify(projectAnalysisError(result))).not.toContain("private"); +}); + it("coarsens format issue pointers without creating replacement coordinates", () => { const error = new AnalysisInputError( "inspect_web_network_capture", diff --git a/src/domain/explicitSensitiveFailure.ts b/src/domain/explicitSensitiveFailure.ts index 05a4f2f88..8a0fac095 100644 --- a/src/domain/explicitSensitiveFailure.ts +++ b/src/domain/explicitSensitiveFailure.ts @@ -154,6 +154,7 @@ export const redactExplicitFailure = ( ...(error.userMessage === undefined ? {} : { userMessage: text(error.userMessage) }), + ...(error.retryable ? { retryable: true } : {}), }, ); if (error instanceof AnalysisResourceConstraintError) diff --git a/src/domain/flutter/flutterBuildAnalysis.ts b/src/domain/flutter/flutterBuildAnalysis.ts index 068149f68..10c5b7b00 100644 --- a/src/domain/flutter/flutterBuildAnalysis.ts +++ b/src/domain/flutter/flutterBuildAnalysis.ts @@ -30,6 +30,12 @@ export const flutterInputSchemas = { }), } as const; +/** Retained delivery is selected independently of the provider's ABI request. */ +export const dartAotInspectionInputSchema = + flutterInputSchemas.inspect_dart_aot.extend({ + detail: z.enum(["complete", "summary"]).optional(), + }); + /** Supported Flutter-backed operations. */ export type FlutterOperation = keyof typeof flutterInputSchemas; /** Validated Flutter requests carry their selected operation. */ diff --git a/src/domain/functionComparison.test.ts b/src/domain/functionComparison.test.ts index acb505dac..e03a27748 100644 --- a/src/domain/functionComparison.test.ts +++ b/src/domain/functionComparison.test.ts @@ -119,6 +119,34 @@ const observe = ( ); describe("function comparison normalized identity", () => { + it("keeps differing generated names ambiguous and stable names mismatched", () => { + const named = (base: "0x1000" | "0x2000", name: string) => + functionDossierSchema.parse({ + ...dossier("return 0;", base), + procedure: { + ...procedure(base, name), + signature: "int helper(void)", + locals: [], + }, + }); + const generated = compareFunctions( + observe("1", named("0x1000", "sub_1000")), + observe("2", named("0x2000", "sub_2000")), + ); + expect(generated.function_match.status).toBe("ambiguous"); + expect(generated.status).toBe("unknown"); + expect( + generated.dimensions.find(({ dimension }) => dimension === "identity"), + ).toMatchObject({ status: "unknown" }); + + const stable = compareFunctions( + observe("3", named("0x1000", "firstFunction")), + observe("4", named("0x2000", "secondFunction")), + ); + expect(stable.function_match.status).toBe("mismatched"); + expect(stable.status).toBe("changed"); + }); + it.each(["sub_deallocate", "sub_deadbeef_handler", "fcn.dispatch"])( "recognizes the explicit symbol %s without a generated-name prefix false positive", (name) => { diff --git a/src/domain/functionComparisonNormalization.ts b/src/domain/functionComparisonNormalization.ts index a676e1e49..5282272e1 100644 --- a/src/domain/functionComparisonNormalization.ts +++ b/src/domain/functionComparisonNormalization.ts @@ -16,24 +16,21 @@ export const functionMatch = ( left: FunctionSnapshot, right: FunctionSnapshot, ): FunctionComparisonResult["function_match"] => { - if ( - !isAutoName(left.dossier.procedure.name) && - left.dossier.procedure.name === right.dossier.procedure.name - ) + const leftName = left.dossier.procedure.name; + const rightName = right.dossier.procedure.name; + const stableNames = !isAutoName(leftName) && !isAutoName(rightName); + if (stableNames && leftName === rightName) return { status: "matched", method: "symbol", - left_name: left.dossier.procedure.name, - right_name: right.dossier.procedure.name, + left_name: leftName, + right_name: rightName, }; return { - status: - left.dossier.procedure.name === right.dossier.procedure.name - ? "ambiguous" - : "mismatched", + status: stableNames ? "mismatched" : "ambiguous", method: "explicit", - left_name: left.dossier.procedure.name, - right_name: right.dossier.procedure.name, + left_name: leftName, + right_name: rightName, }; }; diff --git a/src/domain/hopperValues.test.ts b/src/domain/hopperValues.test.ts index 7af5df704..c5931cd35 100644 --- a/src/domain/hopperValues.test.ts +++ b/src/domain/hopperValues.test.ts @@ -8,7 +8,6 @@ import { parseNames, parseProcedures, parseRelatedAddresses, - parseSegmentImageBase, parseSegments, } from "./hopperValues.js"; @@ -66,19 +65,6 @@ describe("Hopper boundary values", () => { ok: true, value: ["fixture"], }); - expect( - parseSegmentImageBase([ - { image_base: "0x100000" }, - { image_base: "0x100000" }, - ]), - ).toBe("0x100000"); - expect( - parseSegmentImageBase([ - { image_base: "0x100000" }, - { image_base: "0x200000" }, - ]), - ).toBeUndefined(); - expect(parseSegmentImageBase([{ name: "__TEXT" }])).toBeUndefined(); }); it.each([ diff --git a/src/domain/hopperValues.ts b/src/domain/hopperValues.ts index 5e5a3987b..769d0f040 100644 --- a/src/domain/hopperValues.ts +++ b/src/domain/hopperValues.ts @@ -20,6 +20,8 @@ export interface SegmentSummary { readonly readable: boolean | null; readonly writable: boolean | null; readonly executable: boolean | null; + readonly image_base?: string; + readonly address_space?: string; } /** Return a bounded byte distance between canonical addresses in one space. */ @@ -58,10 +60,9 @@ const segmentSchema = z.object({ readable: z.boolean().nullable(), writable: z.boolean().nullable(), executable: z.boolean().nullable(), + image_base: z.string().min(1).exactOptional(), + address_space: z.string().min(1).exactOptional(), }); -const segmentImageBaseSchema = z - .object({ image_base: z.string().min(1) }) - .passthrough(); const unavailableAnalysisFactSchema = z .object({ available: z.literal(false), reason: z.string() }) .strict(); @@ -415,7 +416,7 @@ export const parseRelatedAddresses = ( : invalid(`${relation} list`, parsed.error); }; -/** Parse direct or wrapped Hopper segment records. */ +/** Preserve reported address context in direct or wrapped provider segments. */ export const parseSegments = ( value: JsonValue, ): Result => { @@ -427,14 +428,15 @@ export const parseSegments = ( : invalid("segment list", parsed.error); }; -/** Return a provider-reported image base only when every segment agrees on it. */ -export const parseSegmentImageBase = (value: JsonValue): string | undefined => { - const parsed = z - .array(segmentImageBaseSchema) - .safeParse(unwrapProperty(value, "segments")); - if (!parsed.success) return undefined; - const bases = new Set(parsed.data.map(({ image_base }) => image_base)); - return bases.size === 1 ? parsed.data[0]?.image_base : undefined; +/** Return a reported overview base only when every parsed segment agrees. */ +export const parseSegmentImageBase = ( + segments: readonly SegmentSummary[], +): string | undefined => { + const base = segments[0]?.image_base; + return base !== undefined && + segments.every((segment) => segment.image_base === base) + ? base + : undefined; }; /** Parse direct or wrapped Hopper document names. */ diff --git a/src/domain/javascript/javascriptApplicationGraph.fixture.ts b/src/domain/javascript/javascriptApplicationGraph.fixture.ts index 3002b822f..0e78e5115 100644 --- a/src/domain/javascript/javascriptApplicationGraph.fixture.ts +++ b/src/domain/javascript/javascriptApplicationGraph.fixture.ts @@ -6,6 +6,7 @@ import { } from "./javascriptApplicationGraph.js"; import type { ApplicationNode } from "./javascriptApplicationGraphSchemas.js"; import type { ApplicationGraphEvidence } from "./javascriptApplicationEvidenceSchemas.js"; +import { resolveJavaScriptSourceMapReferences } from "./javascriptSourceMapPaths.js"; export const APPLICATION_GRAPH_DIGESTS = { package: "1".repeat(64), @@ -22,6 +23,20 @@ export const completeCoverage = { limits: [], } satisfies ApplicationGraphEvidence["coverage"]; +export const sourceMapReference = ( + sourceName: string, + sourceRoot: string | null, + mapPath: string, +) => { + const reference = resolveJavaScriptSourceMapReferences( + [sourceName], + sourceRoot, + mapPath, + )[0]; + if (reference == null) throw new TypeError("Expected a source-map reference"); + return reference; +}; + const extractor = (operation: string) => ({ name: "rea-test-fixture", version: "1.0.0", diff --git a/src/domain/javascript/javascriptApplicationGraph.test.ts b/src/domain/javascript/javascriptApplicationGraph.test.ts index 5e396a545..5bf917480 100644 --- a/src/domain/javascript/javascriptApplicationGraph.test.ts +++ b/src/domain/javascript/javascriptApplicationGraph.test.ts @@ -20,10 +20,9 @@ import { inferredArtifactEvidence, nodeByLabel, runtimeEvidence, + sourceMapReference, unknownEvidence, } from "./javascriptApplicationGraph.fixture.js"; - -import { resolveJavaScriptSourceMapReference } from "./javascriptSourceMapPaths.js"; const createLargeNativeExportGraph = (): JavaScriptApplicationGraph => { const properties = Object.fromEntries( Array.from({ length: 1_001 }, (_, index) => [ @@ -438,7 +437,7 @@ describe("JavaScript Application Graph: source maps and observations", () => { observations: [ { label: "src/editor.ts", - source_map_reference: resolveJavaScriptSourceMapReference( + source_map_reference: sourceMapReference( "webpack:///src/editor.ts", null, "dist/app.js.map", @@ -535,7 +534,7 @@ describe("JavaScript Application Graph: source-map digest consistency", () => { observations: [ { label: null, - source_map_reference: resolveJavaScriptSourceMapReference( + source_map_reference: sourceMapReference( "src/editor.ts", null, "dist/app.js.map", diff --git a/src/domain/javascript/javascriptBundlerRegistrationIdentity.test.ts b/src/domain/javascript/javascriptBundlerRegistrationIdentity.test.ts new file mode 100644 index 000000000..1b251e313 --- /dev/null +++ b/src/domain/javascript/javascriptBundlerRegistrationIdentity.test.ts @@ -0,0 +1,78 @@ +import { expect, it } from "vitest"; +import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js"; + +const registration = (runtime: string, callback: string, chunk = 1) => + "(globalThis." + + runtime + + " = globalThis." + + runtime + + " || []).push([[" + + chunk + + "], {a: function() {}}, " + + callback + + "]);"; + +it.each(["webpackChunkFixture", "rspackChunkFixture"])( + "keeps differing callback facts for %s independent of source order", + (runtime) => { + const first = registration( + runtime, + 'function(r) { r(7); r.e("chunk-a"); }', + ); + const second = registration( + runtime, + 'function(r) { r(8); r.e("chunk-b"); }', + ); + for (const source of [first + "\n" + second, second + "\n" + first]) { + const result = analyzeJavaScriptStaticSource(source); + expect(result.parse_status).toBe("complete"); + expect(result.bundler_registrations).toHaveLength(2); + expect( + result.bundler_registrations.flatMap((r) => r.entry_module_keys).sort(), + ).toEqual(["7", "8"]); + expect( + result.bundler_registrations.flatMap((r) => r.async_chunk_keys).sort(), + ).toEqual(["chunk-a", "chunk-b"]); + } + expect( + analyzeJavaScriptStaticSource(first + "\n" + first).bundler_registrations, + ).toHaveLength(1); + expect( + analyzeJavaScriptStaticSource(first).bundler_registrations[0], + ).toMatchObject({ + entry_module_keys: ["7"], + async_chunk_keys: ["chunk-a"], + }); + expect( + analyzeJavaScriptStaticSource(second).bundler_registrations[0], + ).toMatchObject({ + entry_module_keys: ["8"], + async_chunk_keys: ["chunk-b"], + }); + }, +); + +it.each([ + ["function(r) { r(7); }", "function(r) { r(8); }"], + ['function(r) { r.e("a"); }', 'function(r) { r.e("b"); }'], + ["function(r) {}", "function(s) {}"], + ["function(r) {}", "function(r) { r(dynamic); }"], + ["function(r) {}", "function(r) { r.e(dynamic); }"], +])("retains callback metadata differences: %s / %s", (left, right) => { + const result = analyzeJavaScriptStaticSource( + registration("webpackChunkFixture", left) + + "\n" + + registration("webpackChunkFixture", right), + ); + expect(result.bundler_registrations).toHaveLength(2); +}); + +it("retains distinct chunk identities with identical callbacks", () => { + const callback = "function(r) { r(7); }"; + const result = analyzeJavaScriptStaticSource( + registration("webpackChunkFixture", callback, 1) + + "\n" + + registration("webpackChunkFixture", callback, 2), + ); + expect(result.bundler_registrations).toHaveLength(2); +}); diff --git a/src/domain/javascript/javascriptModuleDeclaration.ts b/src/domain/javascript/javascriptModuleDeclaration.ts new file mode 100644 index 000000000..d7a8d6754 --- /dev/null +++ b/src/domain/javascript/javascriptModuleDeclaration.ts @@ -0,0 +1,60 @@ +import * as t from "@babel/types"; + +/** Whether TypeScript explicitly erases this entire import declaration. */ +export const isTypeOnlyImportDeclaration = ( + node: t.ImportDeclaration, +): boolean => node.importKind === "type" || node.importKind === "typeof"; + +/** Whether TypeScript explicitly erases this entire export declaration. */ +export const isTypeOnlyExportDeclaration = ( + node: t.ExportNamedDeclaration | t.ExportAllDeclaration, +): boolean => + node.exportKind === "type" || + (t.isExportNamedDeclaration(node) && + node.declaration !== null && + (t.isTSInterfaceDeclaration(node.declaration) || + t.isTSTypeAliasDeclaration(node.declaration) || + t.isTSDeclareFunction(node.declaration))); + +/** Whether this import binding is explicitly type-only. */ +export const isTypeOnlyImportSpecifier = (node: t.ImportSpecifier): boolean => + node.importKind === "type" || node.importKind === "typeof"; + +/** Whether this exported binding is explicitly type-only. */ +export const isTypeOnlyExportSpecifier = (node: t.ExportSpecifier): boolean => + node.exportKind === "type"; + +/** A regular import whose bindings are all erased but may retain side effects. */ +export const hasOnlyInlineTypeImportSpecifiers = ( + node: t.ImportDeclaration, +): boolean => + !isTypeOnlyImportDeclaration(node) && + node.specifiers.length > 0 && + node.specifiers.every( + (specifier) => + t.isImportSpecifier(specifier) && isTypeOnlyImportSpecifier(specifier), + ); + +/** A regular re-export whose bindings are all erased but may retain side effects. */ +export const hasOnlyInlineTypeExportSpecifiers = ( + node: t.ExportNamedDeclaration, +): boolean => + !isTypeOnlyExportDeclaration(node) && + node.source != null && + node.specifiers.length > 0 && + node.specifiers.every( + (specifier) => + t.isExportSpecifier(specifier) && isTypeOnlyExportSpecifier(specifier), + ); + +/** Whether compiler options leave an inline type-only declaration's side effect unknown. */ +export const hasUncertainTypeOnlyModuleSideEffect = ( + program: t.Program, +): boolean => + program.body.some( + (node) => + (t.isImportDeclaration(node) && + hasOnlyInlineTypeImportSpecifiers(node)) || + (t.isExportNamedDeclaration(node) && + hasOnlyInlineTypeExportSpecifiers(node)), + ); diff --git a/src/domain/javascript/javascriptModuleResolutionMode.ts b/src/domain/javascript/javascriptModuleResolutionMode.ts new file mode 100644 index 000000000..d14b91bd9 --- /dev/null +++ b/src/domain/javascript/javascriptModuleResolutionMode.ts @@ -0,0 +1,23 @@ +import { posix } from "node:path"; + +/** Loader evidence retained for a source-level module reference. */ +export type JavaScriptModuleResolutionMode = + | "import" + | "require" + | "compiler-dependent"; + +/** Derive source mode only when syntax or an explicit source format owns it. */ +export const moduleResolutionModeForJavaScriptReference = ( + sourcePath: string, + referenceKind: "static-import" | "dynamic-import" | "require", + explicitMode?: JavaScriptModuleResolutionMode, +): JavaScriptModuleResolutionMode => { + if (explicitMode !== undefined) return explicitMode; + if (referenceKind === "require") return "require"; + if (referenceKind === "dynamic-import") return "import"; + const extension = posix.extname(sourcePath).toLowerCase(); + if (extension === ".cts") return "require"; + if (extension === ".mts") return "import"; + if (extension === ".ts" || extension === ".tsx") return "compiler-dependent"; + return "import"; +}; diff --git a/src/domain/javascript/javascriptModuleSpecifier.ts b/src/domain/javascript/javascriptModuleSpecifier.ts new file mode 100644 index 000000000..f52f081dc --- /dev/null +++ b/src/domain/javascript/javascriptModuleSpecifier.ts @@ -0,0 +1,6 @@ +/** Relative module syntax differs from an arbitrary dot-prefixed filename. */ +export const isRelativeJavaScriptModuleSpecifier = (value: string): boolean => + value === "." || + value === ".." || + value.startsWith("./") || + value.startsWith("../"); diff --git a/src/domain/javascript/javascriptRuntimeStaticCandidates.ts b/src/domain/javascript/javascriptRuntimeStaticCandidates.ts index 1f02c820d..810ab7f5e 100644 --- a/src/domain/javascript/javascriptRuntimeStaticCandidates.ts +++ b/src/domain/javascript/javascriptRuntimeStaticCandidates.ts @@ -1,4 +1,4 @@ -import { posix, relative, win32 } from "node:path"; +import { posix, win32 } from "node:path"; import type { ApplicationNode } from "./javascriptApplicationGraphSchemas.js"; import type { JavaScriptApplicationGraph } from "./javascriptApplicationGraph.js"; @@ -216,7 +216,7 @@ const pathBelowRoot = (root: string, value: string): string | null => { const remainder = rootStyle === "windows" ? win32.relative(root, value) - : relative(root, value); + : posix.relative(root, value); const portableRemainder = remainder.replaceAll("\\", "/"); if ( remainder === "" || diff --git a/src/domain/javascript/javascriptSemanticAnalysis.require_links.test.ts b/src/domain/javascript/javascriptSemanticAnalysis.require_links.test.ts index 333ad4f9c..a0d93c3c3 100644 --- a/src/domain/javascript/javascriptSemanticAnalysis.require_links.test.ts +++ b/src/domain/javascript/javascriptSemanticAnalysis.require_links.test.ts @@ -22,6 +22,11 @@ describe("TypeScript import-equals links", () => { localName: "dependency", exportedName: null, }), + expect.objectContaining({ + kind: "type-import", + specifier: "./types", + localName: "types", + }), ]); }); @@ -51,6 +56,57 @@ describe("TypeScript import-equals links", () => { }); }); +describe("TypeScript type-only module links", () => { + it("retains declarations without runtime bindings or callable claims", () => { + const ir = analyzeJavaScriptSemantics(` + import type { Whole } from "./whole"; + import { type Inline } from "./inline"; + import { type Erased, value } from "./mixed"; + export type { Reexported } from "./reexported"; + export { type InlineExport } from "./inline-export"; + export type LocalType = string; + export interface LocalInterface { value: string } + function hiddenFunction() { return 1; } + export type { hiddenFunction }; + `); + + const externalLinks = ir.moduleLinks + .filter(({ specifier }) => specifier !== null) + .map( + ({ kind, specifier, importedName, exportedName }) => + [kind, specifier, importedName, exportedName] as const, + ); + expect(externalLinks).toEqual([ + ["type-import", "./whole", "Whole", null], + ["type-import", "./inline", "Inline", null], + ["type-import", "./mixed", "Erased", null], + ["import", "./mixed", "value", null], + ["type-import", "./reexported", "Reexported", "Reexported"], + ["type-import", "./inline-export", "InlineExport", "InlineExport"], + ]); + + const typeLinks = ir.moduleLinks + .filter(({ kind }) => kind === "type-import") + .map( + ({ specifier, localName, exportedName, callableId }) => + [specifier, localName, exportedName, callableId] as const, + ); + expect(typeLinks).toEqual([ + ["./whole", "Whole", null, null], + ["./inline", "Inline", null, null], + ["./mixed", "Erased", null, null], + ["./reexported", null, "Reexported", null], + ["./inline-export", null, "InlineExport", null], + [null, "LocalType", "LocalType", null], + [null, "LocalInterface", "LocalInterface", null], + [null, "hiddenFunction", "hiddenFunction", null], + ]); + expect(ir.limitations).toContain( + "Compiler options are unavailable; inline type-only imports or re-exports may preserve a module side-effect dependency.", + ); + }); +}); + describe("CommonJS dependency links", () => { it("retains an import-equals binding and its module origin", () => { const ir = analyzeJavaScriptSemantics(` @@ -76,6 +132,12 @@ describe("CommonJS dependency links", () => { importedName: null, localName: "typed", }), + expect.objectContaining({ + kind: "type-import", + specifier: "type-only", + importedName: null, + localName: "TypeOnly", + }), ]); expect(ir.references.filter(({ name }) => name === "typed")).toHaveLength( 1, diff --git a/src/domain/javascript/javascriptSemanticAnalysis.structure.test.ts b/src/domain/javascript/javascriptSemanticAnalysis.structure.test.ts index 2cd9fba80..2312eff5d 100644 --- a/src/domain/javascript/javascriptSemanticAnalysis.structure.test.ts +++ b/src/domain/javascript/javascriptSemanticAnalysis.structure.test.ts @@ -72,9 +72,9 @@ describe("JavaScript semantic analysis: structure 1", () => { }); const shadow = onlyBinding(ir, "ipcRenderer"); expect(shadow.provenance).toEqual({ - status: "local", + status: "unknown", origins: [], - reason: null, + reason: "Parameter provenance depends on caller arguments.", }); const shadowReference = ir.references.find( ({ name, bindingId, role }) => diff --git a/src/domain/javascript/javascriptSemanticAnalysis.ts b/src/domain/javascript/javascriptSemanticAnalysis.ts index b56e1a112..f6c6db25d 100644 --- a/src/domain/javascript/javascriptSemanticAnalysis.ts +++ b/src/domain/javascript/javascriptSemanticAnalysis.ts @@ -43,6 +43,7 @@ import { import { semanticRequireOrigin } from "./javascriptSemanticRequireOrigin.js"; import { collectSemanticMemberMutationsSteps } from "./javascriptSemanticMemberMutations.js"; import { indexJavaScriptAmbientWritesSteps } from "./javascriptSemanticAmbientWrites.js"; +import { hasUncertainTypeOnlyModuleSideEffect } from "./javascriptModuleDeclaration.js"; import { collectSemanticReturns, resolveSemanticModuleCallables, @@ -67,6 +68,7 @@ import { import { isJavaScriptRpcClientFactory } from "./javascriptRpcEndpoints.js"; import { createSemanticModuleInterop } from "./javascriptModuleInterop.js"; import { SemanticPropertyPathCoverage } from "./javascriptSemanticPropertyPaths.js"; +import type { JavaScriptModuleResolutionMode } from "./javascriptModuleResolutionMode.js"; interface BindPatternInput { readonly pattern: t.Node; @@ -137,7 +139,7 @@ export function* indexJavaScriptBindingsSteps( /** Recover semantics from an already parsed JavaScript artifact. */ export const analyzeParsedJavaScriptSemantics = ( file: ParsedJavaScriptSource, - staticImportResolutionMode: "import" | "require" = "import", + staticImportResolutionMode: JavaScriptModuleResolutionMode = "import", ): JavaScriptSemanticIr => completeSemanticSteps( analyzeParsedJavaScriptSemanticsSteps(file, staticImportResolutionMode), @@ -151,7 +153,7 @@ export const analyzeParsedJavaScriptSemantics = ( */ export function* analyzeParsedJavaScriptSemanticsSteps( file: ParsedJavaScriptSource, - staticImportResolutionMode: "import" | "require" = "import", + staticImportResolutionMode: JavaScriptModuleResolutionMode = "import", ): Generator { const state = createState(file.program, staticImportResolutionMode); yield* collectDefinitionsSteps(file.program, state); @@ -200,6 +202,11 @@ export function* analyzeParsedJavaScriptSemanticsSteps( "The parser recovered from syntax errors; affected bindings are partial.", ] : []), + ...(hasUncertainTypeOnlyModuleSideEffect(file.program) + ? [ + "Compiler options are unavailable; inline type-only imports or re-exports may preserve a module side-effect dependency.", + ] + : []), "Values and aliases were recovered from inert syntax only; no JavaScript was executed.", "Return sites include only direct callable returns; nested callable returns remain separate.", "Local call, argument, return, and closure relations are static candidates and do not prove runtime invocation.", @@ -533,7 +540,7 @@ const bindingOrigin = ( const createState = ( program: t.Program, - staticImportResolutionMode: "import" | "require" = "import", + staticImportResolutionMode: JavaScriptModuleResolutionMode = "import", ): JavaScriptSemanticAnalysisState => { const root: JavaScriptSemanticScopeState = { scopeId: semanticScopeId("program", program), @@ -1210,8 +1217,11 @@ const addBinding = (input: AddBindingInput): void => { if (directOrigin !== undefined) binding.directOrigins.push( directOrigin.resolutionMode === undefined && - state.staticImportResolutionMode === "require" - ? { ...directOrigin, resolutionMode: "require" } + state.staticImportResolutionMode !== "import" + ? { + ...directOrigin, + resolutionMode: state.staticImportResolutionMode, + } : directOrigin, ); binding.runtimeImport ||= runtimeImport === true; diff --git a/src/domain/javascript/javascriptSemanticIr.ts b/src/domain/javascript/javascriptSemanticIr.ts index 18f1eb485..d8349e895 100644 --- a/src/domain/javascript/javascriptSemanticIr.ts +++ b/src/domain/javascript/javascriptSemanticIr.ts @@ -4,15 +4,19 @@ import type { JavaScriptSemanticCoverage, JavaScriptSemanticReturnCoverage, } from "./javascriptSemanticCoverage.js"; +import type { JavaScriptModuleResolutionMode } from "./javascriptModuleResolutionMode.js"; /** One exact module origin followed through imports, requires, or aliases. */ export interface JavaScriptModuleOrigin { - readonly resolutionMode?: "import" | "require"; + readonly resolutionMode?: JavaScriptModuleResolutionMode; readonly specifier: string; readonly importedPath: readonly string[]; } -/** Fail-closed provenance classification for one binding. */ +/** + * Fail-closed module-alias provenance for one binding, not transitive data flow. + * Locally constructed values may contain or derive from imported values. + */ export type JavaScriptBindingProvenance = | { readonly status: "module"; @@ -393,7 +397,7 @@ export interface JavaScriptSemanticFrontier { /** Static import/export relationship retained for cross-file composition. */ export interface JavaScriptSemanticModuleLink { - readonly resolutionMode?: "import" | "require"; + readonly resolutionMode?: JavaScriptModuleResolutionMode; readonly kind: | "import" | "type-import" diff --git a/src/domain/javascript/javascriptSemanticProjection.ts b/src/domain/javascript/javascriptSemanticProjection.ts index 7e4663efe..b477bb5af 100644 --- a/src/domain/javascript/javascriptSemanticProjection.ts +++ b/src/domain/javascript/javascriptSemanticProjection.ts @@ -28,6 +28,12 @@ import { propertyName, semanticStaticPropertyKey, } from "./javascriptAstValues.js"; +import { + isTypeOnlyExportDeclaration, + isTypeOnlyExportSpecifier, + isTypeOnlyImportDeclaration, + isTypeOnlyImportSpecifier, +} from "./javascriptModuleDeclaration.js"; interface CollectCallableInput { readonly node: t.Node; @@ -75,7 +81,7 @@ export const collectSemanticModuleLink = ( addModuleLink( state, { - kind: "re-export", + kind: isTypeOnlyExportDeclaration(node) ? "type-import" : "re-export", specifier: node.source.value, importedName: "*", localName: null, @@ -108,12 +114,19 @@ const collectImportEquals = ( node: t.TSImportEqualsDeclaration, state: JavaScriptSemanticAnalysisState, ): void => { - const specifier = semanticImportEqualsSpecifier(node); + const moduleReference = node.moduleReference; + const specifier = + semanticImportEqualsSpecifier(node) ?? + (node.importKind === "type" && + t.isTSExternalModuleReference(moduleReference) && + t.isStringLiteral(moduleReference.expression) + ? moduleReference.expression.value + : null); if (specifier === null) return; addModuleLink( state, { - kind: "require", + kind: node.importKind === "type" ? "type-import" : "require", specifier, importedName: null, localName: node.id.name, @@ -287,7 +300,7 @@ const collectImports = ( addModuleLink( state, { - kind: "import", + kind: isTypeOnlyImportDeclaration(node) ? "type-import" : "import", specifier: node.source.value, importedName: null, localName: null, @@ -300,7 +313,12 @@ const collectImports = ( addModuleLink( state, { - kind: "import", + kind: + isTypeOnlyImportDeclaration(node) || + (t.isImportSpecifier(specifier) && + isTypeOnlyImportSpecifier(specifier)) + ? "type-import" + : "import", specifier: node.source.value, importedName: t.isImportDefaultSpecifier(specifier) ? "default" @@ -319,12 +337,13 @@ const collectNamedExports = ( node: t.ExportNamedDeclaration, state: JavaScriptSemanticAnalysisState, ): void => { + const declarationTypeOnly = isTypeOnlyExportDeclaration(node); if (node.declaration !== null && node.declaration !== undefined) for (const localName of declarationNames(node.declaration)) addModuleLink( state, { - kind: "export", + kind: declarationTypeOnly ? "type-import" : "export", specifier: null, importedName: null, localName, @@ -342,7 +361,14 @@ const collectNamedExports = ( addModuleLink( state, { - kind: node.source == null ? "export" : "re-export", + kind: + declarationTypeOnly || + (t.isExportSpecifier(specifier) && + isTypeOnlyExportSpecifier(specifier)) + ? "type-import" + : node.source == null + ? "export" + : "re-export", specifier: node.source?.value ?? null, importedName: t.isExportNamespaceSpecifier(specifier) ? "*" @@ -507,7 +533,20 @@ const addModuleLink = ( }, referenceNode: t.Node, ): void => { - const collected = { ...link, callableId: link.callableId ?? null }; + const resolutionMode = + link.resolutionMode ?? + (link.kind === "import" || + link.kind === "re-export" || + link.kind === "type-import" + ? state.staticImportResolutionMode + : link.kind === "require" + ? "require" + : undefined); + const collected = { + ...link, + ...(resolutionMode === undefined ? {} : { resolutionMode }), + callableId: link.callableId ?? null, + }; state.moduleLinks.push(collected); if (link.localName !== null) { const binding = resolveSemanticBindingState( @@ -745,6 +784,13 @@ const declarationNames = (declaration: t.Declaration): string[] => { t.isIdentifier(declaration.id) ) return [declaration.id.name]; + if ( + (t.isTSInterfaceDeclaration(declaration) || + t.isTSTypeAliasDeclaration(declaration) || + t.isTSDeclareFunction(declaration)) && + t.isIdentifier(declaration.id) + ) + return [declaration.id.name]; if ( t.isTSImportEqualsDeclaration(declaration) && semanticImportEqualsSpecifier(declaration) !== null diff --git a/src/domain/javascript/javascriptSemanticProvenance.test.ts b/src/domain/javascript/javascriptSemanticProvenance.test.ts new file mode 100644 index 000000000..82a77a449 --- /dev/null +++ b/src/domain/javascript/javascriptSemanticProvenance.test.ts @@ -0,0 +1,94 @@ +import { describe, expect, it } from "vitest"; + +import { analyzeJavaScriptSemantics } from "./javascriptSemanticAnalysis.js"; +import { + onlyBinding, + topLevelBinding, +} from "./javascriptSemanticAnalysis.fixture.js"; + +describe("JavaScript semantic binding provenance", () => { + it("keeps opaque expression results unknown instead of declaring them local", () => { + const ir = analyzeJavaScriptSemantics(` + const called = loadFeature(); + const constructed = new Feature(); + const tagged = tag\`feature\`; + const dynamicRequired = require(specifier); + const sequence = (0, loadFeature()); + const assignment = (slot = loadFeature()); + async function readLater(parameter = require("fallback")) { + const awaited = await loadFeature(); + return awaited; + } + try { loadFeature(); } catch (caught) { void caught; } + function* yieldLater() { + const yielded = yield loadFeature(); + return yielded; + } + `); + + for (const name of [ + "called", + "constructed", + "tagged", + "dynamicRequired", + "sequence", + "assignment", + "awaited", + "yielded", + "parameter", + "caught", + ]) { + expect(onlyBinding(ir, name).provenance).toMatchObject({ + status: "unknown", + origins: [], + }); + } + }); + + it("recognizes explicit local values and preserves exact module aliases", () => { + const ir = analyzeJavaScriptSemantics(` + const object = { value: 1 }; + const array = [1, 2]; + const template = \`feature\`; + const primitive = -1 + 2; + const derived = loadFeature() + 1; + const derivedText = \`value: \${loadFeature()}\`; + let uninitialized; + const callable = () => 1; + const Constructed = class {}; + const imported = require("feature"); + const alias = imported; + const sequence = (0, require("sequence-feature")); + const assignment = (slot = require("assignment-feature")); + `); + + for (const name of [ + "object", + "array", + "template", + "primitive", + "derived", + "derivedText", + "uninitialized", + "callable", + "Constructed", + ]) + expect(topLevelBinding(ir, name).provenance).toMatchObject({ + status: "local", + origins: [], + }); + + expect(topLevelBinding(ir, "alias").provenance).toMatchObject({ + status: "module", + origins: [{ specifier: "feature" }], + }); + expect(topLevelBinding(ir, "sequence").provenance).toMatchObject({ + status: "module", + origins: [{ specifier: "sequence-feature" }], + }); + expect(topLevelBinding(ir, "assignment").provenance).toMatchObject({ + status: "module", + origins: [{ specifier: "assignment-feature" }], + }); + }); +}); diff --git a/src/domain/javascript/javascriptSemanticReturns.ts b/src/domain/javascript/javascriptSemanticReturns.ts index 189a1385e..27bb030d0 100644 --- a/src/domain/javascript/javascriptSemanticReturns.ts +++ b/src/domain/javascript/javascriptSemanticReturns.ts @@ -101,6 +101,7 @@ export const resolveSemanticModuleCallables = ( bindings.map(({ bindingId, provenance }) => [bindingId, provenance]), ); return state.moduleLinks.map((link) => { + if (link.kind === "type-import") return { ...link, callableId: null }; // Named exports follow their lexical binding, including every assignment. // A declaration's ID or a callable's display name cannot prove that link. if (link.localName === null) @@ -122,9 +123,7 @@ export const resolveSemanticModuleCallables = ( : undefined; return { ...link, - ...(resolutionMode === "import" || resolutionMode === "require" - ? { resolutionMode } - : {}), + ...(resolutionMode !== undefined ? { resolutionMode } : {}), callableId: resolved.length === 1 ? (resolved[0] ?? null) : null, }; }); diff --git a/src/domain/javascript/javascriptSemanticState.ts b/src/domain/javascript/javascriptSemanticState.ts index b82abc62d..d01a4be52 100644 --- a/src/domain/javascript/javascriptSemanticState.ts +++ b/src/domain/javascript/javascriptSemanticState.ts @@ -12,6 +12,7 @@ import type { JavaScriptSemanticCallable, JavaScriptSemanticScope, } from "./javascriptSemanticIr.js"; +import type { JavaScriptModuleResolutionMode } from "./javascriptModuleResolutionMode.js"; /** Internal initializer plus a destructuring/member projection. */ interface JavaScriptSemanticInitializer { @@ -63,7 +64,7 @@ export interface JavaScriptSemanticScopeState { /** Shared state for semantic collection and evaluation. */ export interface JavaScriptSemanticAnalysisState { /** Effective loader for static imports in this source artifact. */ - readonly staticImportResolutionMode: "import" | "require"; + readonly staticImportResolutionMode: JavaScriptModuleResolutionMode; readonly parentsByNode: WeakMap; readonly scopes: JavaScriptSemanticScopeState[]; readonly scopesById: Map; diff --git a/src/domain/javascript/javascriptSemanticValues.ts b/src/domain/javascript/javascriptSemanticValues.ts index cf31e0575..d15c5edfc 100644 --- a/src/domain/javascript/javascriptSemanticValues.ts +++ b/src/domain/javascript/javascriptSemanticValues.ts @@ -817,6 +817,13 @@ const provenanceForBindingValue = ( binding: JavaScriptSemanticBindingState, context: EvaluationContext, ): JavaScriptBindingProvenance => { + if (binding.kind === "parameter" || binding.kind === "catch") + return semanticUnresolvedProvenance( + "unknown", + binding.kind === "parameter" + ? "Parameter provenance depends on caller arguments." + : "Catch binding provenance depends on the thrown value.", + ); if (binding.directOrigins.length > 0) return semanticOriginsProvenance(binding.directOrigins); if (binding.initializers.length === 0) return semanticLocalProvenance(); @@ -890,6 +897,14 @@ const provenanceForExpression = ( const required = semanticRequireOrigin(node, context.state); if (required !== undefined) return semanticOriginsProvenance([required.origin]); + if (t.isSequenceExpression(node)) { + const finalExpression = node.expressions.at(-1); + return finalExpression === undefined + ? semanticUnresolvedProvenance("unknown", "Empty sequence expression.") + : provenanceForExpression(finalExpression, nestedContext(context)); + } + if (t.isAssignmentExpression(node) && node.operator === "=") + return provenanceForExpression(node.right, nestedContext(context)); if (t.isIdentifier(node)) { const binding = resolveSemanticBindingState(context.state, node, node.name); return binding === undefined @@ -961,9 +976,25 @@ const provenanceForExpression = ( "Conditional provenance is unresolved.", ); } - return semanticLocalProvenance(); + if (isLocallyCreatedValue(node)) return semanticLocalProvenance(); + return semanticUnresolvedProvenance( + "unknown", + `Unsupported ${node.type} provenance.`, + ); }; +const isLocallyCreatedValue = (node: t.Node): boolean => + readExactJavaScriptLiteral(node).found || + t.isObjectExpression(node) || + t.isArrayExpression(node) || + t.isFunctionExpression(node) || + t.isArrowFunctionExpression(node) || + t.isClassExpression(node) || + t.isTemplateLiteral(node) || + t.isUnaryExpression(node) || + t.isBinaryExpression(node) || + t.isUpdateExpression(node); + const mergeValues = ( values: readonly JavaScriptSemanticValue[], ): JavaScriptSemanticValue => { diff --git a/src/domain/javascript/javascriptSourceMapPaths.ts b/src/domain/javascript/javascriptSourceMapPaths.ts index d897bdd26..06b5f8265 100644 --- a/src/domain/javascript/javascriptSourceMapPaths.ts +++ b/src/domain/javascript/javascriptSourceMapPaths.ts @@ -1,5 +1,6 @@ import { posix } from "node:path"; import { domainToASCII, fileURLToPath, pathToFileURL } from "node:url"; +import { TraceMap } from "@jridgewell/trace-mapping"; import { z } from "zod"; @@ -25,22 +26,64 @@ export type JavaScriptSourceMapReference = z.infer< typeof javascriptSourceMapReferenceSchema >; -/** Interpret a declaration once at the source-map ingestion boundary. */ -export const resolveJavaScriptSourceMapReference = ( - sourceName: string, +/** Interpret declarations together once at their source-map ingestion boundary. */ +export const resolveJavaScriptSourceMapReferences = ( + sourceNames: readonly (string | null)[], sourceRoot: string | null, mapPath: string, -): JavaScriptSourceMapReference => { - // TraceMap's producer prefixes sourceRoot before resolving the URL reference. - const reference = `${sourceRoot ? `${sourceRoot}/` : ""}${sourceName}`; - return { - source_name: sourceName, - source_root: sourceRoot, - map_path: mapPath, - resolution: resolveJavaScriptSourceMapPath(reference, mapPath), - }; +): (JavaScriptSourceMapReference | null)[] => { + if (sourceNames.length === 0) return []; + const resolvedSources = resolveSourceMapUrls( + sourceNames.map((sourceName) => sourceName ?? ""), + sourceRoot, + "", + ); + return sourceNames.map((sourceName, index) => { + if (sourceName === null) return null; + const reference = resolvedSources[index]; + if (reference === undefined) + throw new TypeError( + `TraceMap did not resolve source declaration ${String(index)}`, + ); + return { + source_name: sourceName, + source_root: sourceRoot, + map_path: mapPath, + resolution: resolveJavaScriptSourceMapPath(reference, mapPath), + }; + }); }; +/** Resolve a source declaration using the same pinned format implementation as map consumers. */ +export const resolveJavaScriptSourceMapUrl = ( + source: string | null, + sourceRoot: string | null | undefined, + mapUrl: string, +): string => { + const resolved = resolveSourceMapUrls([source ?? ""], sourceRoot, mapUrl)[0]; + if (resolved === undefined) + throw new TypeError( + "TraceMap did not resolve its single source declaration", + ); + return resolved; +}; + +const resolveSourceMapUrls = ( + sources: string[], + sourceRoot: string | null | undefined, + mapUrl: string, +): readonly string[] => + new TraceMap( + { + version: 3, + names: [], + sources, + ...(sourceRoot == null ? {} : { sourceRoot }), + mappings: "", + }, + mapUrl, + ).resolvedSources; + /** Resolve a source-map URL reference without changing its recorded identity. */ const resolveJavaScriptSourceMapPath = ( source: string, diff --git a/src/domain/javascript/javascriptSourceParser.ts b/src/domain/javascript/javascriptSourceParser.ts index ce5619ead..630d5e9bf 100644 --- a/src/domain/javascript/javascriptSourceParser.ts +++ b/src/domain/javascript/javascriptSourceParser.ts @@ -37,10 +37,19 @@ export const parserPluginsForPath = (sourcePath?: string): ParserPlugin[] => { : ["decorators-legacy", typescript]; }; -/** `.mjs` and `.mts` are modules by extension; other paths leave the mode to syntax. */ +/** `.mjs` and `.mts` explicitly select module mode. */ export const isExplicitModuleSourcePath = (path?: string): boolean => /\.m[jt]s$/iu.test(path ?? ""); +const runtimeSourceTypeForPath = ( + path?: string, +): "commonjs" | "module" | "unambiguous" => + /\.cjs$/iu.test(path ?? "") + ? "commonjs" + : isExplicitModuleSourcePath(path) + ? "module" + : "unambiguous"; + export interface RecoveredJavaScriptParse { readonly file: ParsedJavaScriptSource; /** Errors that apply only if a source of unknown mode is an ES module. */ @@ -58,25 +67,25 @@ export const parseRecoveredJavaScript = ( sourcePath: string | undefined, options: Omit, ): RecoveredJavaScriptParse => { - // `.cjs` is CommonJS by extension, so module-only errors cannot apply. - if (/\.cjs$/iu.test(sourcePath ?? "")) + const sourceType = runtimeSourceTypeForPath(sourcePath); + if (sourceType !== "unambiguous") { + const normalizedOptions = { ...options }; + if (sourceType === "commonjs") { + // Babel owns these wrapper semantics in CommonJS mode and rejects + // explicit script overrides, including the reference-import options. + delete normalizedOptions.allowAwaitOutsideFunction; + delete normalizedOptions.allowReturnOutsideFunction; + delete normalizedOptions.allowNewTargetOutsideFunction; + } return { file: parse(source, { - ...options, - sourceType: "script", - errorRecovery: true, - }), - moduleOnlyErrors: [], - }; - if (isExplicitModuleSourcePath(sourcePath)) - return { - file: parse(source, { - ...options, - sourceType: "module", + ...normalizedOptions, + sourceType, errorRecovery: true, }), moduleOnlyErrors: [], }; + } const file = parse(source, { ...options, sourceType: "unambiguous", @@ -98,18 +107,34 @@ export const parseRecoveredJavaScript = ( }; }; -/** Parse JavaScript or TypeScript once without attaching comments to AST nodes. */ +/** Parse inert JavaScript or TypeScript facts without attaching comments to AST nodes. */ export const parseJavaScriptSource = ( source: string, sourcePath?: string, ): ParsedJavaScriptSource | null => { try { - return parse(source, { - sourceType: "unambiguous", + const runtimeSourceType = runtimeSourceTypeForPath(sourcePath); + const commonjs = runtimeSourceType === "commonjs"; + const options = { errorRecovery: true, attachComment: false, plugins: parserPluginsForPath(sourcePath), + }; + const file = parse(source, { + ...options, + // Inert artifact analysis retains module declarations even in .cjs assets. + // Infer their syntax here; reference imports keep filename-mode diagnostics. + sourceType: commonjs ? "unambiguous" : runtimeSourceType, + allowReturnOutsideFunction: commonjs, + allowNewTargetOutsideFunction: commonjs, }); + // Unambiguous mode retains module-only diagnostics after choosing a script. + // The .cjs extension establishes wrapper mode, so obtain its own diagnostics. + return commonjs && + file.program.sourceType === "script" && + file.errors.length > 0 + ? parse(source, { ...options, sourceType: "commonjs" }) + : file; } catch (cause: unknown) { // Unparseable source is represented by the null return. void cause; diff --git a/src/domain/javascript/javascriptStaticAnalysis.ts b/src/domain/javascript/javascriptStaticAnalysis.ts index 4d10638bc..c34462498 100644 --- a/src/domain/javascript/javascriptStaticAnalysis.ts +++ b/src/domain/javascript/javascriptStaticAnalysis.ts @@ -53,6 +53,11 @@ import { import { createJavaScriptRpcScan } from "./javascriptRpcEndpoints.js"; import { semanticImportEqualsSpecifier } from "./javascriptSemanticProjection.js"; +import { + hasUncertainTypeOnlyModuleSideEffect, + isTypeOnlyExportDeclaration, + isTypeOnlyImportDeclaration, +} from "./javascriptModuleDeclaration.js"; /** Parse one JavaScript artifact and recover static structure only. */ export const analyzeJavaScriptStaticSource = ( @@ -154,6 +159,11 @@ const finalizeStaticAnalysis = ( : [ "One or more static keys, expressions, or Electron boundary values were dynamic and remain unknown.", ]), + ...(hasUncertainTypeOnlyModuleSideEffect(file.program) + ? [ + "Compiler options are unavailable; inline type-only imports or re-exports may preserve a module side-effect dependency.", + ] + : []), ...(accumulator.references.some( ({ value }) => value.specifier !== null && ELECTRON_MODULE.test(value.specifier), @@ -246,14 +256,20 @@ const inspectNode = ( addReference(findings, { node, kind: "require", specifier }); } else if ( (t.isImportDeclaration(node) || t.isExportAllDeclaration(node)) && - node.source !== undefined + node.source !== undefined && + !(t.isImportDeclaration(node) && isTypeOnlyImportDeclaration(node)) && + !(t.isExportAllDeclaration(node) && isTypeOnlyExportDeclaration(node)) ) addReference(findings, { node, kind: "static-import", specifier: node.source.value, }); - else if (t.isExportNamedDeclaration(node) && node.source != null) + else if ( + t.isExportNamedDeclaration(node) && + node.source != null && + !isTypeOnlyExportDeclaration(node) + ) addReference(findings, { node, kind: "static-import", diff --git a/src/domain/javascript/javascriptStaticAnalysisHelpers.ts b/src/domain/javascript/javascriptStaticAnalysisHelpers.ts index a6a6ebc44..71562e6ca 100644 --- a/src/domain/javascript/javascriptStaticAnalysisHelpers.ts +++ b/src/domain/javascript/javascriptStaticAnalysisHelpers.ts @@ -691,6 +691,14 @@ export const registrationKey = ( registration.runtime, registration.chunk_keys, String(registration.unknown_chunk_keys), + // Equal factory tables can be registered with different runtime callbacks. + // Both early collection and finalization must retain those recovered facts. + registration.runtime_require_name, + registration.runtime_module_cache_status, + registration.entry_module_keys, + String(registration.unknown_entry_module_keys), + registration.async_chunk_keys, + String(registration.unknown_async_chunk_keys), registration.modules.map(({ module_key: key, source_sha256: digest }) => [ key, digest, diff --git a/src/domain/javascript/sourceToBundleComparison.test.ts b/src/domain/javascript/sourceToBundleComparison.test.ts index f488ee598..d231cb5ec 100644 --- a/src/domain/javascript/sourceToBundleComparison.test.ts +++ b/src/domain/javascript/sourceToBundleComparison.test.ts @@ -1,10 +1,11 @@ import { describe, expect, it } from "vitest"; +import { TraceMap } from "@jridgewell/trace-mapping"; -import { resolveJavaScriptSourceMapReference } from "./javascriptSourceMapPaths.js"; import { createJavaScriptApplicationGraph, createJavaScriptApplicationNode, } from "./javascriptApplicationGraph.js"; +import type { ApplicationNode } from "./javascriptApplicationGraphSchemas.js"; import { createHistoricalSourceGraph } from "../referenceSourceGraph.js"; import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js"; import { compareSourceToBundle } from "./sourceToBundleComparison.js"; @@ -12,7 +13,10 @@ import { SOURCE_TO_BUNDLE_SIGNAL_WEIGHTS, sourceToBundleComparisonResultSchema, } from "./sourceToBundleComparisonSchemas.js"; -import { artifactEvidence } from "./javascriptApplicationGraph.fixture.js"; +import { + artifactEvidence, + sourceMapReference, +} from "./javascriptApplicationGraph.fixture.js"; const HASH = { artifact: "1".repeat(64), @@ -42,9 +46,6 @@ describe("historical source to bundle comparison", () => { const second = compareSourceToBundle(input); expect(first).toEqual(second); - expect(() => - sourceToBundleComparisonResultSchema.parse(first), - ).not.toThrow(); expect(first.summary).toEqual({ unchanged: 1, modified: 0, @@ -153,7 +154,7 @@ describe("source to bundle digest changes", () => { observations: [ { label: "display label", - source_map_reference: resolveJavaScriptSourceMapReference( + source_map_reference: sourceMapReference( "webpack://fixture/./src/modified.ts", null, "dist/main.js.map", @@ -202,6 +203,90 @@ describe("source to bundle digest changes", () => { }); }); +describe("source to bundle Unicode path collisions", () => { + it("keeps colliding canonical-equivalent current paths ambiguous", () => { + const historicalPath = "src/a\u0301\u0323.ts"; + const currentPaths = ["src/a\u0323\u0301.ts", "src/\u1ea1\u0301.ts"]; + const nodes = currentPaths.map((path, index) => + moduleNode(`unicode-${index}`, { path }), + ); + const result = comparePathToNodes(historicalPath, nodes); + const mapping = item(result, historicalPath); + + expect(mapping).toMatchObject({ + status: "unknown", + confidence: "unknown", + current_node_ids: [], + candidates: [ + expect.objectContaining({ + signals: expect.arrayContaining([ + expect.objectContaining({ kind: "unicode-equivalent-path" }), + ]), + }), + expect.objectContaining({ + signals: expect.arrayContaining([ + expect.objectContaining({ kind: "unicode-equivalent-path" }), + ]), + }), + ], + limitations: [ + expect.stringContaining( + "filesystem paths with distinct Unicode spellings", + ), + ], + }); + }); + + it("prefers a raw source-map path over canonically equivalent alternatives", () => { + const historicalPath = "src/cafe\u0301.ts"; + const exact = sourceMapNode( + "exact", + "cafe\u0301.ts", + "../src/", + HASH.modified, + ); + const equivalent = sourceMapNode( + "equivalent", + "caf\u00e9.ts", + "../src/", + HASH.removed, + ); + const result = comparePathToNodes(historicalPath, [exact, equivalent]); + + expect(item(result, historicalPath)).toMatchObject({ + status: "modified", + current_node_ids: [exact.node_id], + }); + }); + + it("finds Unicode-equivalent suffixes of absolute source-map URLs", () => { + const historicalPath = "src/caf\u00e9.ts"; + const node = sourceMapNode( + "remote", + "cafe\u0301.ts", + "https://cdn.example/src/", + HASH.modified, + ); + const result = comparePathToNodes(historicalPath, [node]); + + expect(item(result, historicalPath)).toMatchObject({ + status: "unknown", + current_node_ids: [], + candidates: [ + expect.objectContaining({ + current_node_id: node.node_id, + signals: expect.arrayContaining([ + expect.objectContaining({ + kind: "unicode-equivalent-path", + current_values: ["cdn.example/src/cafe\u0301.ts"], + }), + ]), + }), + ], + }); + }); +}); + describe("source to bundle path syntax", () => { it.each([ "src/modified#part.ts", @@ -282,9 +367,60 @@ describe("source to bundle path syntax", () => { }), ], }); + expect( + item(result, "src/modified.ts").candidates.flatMap( + ({ signals }) => signals, + ), + ).not.toContainEqual( + expect.objectContaining({ kind: "unicode-equivalent-path" }), + ); }); }); +describe("source-map resolver equivalence", () => { + it.each([ + { + sourceRoot: "https://cdn.example/src/", + expectedSource: "https://cdn.example/src/a.js", + expectedResolution: { kind: "suffix", path: "cdn.example/src/a.js" }, + }, + { + sourceRoot: "https://cdn.example/src//", + expectedSource: "https://cdn.example/src/a.js", + expectedResolution: { kind: "suffix", path: "cdn.example/src/a.js" }, + }, + { + sourceRoot: "webpack://", + expectedSource: "webpack:///a.js", + expectedResolution: { kind: "suffix", path: "a.js" }, + }, + ])( + "matches TraceMap for sourceRoot $sourceRoot", + ({ sourceRoot, expectedSource, expectedResolution }) => { + const producerSource = new TraceMap( + { + version: 3, + file: "main.js", + sourceRoot, + sources: ["a.js"], + names: [], + mappings: "", + }, + "file:///artifact/dist/main.js.map", + ).resolvedSources[0]; + const reference = sourceMapReference( + "a.js", + sourceRoot, + "dist/main.js.map", + ); + + expect(producerSource).toBe(expectedSource); + expect(reference.source_root).toBe(sourceRoot); + expect(reference.resolution).toEqual(expectedResolution); + }, + ); +}); + describe("source to bundle complete metadata", () => { it("accepts long source metadata and all reported limitations", () => { const result = compareSourceToBundle({ @@ -328,6 +464,61 @@ describe("source to bundle complete metadata", () => { }); }); +const sourceMapNode = ( + key: string, + sourceName: string, + sourceRoot: string, + digest: string, +) => + createJavaScriptApplicationNode({ + kind: "source-module", + identity: { + strategy: "source-map-original", + source_root: sourceRoot, + stability: "source-map-exact", + source_map_sha256: HASH.artifact, + original_source: sourceName, + source_sha256: digest, + }, + observations: [ + { + label: `${key} source-map spelling`, + source_map_reference: sourceMapReference( + sourceName, + sourceRoot, + `dist/${key}.map`, + ), + properties: { content_available: true, content_sha256: digest }, + evidence: artifactEvidence(HASH.artifact, `dist/${key}.map`), + }, + ], + }); + +const comparePathToNodes = ( + sourcePath: string, + nodes: readonly ApplicationNode[], +) => + compareSourceToBundle({ + reference: historicalGraph("complete", [sourcePath]), + application: { + evidenceId: EVIDENCE_ID, + rootArtifactSha256: HASH.artifact, + graph: createJavaScriptApplicationGraph({ + schema: "JavaScriptApplicationGraph", + root_node_ids: nodes.map(({ node_id: nodeId }) => nodeId), + nodes, + edges: [], + coverage: { + status: "complete", + truncated: false, + omitted_count: 0, + limits: [], + }, + limitations: [], + }), + }, + }); + const historicalGraph = ( inventoryState: "complete" | "partial", paths = [ diff --git a/src/domain/javascript/sourceToBundleComparison.ts b/src/domain/javascript/sourceToBundleComparison.ts index ac0007cb4..5a70c57f3 100644 --- a/src/domain/javascript/sourceToBundleComparison.ts +++ b/src/domain/javascript/sourceToBundleComparison.ts @@ -258,7 +258,11 @@ const classifyMapping = ( confidence: "unknown", currentNodeIds: [], limitations: [ - "Only weak basename or extension signals were available; no mapping was forced.", + candidates.some((candidate) => + hasSignal(candidate, "unicode-equivalent-path"), + ) + ? "Unicode-equivalent paths are inferred candidates only; filesystem paths with distinct Unicode spellings may identify different files, so no mapping was forced." + : "Only weak basename or extension signals were available; no mapping was forced.", ], }; return absenceComplete diff --git a/src/domain/javascript/sourceToBundleComparisonSchemas.ts b/src/domain/javascript/sourceToBundleComparisonSchemas.ts index 2e27cadb3..9d6bd6b2f 100644 --- a/src/domain/javascript/sourceToBundleComparisonSchemas.ts +++ b/src/domain/javascript/sourceToBundleComparisonSchemas.ts @@ -15,6 +15,7 @@ export const SOURCE_TO_BUNDLE_SIGNAL_WEIGHTS = [ ["source-map-original-path", 70], ["current-path-exact", 60], ["current-path-suffix", 40], + ["unicode-equivalent-path", 20], ["basename-match", 20], ["language-extension", 5], ] as const; @@ -24,6 +25,7 @@ const sourceToBundleSignalKindSchema = z.enum([ "source-map-original-path", "current-path-exact", "current-path-suffix", + "unicode-equivalent-path", "basename-match", "language-extension", ]); diff --git a/src/domain/javascript/sourceToBundleSignals.ts b/src/domain/javascript/sourceToBundleSignals.ts index 2190988fe..b3546aecc 100644 --- a/src/domain/javascript/sourceToBundleSignals.ts +++ b/src/domain/javascript/sourceToBundleSignals.ts @@ -102,8 +102,12 @@ export const buildSourceToBundleCandidateIndex = ( for (const path of projection.paths) { for (const suffix of path.allowSuffix ? pathSuffixes(path.value) - : [path.value]) + : [path.value]) { addIndexValue(byPathSuffix, suffix, projection.node.node_id); + const canonical = suffix.normalize("NFC"); + if (canonical !== suffix) + addIndexValue(byPathSuffix, canonical, projection.node.node_id); + } addIndexValue( byBasename, posix.basename(path.value), @@ -126,9 +130,13 @@ export const candidateIdsForSource = ( source: SourceFile, index: SourceToBundleCandidateIndex, ): string[] => { + const canonicalPath = source.path.normalize("NFC"); const groups = [ source.sha256 === null ? undefined : index.byDigest.get(source.sha256), index.byPathSuffix.get(source.path), + canonicalPath === source.path + ? undefined + : index.byPathSuffix.get(canonicalPath), index.byBasename.get(posix.basename(source.path)), ]; const seen = new Set(); @@ -220,6 +228,14 @@ const candidateSignals = ( signals.push( signal("source-map-original-path", source.path, sourceMapPaths), ); + const unicodeEquivalentPaths = matchingUnicodePaths( + source.path, + current.paths, + ); + if (unicodeEquivalentPaths.length > 0) + signals.push( + signal("unicode-equivalent-path", source.path, unicodeEquivalentPaths), + ); const otherPaths = current.paths.filter( ({ kind }) => kind !== "source-map-original", ); @@ -286,6 +302,27 @@ const matchingPaths = ( ) .map(({ value }) => value); +const matchingUnicodePaths = ( + sourcePath: string, + currentPaths: readonly CurrentPath[], +): string[] => { + const canonicalSource = sourcePath.normalize("NFC"); + return currentPaths + .filter(({ value, allowSuffix }) => { + if ( + value === sourcePath || + (allowSuffix && value.endsWith(`/${sourcePath}`)) + ) + return false; + const canonicalValue = value.normalize("NFC"); + return ( + canonicalValue === canonicalSource || + (allowSuffix && canonicalValue.endsWith(`/${canonicalSource}`)) + ); + }) + .map(({ value }) => value); +}; + const addJsonPath = (paths: CurrentPath[], value: unknown): void => { if (typeof value === "string") addPath(paths, "observation-path", value); }; diff --git a/src/domain/managed/managedReconstruction.ts b/src/domain/managed/managedReconstruction.ts index e10be0ffd..9600166ae 100644 --- a/src/domain/managed/managedReconstruction.ts +++ b/src/domain/managed/managedReconstruction.ts @@ -204,7 +204,8 @@ const buildReconstructionSummary = ( ({ reconstruction }) => reconstruction.kind === "semantic-pseudocode", ).length, total_text_bytes: methods.reduce( - (total, { reconstruction }) => total + reconstruction.text_length, + (total, { reconstruction }) => + total + Buffer.byteLength(reconstruction.text, "utf8"), 0, ), }); diff --git a/src/domain/offsetDateTime.ts b/src/domain/offsetDateTime.ts index bccda7494..b7d38550f 100644 --- a/src/domain/offsetDateTime.ts +++ b/src/domain/offsetDateTime.ts @@ -1,5 +1,11 @@ import { z } from "zod"; +export interface OffsetDateTimeInstant { + readonly epochSecond: number; + /** Exact fractional second with insignificant trailing zeroes removed. */ + readonly fraction: string; +} + /** * ISO-8601 date-time that requires an explicit UTC offset. * @@ -19,3 +25,80 @@ export const offsetDateTimeSchema = z /^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|(?:[+\x2d](?:[01]\d|2[0-3]):[0-5]\d)))$/u, "Use an ISO-8601 date-time with an explicit UTC offset", ); + +/** Parse an already validated offset timestamp without losing sub-millisecond precision. */ +export const parseOffsetDateTimeInstant = ( + value: string, +): OffsetDateTimeInstant => { + const match = /^(.*?)(?:\.(\d+))?(Z|[+\x2d]\d{2}:\d{2})$/u.exec(value); + if (match === null) + throw new TypeError("Expected a validated offset date-time."); + const [, dateTime, fractionalDigits, offset] = match; + if (dateTime === undefined || offset === undefined) + throw new TypeError("Expected a validated offset date-time."); + const wholeSecondMilliseconds = Date.parse(`${dateTime}${offset}`); + if ( + !Number.isSafeInteger(wholeSecondMilliseconds) || + wholeSecondMilliseconds % 1000 !== 0 + ) + throw new TypeError( + "Offset date-time is outside the supported time range.", + ); + return { + epochSecond: wholeSecondMilliseconds / 1000, + fraction: fractionalDigits?.replace(/0+$/u, "") ?? "", + }; +}; + +/** Convert a Date.now-style integer into the same exact comparison shape. */ +export const offsetDateTimeInstantFromEpochMilliseconds = ( + epochMilliseconds: number, +): OffsetDateTimeInstant => { + if (!Number.isFinite(epochMilliseconds)) + throw new TypeError("Expected finite epoch milliseconds."); + if (Math.abs(epochMilliseconds) > Number.MAX_SAFE_INTEGER) + return { epochSecond: epochMilliseconds / 1000, fraction: "" }; + const epochSecond = Math.floor(epochMilliseconds / 1000); + const millisecondsWithinSecond = epochMilliseconds - epochSecond * 1000; + return { + epochSecond, + fraction: fractionalSecondFromMilliseconds(millisecondsWithinSecond), + }; +}; + +const fractionalSecondFromMilliseconds = (milliseconds: number): string => { + if (milliseconds === 0) return ""; + const [coefficient = "", exponentText] = String(milliseconds) + .toLowerCase() + .split("e"); + const exponent = exponentText === undefined ? 0 : Number(exponentText); + const point = coefficient.indexOf("."); + const decimalPosition = + (point < 0 ? coefficient.length : point) + exponent - 3; + const digits = coefficient.replace(".", ""); + const fraction = + decimalPosition <= 0 + ? `0.${"0".repeat(-decimalPosition)}${digits}` + : decimalPosition < digits.length + ? `${digits.slice(0, decimalPosition)}.${digits.slice(decimalPosition)}` + : `${digits}${"0".repeat(decimalPosition - digits.length)}`; + return ( + fraction.includes(".") ? fraction.slice(fraction.indexOf(".") + 1) : "" + ).replace(/0+$/u, ""); +}; + +/** Compare instants exactly while treating absent fraction digits as zeroes. */ +export const compareOffsetDateTimeInstants = ( + left: OffsetDateTimeInstant, + right: OffsetDateTimeInstant, +): number => { + if (left.epochSecond !== right.epochSecond) + return left.epochSecond < right.epochSecond ? -1 : 1; + const length = Math.max(left.fraction.length, right.fraction.length); + for (let index = 0; index < length; index += 1) { + const leftDigit = left.fraction.charCodeAt(index) || 48; + const rightDigit = right.fraction.charCodeAt(index) || 48; + if (leftDigit !== rightDigit) return leftDigit < rightDigit ? -1 : 1; + } + return 0; +}; diff --git a/src/domain/pcap/pcapAnalysis.ts b/src/domain/pcap/pcapAnalysis.ts new file mode 100644 index 000000000..21c64f365 --- /dev/null +++ b/src/domain/pcap/pcapAnalysis.ts @@ -0,0 +1,110 @@ +import { z } from "zod"; +import { localPathStringSchema } from "../localPath.js"; +import { digestSchema } from "../digests.js"; + +/** + * Caller intent for packet-capture analysis through caller-supplied tshark + * and capinfos. REA never installs Wireshark or its tools. + */ +export const pcapInputSchemas = { + inspect_pcap_client: z.strictObject({}), + inspect_pcap_capture: z.strictObject({ + path: localPathStringSchema.describe( + "Local pcap or pcapng capture file to inspect", + ), + }), +} as const; + +/** Supported pcap-backed operations. */ +export type PcapOperation = keyof typeof pcapInputSchemas; +/** Validated pcap requests carry their selected operation. */ +export type PcapRequest = { + [Name in PcapOperation]: { + operation: Name; + input: z.infer<(typeof pcapInputSchemas)[Name]>; + }; +}[PcapOperation]; + +/** Validate operation and input together so their types remain correlated. */ +export const pcapRequestSchema = z.discriminatedUnion("operation", [ + z.strictObject({ + operation: z.literal("inspect_pcap_client"), + input: pcapInputSchemas.inspect_pcap_client, + }), + z.strictObject({ + operation: z.literal("inspect_pcap_capture"), + input: pcapInputSchemas.inspect_pcap_capture, + }), +]); + +const client = z.strictObject({ + tshark_command: z.string().min(1), + tshark_source: z.enum(["environment", "path"]), + tshark_version: z.string().min(1).nullable(), + capinfos_command: z.string().min(1), + capinfos_source: z.enum(["environment", "path"]), + capinfos_version: z.string().min(1).nullable(), +}); + +const endpoint = z.strictObject({ + address: z.string().min(1), + port: z.number().int().positive().nullable(), + packet_count: z.number().int().positive(), +}); + +const dnsQuery = z.strictObject({ + query: z.string().min(1), + response_addresses: z.array(z.string().min(1)), + response_address_count: z.number().int().nonnegative(), +}); + +const protocolCount = z.strictObject({ + protocol: z.string().min(1), + packet_count: z.number().int().positive(), +}); + +/** Portable pcap observations with explicit coverage limitations. */ +export const pcapResultSchemas = { + inspect_pcap_client: z.strictObject({ + client, + }), + inspect_pcap_capture: z.strictObject({ + client, + target: z.strictObject({ + path: localPathStringSchema, + bytes: z.number().int().nonnegative(), + sha256: digestSchema, + }), + /** File format as capinfos reports it (pcap vs pcapng). */ + file_type: z.string().min(1).nullable(), + encapsulation: z.string().min(1).nullable(), + packet_count: z.number().int().nonnegative().nullable(), + capture_start: z.string().nullable(), + capture_end: z.string().nullable(), + capture_duration_seconds: z.number().nonnegative().nullable(), + snapshot_length: z.number().int().positive().nullable(), + /** Distinct endpoints with packet counts, bounded. */ + endpoints: z.array(endpoint), + endpoint_count: z.number().int().nonnegative(), + /** DNS queries with resolved addresses, bounded. */ + dns_queries: z.array(dnsQuery), + dns_query_count: z.number().int().nonnegative(), + /** TLS Server Name Indication values observed in handshakes. */ + tls_sni_values: z.array(z.string().min(1)), + tls_sni_count: z.number().int().nonnegative(), + /** Protocol distribution (frame.protocols column counts). */ + protocol_distribution: z.array(protocolCount), + protocol_count: z.number().int().nonnegative(), + /** HTTP request URIs seen on plain-text ports, bounded. */ + http_request_uris: z.array(z.string().min(1)), + http_request_uri_count: z.number().int().nonnegative(), + http_uri_redaction_count: z.number().int().nonnegative(), + unattributed_dns_addresses: z.array(z.string().min(1)), + unattributed_dns_address_count: z.number().int().nonnegative(), + unattributed_dns_packet_count: z.number().int().nonnegative(), + coverage: z.enum(["complete", "partial"]), + diagnostics: z + .strictObject({ capinfos_stderr: z.string(), tshark_stderr: z.string() }) + .optional(), + }), +} as const; diff --git a/src/domain/pcap/pcapEvidence.ts b/src/domain/pcap/pcapEvidence.ts new file mode 100644 index 000000000..848350fe3 --- /dev/null +++ b/src/domain/pcap/pcapEvidence.ts @@ -0,0 +1,34 @@ +import { createEvidence } from "../evidence.js"; +import { jsonObjectSchema, type JsonValue } from "../jsonValue.js"; +import type { PcapRequest } from "./pcapAnalysis.js"; + +/** Domain facts needed by both successful and retained partial observations. */ +interface PcapObservation { + readonly subject: Parameters[0] | null; + readonly provider: Parameters[1]; + readonly result: JsonValue; + readonly rawResult: JsonValue | null; + readonly limitations: readonly string[]; + readonly locations: NonNullable< + Parameters[2]["locations"] + >; +} + +/** One owner commits packet aggregation provenance and caller intent into Evidence. */ +export const createPcapEvidence = ( + request: PcapRequest, + observation: PcapObservation, +) => + createEvidence(observation.subject ?? undefined, observation.provider, { + operation: request.operation, + parameters: jsonObjectSchema.parse(request.input), + result: observation.result, + rawResult: observation.rawResult, + limitations: observation.limitations, + locations: observation.locations, + confidence: + request.operation === "inspect_pcap_capture" ? "derived" : "observed", + ...(request.operation === "inspect_pcap_capture" + ? { authority: "historical-reference" as const } + : {}), + }); diff --git a/src/domain/pngHeader.test.ts b/src/domain/pngHeader.test.ts index e8df531bc..676a832e0 100644 --- a/src/domain/pngHeader.test.ts +++ b/src/domain/pngHeader.test.ts @@ -33,3 +33,24 @@ it("rejects incomplete headers, invalid signatures and zero dimensions", () => { expect(readPngHeaderDimensions(zero)).toBeUndefined(); } }); + +it.each([0, 12, 14, 0xffff_ffff])("rejects IHDR data length %s", (length) => { + const bytes = Buffer.from(png); + bytes.writeUInt32BE(length, 8); + expect(readPngHeaderDimensions(bytes)).toBeUndefined(); +}); + +it.each([16, 20])("rejects out-of-range PNG dimension at %s", (offset) => { + const bytes = Buffer.from(png); + bytes.writeUInt32BE(0x8000_0000, offset); + expect(readPngHeaderDimensions(bytes)).toBeUndefined(); +}); + +it("accepts the largest dimension representable by the PNG specification", () => { + const bytes = Buffer.from(png); + bytes.writeUInt32BE(0x7fff_ffff, 16); + expect(readPngHeaderDimensions(bytes)).toEqual({ + width: 0x7fff_ffff, + height: 1, + }); +}); diff --git a/src/domain/pngHeader.ts b/src/domain/pngHeader.ts index 58cdd7d3f..5ab8c7c3d 100644 --- a/src/domain/pngHeader.ts +++ b/src/domain/pngHeader.ts @@ -8,10 +8,16 @@ export const readPngHeaderDimensions = ( if ( bytes.byteLength < 24 || !bytes.subarray(0, 8).equals(PNG_SIGNATURE) || + bytes.readUInt32BE(8) !== 13 || !bytes.subarray(12, 16).equals(IHDR_TYPE) ) return undefined; const width = bytes.readUInt32BE(16); const height = bytes.readUInt32BE(20); - return width === 0 || height === 0 ? undefined : { width, height }; + return width === 0 || + height === 0 || + width > 0x7fff_ffff || + height > 0x7fff_ffff + ? undefined + : { width, height }; }; diff --git a/src/domain/process/processCapture.fixture.ts b/src/domain/process/processCapture.fixture.ts index 701e76e2a..a8f2e669f 100644 --- a/src/domain/process/processCapture.fixture.ts +++ b/src/domain/process/processCapture.fixture.ts @@ -1,3 +1,4 @@ +import type { ProcessTraceSpecification } from "./processTraceSpecification.js"; import { compareProcessCaptures } from "./processComparison.js"; import { parseProcessCapture } from "./processCaptureParsing.js"; import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "./processCaptureExample.js"; @@ -112,3 +113,56 @@ export const compareUnverifiedProcessCaptures = ( parseProcessCapture(right), options, ); + +/** One journal and its matching declared trace, shared by domain and adapter checks. */ +export const processTraceCaptureFixture = () => { + const capture = { + ...EMPTY_PROCESS_CAPTURE_EXAMPLE, + event_journal: [ + { capture_order: 0, collection: "filesystem_checkpoints", index: 0 }, + { capture_order: 1, collection: "lifecycle", index: 0 }, + { capture_order: 2, collection: "lifecycle", index: 1 }, + { capture_order: 3, collection: "filesystem_checkpoints", index: 1 }, + ], + } as const; + const [before, after] = capture.filesystem_checkpoints; + if (before === undefined || after === undefined) + throw new Error( + "Trace fixture requires before and after filesystem checkpoints", + ); + const traceSpecification: ProcessTraceSpecification = { + events: [ + { + id: "before", + source: "filesystem", + exact: before, + cardinality: { kind: "required" }, + }, + { + id: "exit", + source: "lifecycle", + exact: { event: "exit", ...capture.exit }, + cardinality: { kind: "required" }, + }, + { + id: "settlement", + source: "lifecycle", + exact: { event: "settlement", ...capture.settlement }, + cardinality: { kind: "required" }, + }, + { + id: "after", + source: "filesystem", + exact: after, + cardinality: { kind: "required" }, + }, + ], + language: { + kind: "finite_traces", + variants: [ + { id: "normal", trace: ["before", "exit", "settlement", "after"] }, + ], + }, + }; + return { capture, traceSpecification }; +}; diff --git a/src/domain/process/processCaptureValidation.ts b/src/domain/process/processCaptureValidation.ts index 10d6b831b..33c6d5483 100644 --- a/src/domain/process/processCaptureValidation.ts +++ b/src/domain/process/processCaptureValidation.ts @@ -47,10 +47,6 @@ const validateCommitments = ( digestProcessCommitment( value, ), `manifest.${field}`, "commitment does not match its canonical value"); - require(Date.parse(manifest.started_at) <= - Date.parse( - manifest.completed_at, - ), "manifest.completed_at", "completion precedes start"); }; const validateOrdering = ( diff --git a/src/domain/process/processScenario.ts b/src/domain/process/processScenario.ts index a87ffd86e..e98d7a537 100644 --- a/src/domain/process/processScenario.ts +++ b/src/domain/process/processScenario.ts @@ -128,6 +128,9 @@ export const processComparisonContract = ( : {}), limits: scenario.limits, normalization: scenario.normalization, + ...(scenario.normalization.paths + ? { path_normalization_version: "longest-original-paths-v1" } + : {}), ...(scenario.normalization.ports ? { port_normalization_version: "contextual-endpoints-v2" } : {}), diff --git a/src/domain/process/processTraceAdapters.test.ts b/src/domain/process/processTraceAdapters.test.ts index 18cdea5c6..959ca76c8 100644 --- a/src/domain/process/processTraceAdapters.test.ts +++ b/src/domain/process/processTraceAdapters.test.ts @@ -1,72 +1,13 @@ import { describe, expect, it } from "vitest"; -import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "./processCaptureExample.js"; -import { accountFullyObservedProcessCapture } from "./processCapture.fixture.js"; +import { + processTraceCaptureFixture, + accountFullyObservedProcessCapture, +} from "./processCapture.fixture.js"; import { compareProcessCaptures } from "./processComparison.js"; import { parseProcessCapture } from "./processCaptureParsing.js"; import type { ProcessTraceSpecification } from "./processTraceSpecification.js"; -const beforeCheckpoint = { - name: "before", - at_ms: 0, - files: [], - effects: [], - truncated: false, -}; -const afterCheckpoint = { - name: "after_settlement", - at_ms: 50, - files: [], - effects: [], - truncated: false, -}; - -const capture = { - ...EMPTY_PROCESS_CAPTURE_EXAMPLE, - event_journal: [ - { capture_order: 0, collection: "filesystem_checkpoints", index: 0 }, - { capture_order: 1, collection: "lifecycle", index: 0 }, - { capture_order: 2, collection: "lifecycle", index: 1 }, - { capture_order: 3, collection: "filesystem_checkpoints", index: 1 }, - ], -} as const; - -const traceSpecification: ProcessTraceSpecification = { - events: [ - { - id: "before", - source: "filesystem", - exact: beforeCheckpoint, - cardinality: { kind: "required" }, - }, - { - id: "exit", - source: "lifecycle", - exact: { event: "exit", ...capture.exit }, - cardinality: { kind: "required" }, - }, - { - id: "settlement", - source: "lifecycle", - exact: { event: "settlement", ...capture.settlement }, - cardinality: { kind: "required" }, - }, - { - id: "after", - source: "filesystem", - exact: afterCheckpoint, - cardinality: { kind: "required" }, - }, - ], - language: { - kind: "finite_traces", - variants: [ - { - id: "normal", - trace: ["before", "exit", "settlement", "after"], - }, - ], - }, -}; +const { capture, traceSpecification } = processTraceCaptureFixture(); describe("declared trace comparison nonconformance", () => { it("does not call identical captures changed when both violate the language", () => { diff --git a/src/domain/process/processTraceComparison.test.ts b/src/domain/process/processTraceComparison.test.ts index caeaf7999..2207352e3 100644 --- a/src/domain/process/processTraceComparison.test.ts +++ b/src/domain/process/processTraceComparison.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vitest"; import { parseProcessCapture } from "./processCaptureParsing.js"; import type { ProcessTraceSpecification } from "./processTraceSpecification.js"; +import { processTraceSpecificationSchema as specificationSchema } from "./processTraceSpecification.js"; import { processTraceComparisonResultSchema } from "./processTraceEvaluation.js"; import { capture, @@ -100,6 +101,33 @@ describe("generic capture trace comparison", () => { right: { matched_variant: "two" }, }); }); + + it("compares a declared identifier the comparison result can represent", () => { + // The specification owns the trace identifier vocabulary and the result + // echoes those identifiers verbatim, so both must accept the same values + // rather than handing the caller a raw schema error for its own input. + const eventId = `e${"0".repeat(64)}`; + const specification: ProcessTraceSpecification = { + events: [ + { + id: eventId, + source: "terminal_raw", + exact: terminal, + cardinality: { kind: "required" }, + }, + ], + language: { + kind: "finite_traces", + variants: [{ id: "only", trace: [eventId] }], + }, + }; + expect(specificationSchema.safeParse(specification).success).toBe(true); + const left = capture(values(["terminal", "process"])); + expect(compareProcessTraces(left, left, specification)).toMatchObject({ + verdict: "equivalent", + left: { matched_variant: "only", raw_trace: [{ event_id: eventId }] }, + }); + }); }); describe("process trace constraints and evidence sufficiency", () => { diff --git a/src/domain/process/processTraceEvaluation.ts b/src/domain/process/processTraceEvaluation.ts index 51a2a15f8..7c232a480 100644 --- a/src/domain/process/processTraceEvaluation.ts +++ b/src/domain/process/processTraceEvaluation.ts @@ -13,13 +13,12 @@ import { import { canonicalTraceJson, processTraceCardinalityBounds, + processTraceIdentifierSchema, type ProcessTraceSpecification, } from "./processTraceSpecification.js"; -const identifierSchema = z.string().regex(/^[A-Za-z][A-Za-z0-9._\x2d]{0,63}$/u); - const matchedEventSchema = z.strictObject({ - event_id: identifierSchema, + event_id: processTraceIdentifierSchema, location: processObservationLocationSchema, }); @@ -32,7 +31,7 @@ const sideResultSchema = z.union([ z.strictObject({ ...sideResultShape, status: z.literal("pass"), - matched_variant: identifierSchema.nullable(), + matched_variant: processTraceIdentifierSchema.nullable(), }), z.strictObject({ ...sideResultShape, @@ -53,7 +52,7 @@ const diagnosticSchema = z.strictObject({ ]), side: z.enum(["left", "right"]), message: z.string(), - event_ids: z.array(identifierSchema), + event_ids: z.array(processTraceIdentifierSchema), locations: z.array(processObservationLocationSchema), }); diff --git a/src/domain/process/processTraceSpecification.test.ts b/src/domain/process/processTraceSpecification.test.ts index aeedf4d31..ab649d2aa 100644 --- a/src/domain/process/processTraceSpecification.test.ts +++ b/src/domain/process/processTraceSpecification.test.ts @@ -39,30 +39,110 @@ const specification = (): ProcessTraceSpecification => ({ }); describe("process trace specification", () => { - it("summarizes an incomplete language with its exact missing pair count", () => { - const events = Array.from({ length: 200 }, (_, index) => ({ - id: `e${String(index)}`, + it("reports independent declaration errors alongside a cycle", () => { + const base = specification(); + const result = processTraceSpecificationSchema.safeParse({ + ...base, + language: { + ...base.language, + happens_before: [ + { before: "ready", after: "worker" }, + { before: "worker", after: "ready" }, + ], + not_before: [{ event: "missing", anchor: "ready" }], + unordered_groups: [{ events: ["missing", "missing"] }], + prefix: ["missing"], + suffix: ["missing"], + }, + }); + if (result.success) throw new Error("Expected invalid trace declarations"); + expect(result.error.issues).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + message: "happens-before graph must be acyclic", + }), + expect.objectContaining({ + path: ["language", "not_before", 0, "event"], + }), + expect.objectContaining({ + path: ["language", "unordered_groups", 0, "events"], + }), + expect.objectContaining({ path: ["language", "prefix", 0] }), + expect.objectContaining({ path: ["language", "suffix", 0] }), + ]), + ); + }); + + it("accepts an acyclic order with shared successors and explicit unordered peers", () => { + const result = processTraceSpecificationSchema.parse({ + events: ["a", "b", "c", "d"].map((id) => ({ + id, + source: "lifecycle", + exact: { marker: id }, + })), + language: { + kind: "partial_order", + happens_before: [ + { before: "a", after: "b" }, + { before: "a", after: "c" }, + { before: "b", after: "d" }, + { before: "c", after: "d" }, + ], + unordered_groups: [{ events: ["b", "c"] }], + prefix: ["a"], + suffix: ["d"], + }, + }); + expect(result.language.kind).toBe("partial_order"); + }); +}); + +describe("process trace ordering validation", () => { + it("uses a unique topological order for transitive declarations and conflicts", () => { + const events = ["a", "b", "c"].map((id) => ({ + id, source: "lifecycle" as const, - exact: { fixture: index }, + exact: { marker: id }, cardinality: { kind: "optional" as const }, })); - const result = processTraceSpecificationSchema.safeParse({ + const accepted = processTraceSpecificationSchema.safeParse({ events, - language: { kind: "partial_order" }, + language: { + kind: "partial_order", + happens_before: [ + { before: "a", after: "b" }, + { before: "b", after: "c" }, + ], + }, }); - expect(result.success).toBe(false); - if (result.success) - throw new Error("Expected incomplete pair declarations"); - expect(result.error.issues).toEqual([ + expect(accepted.success).toBe(true); + + const rejected = processTraceSpecificationSchema.safeParse({ + events, + language: { + kind: "partial_order", + happens_before: [ + { before: "a", after: "b" }, + { before: "b", after: "c" }, + ], + not_before: [{ event: "a", anchor: "c" }], + unordered_groups: [{ events: ["a", "b", "c"] }], + }, + }); + if (rejected.success) throw new Error("Expected ordered pair conflicts"); + expect(rejected.error.issues).toEqual([ expect.objectContaining({ - path: ["language"], - message: - "19900 event pairs must be explicitly ordered or unordered; first undeclared pair: e0/e1", + path: ["language", "not_before", 0], + message: "not-before constraint conflicts with happens-before order", + }), + expect.objectContaining({ + path: ["language", "unordered_groups", 0], + message: "ordered events cannot also be declared unordered", }), ]); }); - it("counts only undeclared pairs after transitive, not-before and unordered relations", () => { + it("counts only undeclared pairs across transitive and disconnected relations", () => { const events = ["a", "b", "c", "d"].map((id) => ({ id, source: "lifecycle" as const, @@ -91,7 +171,7 @@ describe("process trace specification", () => { ]); }); - it("retains duplicate unordered-pair diagnostics for reversed declarations", () => { + it("reports one duplicate-pair diagnostic per overlapping group", () => { const result = processTraceSpecificationSchema.safeParse({ events: ["z", "a", "b"].map((id) => ({ id, @@ -101,7 +181,10 @@ describe("process trace specification", () => { })), language: { kind: "partial_order", - unordered_groups: [{ events: ["z", "a", "b"] }, { events: ["a", "z"] }], + unordered_groups: [ + { events: ["z", "a", "b"] }, + { events: ["b", "a", "z"] }, + ], }, }); expect(result.success).toBe(false); @@ -113,27 +196,84 @@ describe("process trace specification", () => { }), ]); }); +}); - it("rejects cycles, implicit ordering gaps, invalid ignores, and unsatisfiable variants", () => { - const base = specification(); - expect( - processTraceSpecificationSchema.safeParse({ - ...base, - language: { - kind: "partial_order", - happens_before: [ - { before: "ready", after: "worker" }, - { before: "worker", after: "ready" }, - ], +describe("malformed process trace declarations", () => { + it("preserves independent diagnostics when event ids are duplicated", () => { + const result = processTraceSpecificationSchema.safeParse({ + events: [ + { + id: "a", + source: "lifecycle", + exact: { fixture: "first" }, + cardinality: { kind: "optional" }, }, - }).success, - ).toBe(false); - expect( - processTraceSpecificationSchema.safeParse({ - ...base, - language: { kind: "partial_order" }, - }).success, - ).toBe(false); + { + id: "a", + source: "lifecycle", + exact: { fixture: "second" }, + cardinality: { kind: "optional" }, + }, + ], + language: { + kind: "partial_order", + unordered_groups: [{ events: ["a", "b"] }], + }, + }); + expect(result.success).toBe(false); + if (result.success) throw new Error("Expected a duplicate event id"); + expect(result.error.issues).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + path: ["events", 1, "id"], + message: "event ids must be unique", + }), + expect.objectContaining({ + path: ["language", "unordered_groups", 0, "events", 1], + message: "unknown event id: b", + }), + ]), + ); + }); + + it("keeps reachability diagnostics for unknown referenced successors", () => { + const result = processTraceSpecificationSchema.safeParse({ + events: ["a", "b"].map((id) => ({ + id, + source: "lifecycle", + exact: { fixture: id }, + cardinality: { kind: "optional" }, + })), + language: { + kind: "partial_order", + happens_before: [{ before: "a", after: "missing" }], + not_before: [{ event: "a", anchor: "missing" }], + }, + }); + expect(result.success).toBe(false); + if (result.success) throw new Error("Expected an unknown event reference"); + expect(result.error.issues).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + path: ["language", "happens_before", 0, "after"], + message: "unknown event id: missing", + }), + expect.objectContaining({ + path: ["language", "not_before", 0, "anchor"], + message: "unknown event id: missing", + }), + expect.objectContaining({ + path: ["language", "not_before", 0], + message: "not-before constraint conflicts with happens-before order", + }), + ]), + ); + }); +}); + +describe("finite trace specification validation", () => { + it("rejects invalid ignores and unsatisfiable variants", () => { + const base = specification(); expect( processTraceSpecificationSchema.safeParse({ events: [ diff --git a/src/domain/process/processTraceSpecification.ts b/src/domain/process/processTraceSpecification.ts index 61ace7ca1..4e28774e0 100644 --- a/src/domain/process/processTraceSpecification.ts +++ b/src/domain/process/processTraceSpecification.ts @@ -9,7 +9,16 @@ import { processObservationSourceSchema, } from "./processObservation.js"; -const identifierSchema = z.string().regex(IDENTIFIER_PATTERN); +/** + * A declared trace, event or variant identifier. The specification owns this + * vocabulary and the comparison result echoes those identifiers verbatim, so + * the result module must reuse this schema rather than restate the pattern: + * two bounds on the same identifier would reject the result of an accepted + * specification. + */ +export const processTraceIdentifierSchema = z + .string() + .regex(IDENTIFIER_PATTERN); const cardinalitySchema = z.discriminatedUnion("kind", [ z.strictObject({ kind: z.literal("required") }), @@ -31,7 +40,7 @@ const cardinalitySchema = z.discriminatedUnion("kind", [ ]); const eventDeclarationSchema = z.strictObject({ - id: identifierSchema, + id: processTraceIdentifierSchema, source: processObservationSourceSchema, exact: jsonValueSchema, ignore_fields: z @@ -56,29 +65,31 @@ const partialOrderLanguageSchema = z.strictObject({ happens_before: z .array( z.strictObject({ - before: identifierSchema, - after: identifierSchema, + before: processTraceIdentifierSchema, + after: processTraceIdentifierSchema, }), ) .default([]), not_before: z .array( z.strictObject({ - event: identifierSchema, - anchor: identifierSchema, + event: processTraceIdentifierSchema, + anchor: processTraceIdentifierSchema, }), ) .default([]), unordered_groups: z - .array(z.strictObject({ events: z.array(identifierSchema).min(2) })) + .array( + z.strictObject({ events: z.array(processTraceIdentifierSchema).min(2) }), + ) .default([]), - prefix: z.array(identifierSchema).default([]), - suffix: z.array(identifierSchema).default([]), + prefix: z.array(processTraceIdentifierSchema).default([]), + suffix: z.array(processTraceIdentifierSchema).default([]), }); const finiteTraceTokenSchema = z.union([ - identifierSchema, - z.strictObject({ unordered: z.array(identifierSchema).min(2) }), + processTraceIdentifierSchema, + z.strictObject({ unordered: z.array(processTraceIdentifierSchema).min(2) }), ]); const finiteTraceLanguageSchema = z.strictObject({ @@ -86,7 +97,7 @@ const finiteTraceLanguageSchema = z.strictObject({ variants: z .array( z.strictObject({ - id: identifierSchema, + id: processTraceIdentifierSchema, trace: z.array(finiteTraceTokenSchema), }), ) @@ -106,6 +117,17 @@ export type ProcessTraceSpecification = z.infer< >; type PartialOrderLanguage = z.infer; +type AcyclicGraphFacts = + | { + readonly kind: "total-order"; + readonly rank: ReadonlyMap; + } + | { + readonly kind: "partial-order"; + readonly reverseAdjacency: ReadonlyMap>; + }; +type GraphFacts = { readonly kind: "cyclic" } | AcyclicGraphFacts; + export const canonicalTraceJson = (value: unknown): string => { const serialized = canonicalize(value); if (serialized === undefined) @@ -170,7 +192,6 @@ const validateNotBefore = ( language: PartialOrderLanguage, context: z.RefinementCtx, known: ReadonlySet, - reachable: ReadonlyMap>, ): ReadonlySet => { const pairs = new Set(); for (const [index, constraint] of language.not_before.entries()) { @@ -191,76 +212,101 @@ const validateNotBefore = ( path, }); pairs.add(key); - if (reachable.get(constraint.event)?.has(constraint.anchor) === true) - context.addIssue({ - code: "custom", - message: "not-before constraint conflicts with happens-before order", - path, - }); } return pairs; }; -const graphHasCycle = ( +const classifyGraph = ( ids: readonly string[], adjacency: ReadonlyMap>, -): boolean => { - const active = new Set(); - const complete = new Set(); - const visit = (current: string): boolean => { - if (active.has(current)) return true; - if (complete.has(current)) return false; - active.add(current); - const cyclic = [...(adjacency.get(current) ?? [])].some(visit); - active.delete(current); - complete.add(current); - return cyclic; - }; - return ids.some(visit); -}; - -const computeReachability = ( - ids: readonly string[], - adjacency: ReadonlyMap>, -): ReadonlyMap> => { - const reachable = new Map>(); - for (const origin of ids) { - const seen = new Set(); - const pending = [...(adjacency.get(origin) ?? [])]; - while (pending.length > 0) { - const current = pending.pop(); - if (current === undefined || seen.has(current)) continue; - seen.add(current); - pending.push(...(adjacency.get(current) ?? [])); +): GraphFacts => { + const incoming = new Map(ids.map((id) => [id, 0])); + let hasUnknownSuccessor = false; + for (const successors of adjacency.values()) + for (const successor of successors) { + const count = incoming.get(successor); + if (count === undefined) hasUnknownSuccessor = true; + else incoming.set(successor, count + 1); + } + const ready = [...incoming].flatMap(([id, count]) => + count === 0 ? [id] : [], + ); + const order: string[] = []; + let unique = true; + while (ready.length > 0) { + if (ready.length !== 1) unique = false; + const current = ready.pop(); + if (current === undefined) continue; + order.push(current); + for (const successor of adjacency.get(current) ?? []) { + const count = incoming.get(successor); + if (count === undefined) continue; + incoming.set(successor, count - 1); + if (count === 1) ready.push(successor); } - reachable.set(origin, seen); } - return reachable; + if (order.length !== incoming.size) return { kind: "cyclic" }; + if (unique && order.length === ids.length && !hasUnknownSuccessor) { + return { + kind: "total-order", + rank: new Map(order.map((id, index) => [id, index])), + }; + } + const reverseAdjacency = new Map( + [...incoming.keys()].map((id) => [id, new Set()]), + ); + for (const [before, successors] of adjacency) + for (const after of successors) reverseAdjacency.get(after)?.add(before); + return { kind: "partial-order", reverseAdjacency }; }; -const isOrdered = ( - reachable: ReadonlyMap>, - left: string, - right: string, -): boolean => - reachable.get(left)?.has(right) === true || - reachable.get(right)?.has(left) === true; - -type OrderingRelations = { - readonly reachable: ReadonlyMap>; - readonly notBeforePairs: ReadonlySet; +const collectReachable = ( + origin: string, + adjacency: ReadonlyMap>, +): ReadonlySet => { + const seen = new Set(); + const pending = [...(adjacency.get(origin) ?? [])]; + while (pending.length > 0) { + const current = pending.pop(); + if (current === undefined || seen.has(current)) continue; + seen.add(current); + for (const successor of adjacency.get(current) ?? []) + pending.push(successor); + } + return seen; }; const validateUnorderedGroups = ( language: PartialOrderLanguage, context: z.RefinementCtx, known: ReadonlySet, - relations: OrderingRelations, -): ReadonlySet => { - const pairs = new Set(); +): { + readonly groups: readonly ReadonlySet[]; + hasPair(left: string, right: string): boolean; + markDeclaredPairConflicts( + pairs: ReadonlySet, + conflicts: boolean[], + ): void; + markSharedGroups(left: string, right: string, conflicts: boolean[]): void; +} => { + const memberships = new Map>(); + const groups: Set[] = []; + const repeatedMemberships = new Map>(); for (const [groupIndex, group] of language.unordered_groups.entries()) { const path = ["language", "unordered_groups", groupIndex]; - if (new Set(group.events).size !== group.events.length) + const uniqueIds = new Set(); + const repeatedIds = new Set(); + for (const id of group.events) { + if (uniqueIds.has(id)) repeatedIds.add(id); + else uniqueIds.add(id); + } + groups.push(uniqueIds); + for (const id of repeatedIds) { + const groupIndexes = repeatedMemberships.get(id) ?? new Set(); + groupIndexes.add(groupIndex); + repeatedMemberships.set(id, groupIndexes); + } + if (uniqueIds.size !== group.events.length) context.addIssue({ code: "custom", message: "unordered groups must not repeat event ids", @@ -268,46 +314,136 @@ const validateUnorderedGroups = ( }); for (const [eventIndex, id] of group.events.entries()) addReferenceIssue(context, known, id, [...path, "events", eventIndex]); - for (const [leftIndex, leftId] of group.events.entries()) { - for ( - let rightIndex = leftIndex + 1; - rightIndex < group.events.length; - rightIndex++ - ) { - const rightId = group.events[rightIndex]; - if (rightId === undefined) continue; - const key = pairKey(leftId, rightId); - if (pairs.has(key)) - context.addIssue({ - code: "custom", - message: "unordered event pairs must be declared once", - path, - }); - pairs.add(key); - if ( - isOrdered(relations.reachable, leftId, rightId) || - relations.notBeforePairs.has(key) - ) - context.addIssue({ - code: "custom", - message: "ordered events cannot also be declared unordered", - path, - }); - } + const overlaps = new Map(); + for (const id of uniqueIds) { + const priorGroups = memberships.get(id) ?? new Set(); + for (const prior of priorGroups) + overlaps.set(prior, (overlaps.get(prior) ?? 0) + 1); + priorGroups.add(groupIndex); + memberships.set(id, priorGroups); } + if ([...overlaps.values()].some((count) => count > 1)) + context.addIssue({ + code: "custom", + message: "unordered event pairs must be declared once", + path, + }); } - return pairs; + const markSharedGroups = ( + left: string, + right: string, + conflicts: boolean[], + ): void => { + if (left === right) { + for (const groupIndex of repeatedMemberships.get(left) ?? []) + conflicts[groupIndex] = true; + return; + } + const rightGroups = memberships.get(right); + for (const group of memberships.get(left) ?? []) + if (rightGroups?.has(group) === true) conflicts[group] = true; + }; + return { + groups, + hasPair(left, right) { + if (left === right) return memberships.has(left); + const rightGroups = memberships.get(right); + for (const group of memberships.get(left) ?? []) + if (rightGroups?.has(group) === true) return true; + return false; + }, + markDeclaredPairConflicts(pairs, conflicts) { + for (const key of pairs) { + const separator = key.indexOf("\0"); + const left = key.slice(0, separator); + const right = key.slice(separator + 1); + markSharedGroups(left, right, conflicts); + } + }, + markSharedGroups, + }; }; -const validateCompletePairDeclarations = ( +const validateTotalOrderRelations = ( + language: PartialOrderLanguage, + graph: Extract, + unorderedGroups: ReturnType, + notBeforePairs: ReadonlySet, + context: z.RefinementCtx, +): void => { + for (const [index, constraint] of language.not_before.entries()) { + const before = graph.rank.get(constraint.event); + const after = graph.rank.get(constraint.anchor); + if (before !== undefined && after !== undefined && before < after) + context.addIssue({ + code: "custom", + message: "not-before constraint conflicts with happens-before order", + path: ["language", "not_before", index], + }); + } + + const conflicts = new Array(language.unordered_groups.length).fill( + false, + ); + for (const [groupIndex, group] of unorderedGroups.groups.entries()) { + let comparableEvents = 0; + for (const id of group) + if (graph.rank.has(id) && ++comparableEvents === 2) { + conflicts[groupIndex] = true; + break; + } + } + unorderedGroups.markDeclaredPairConflicts(notBeforePairs, conflicts); + addUnorderedConflictIssues(conflicts, context); +}; + +const addUnorderedConflictIssues = ( + conflicts: readonly boolean[], + context: z.RefinementCtx, +): void => { + for (const [groupIndex, conflict] of conflicts.entries()) + if (conflict) + context.addIssue({ + code: "custom", + message: "ordered events cannot also be declared unordered", + path: ["language", "unordered_groups", groupIndex], + }); +}; + +const validatePartialOrderRelations = ( ids: readonly string[], - relations: OrderingRelations, - unorderedPairs: ReadonlySet, + language: PartialOrderLanguage, + adjacency: ReadonlyMap>, + graph: Extract, + unorderedGroups: ReturnType, + notBeforePairs: ReadonlySet, context: z.RefinementCtx, ): void => { let missingPairCount = 0; let firstMissingPair = ""; + const groupConflicts = new Array( + language.unordered_groups.length, + ).fill(false); + unorderedGroups.markDeclaredPairConflicts(notBeforePairs, groupConflicts); + const notBeforeConflictFlags = new Uint8Array(language.not_before.length); + const constraintsBySource = new Map(); + for (const [index, constraint] of language.not_before.entries()) { + const indexes = constraintsBySource.get(constraint.event) ?? []; + indexes.push(index); + constraintsBySource.set(constraint.event, indexes); + } + + // Keep only one origin's forward and backward closure live at a time. Pair + // iteration stays in declaration order so the count and first missing pair + // retain the established diagnostic semantics. for (const [leftIndex, leftId] of ids.entries()) { + const forward = collectReachable(leftId, adjacency); + const backward = collectReachable(leftId, graph.reverseAdjacency); + for (const constraintIndex of constraintsBySource.get(leftId) ?? []) { + const constraint = language.not_before[constraintIndex]; + if (constraint !== undefined && forward.has(constraint.anchor)) + notBeforeConflictFlags[constraintIndex] = 1; + } for ( let rightIndex = leftIndex + 1; rightIndex < ids.length; @@ -315,14 +451,32 @@ const validateCompletePairDeclarations = ( ) { const rightId = ids[rightIndex]; if (rightId === undefined) continue; - if (isOrdered(relations.reachable, leftId, rightId)) continue; + const sameEvent = leftId === rightId; + const ordered = + !sameEvent && (forward.has(rightId) || backward.has(rightId)); const key = pairKey(leftId, rightId); - if (!relations.notBeforePairs.has(key) && !unorderedPairs.has(key)) { + const notBefore = notBeforePairs.has(key); + const unordered = unorderedGroups.hasPair(leftId, rightId); + if (ordered || notBefore) { + if (!sameEvent) + unorderedGroups.markSharedGroups(leftId, rightId, groupConflicts); + } + if (!ordered && !notBefore && !unordered) { if (missingPairCount === 0) firstMissingPair = `${leftId}/${rightId}`; missingPairCount++; } } } + + for (const [index, conflict] of notBeforeConflictFlags.entries()) + if (conflict === 1) + context.addIssue({ + code: "custom", + message: "not-before constraint conflicts with happens-before order", + path: ["language", "not_before", index], + }); + addUnorderedConflictIssues(groupConflicts, context); + if (missingPairCount > 0) context.addIssue({ code: "custom", @@ -342,27 +496,44 @@ const validatePartialOrder = ( const ids = specification.events.map(({ id }) => id); const known = new Set(ids); const adjacency = buildAdjacency(specification.language, context, known); - if (graphHasCycle(ids, adjacency)) + const graph = classifyGraph(ids, adjacency); + if (graph.kind === "cyclic") context.addIssue({ code: "custom", message: "happens-before graph must be acyclic", path: ["language"], }); - const reachable = computeReachability(ids, adjacency); const notBeforePairs = validateNotBefore( specification.language, context, known, - reachable, ); - const relations = { reachable, notBeforePairs }; - const unorderedPairs = validateUnorderedGroups( + const unorderedGroups = validateUnorderedGroups( specification.language, context, known, - relations, ); - validateCompletePairDeclarations(ids, relations, unorderedPairs, context); + // Preserve independent declaration diagnostics on cyclic input. Computing + // all pair relations cannot establish a valid partial order in that case. + if (graph.kind === "total-order") { + validateTotalOrderRelations( + specification.language, + graph, + unorderedGroups, + notBeforePairs, + context, + ); + } else if (graph.kind === "partial-order") { + validatePartialOrderRelations( + ids, + specification.language, + adjacency, + graph, + unorderedGroups, + notBeforePairs, + context, + ); + } for (const [kind, values] of [ ["prefix", specification.language.prefix], ["suffix", specification.language.suffix], diff --git a/src/domain/qlogCapture.ts b/src/domain/qlogCapture.ts new file mode 100644 index 000000000..575cf2a60 --- /dev/null +++ b/src/domain/qlogCapture.ts @@ -0,0 +1,76 @@ +import { z } from "zod"; + +const decimal = z.string().regex(/^(0|[1-9][0-9]*)$/u); +const unsignedFact = z.discriminatedUnion("state", [ + z.strictObject({ state: z.literal("reported"), value: decimal }), + z.strictObject({ + state: z.literal("unknown"), + reason: z.literal("omitted-null-or-redacted"), + }), +]); +const traceLocation = z.discriminatedUnion("kind", [ + z.strictObject({ kind: z.literal("json-pointer"), pointer: z.string() }), + z.strictObject({ + kind: z.literal("unknown"), + reason: z.literal("explicit-sensitive-value"), + }), +]); + +/** Exact, source-bound transport facts; coverage never establishes network completeness. */ +export const qlogCaptureFactsSchema = z.strictObject({ + profile: z.literal("aioquic-1.5.0-json-0.3"), + scope: z.literal("all-recorded-events-before-selection"), + body_bytes: z.literal("not-reported"), + clock: z.strictObject({ + unit: z.literal("milliseconds"), + domain: z.literal("unix-epoch"), + basis: z.literal("selected-aioquic-profile-not-producer-authentication"), + }), + traces: z.array( + z.strictObject({ + trace_index: z.number().int().nonnegative(), + location: traceLocation, + event_count: z.number().int().nonnegative(), + odcid: z.string().nullable(), + vantage_point: z.enum(["client", "server"]).nullable(), + incomplete_fact_records: z.array(z.number().int().nonnegative()), + loss_declarations: z.array( + z.strictObject({ + record_ordinal: z.number().int().nonnegative(), + confidence: z.literal("observed"), + packet_number: unsignedFact, + packet_type: z.string().nullable(), + packet_number_space: z + .enum(["initial", "handshake", "application"]) + .nullable(), + }), + ), + streams: z.array( + z.strictObject({ + stream_id: decimal, + direction: z.enum(["sent", "received"]), + confidence: z.literal("derived"), + scope: z.literal("observed-stream-frame-ranges"), + contributions: z.array( + z.strictObject({ + record_ordinal: z.number().int().nonnegative(), + frame_index: z.number().int().nonnegative(), + offset: decimal, + length: decimal, + fin: z.boolean().nullable(), + }), + ), + covered_ranges: z.array( + z.strictObject({ start: decimal, end: decimal }), + ), + unique_bytes: decimal, + frame_length_sum: decimal, + repeated_bytes: decimal, + reported_final_sizes: z.array(decimal), + }), + ), + }), + ), +}); + +export type QlogCaptureFacts = z.output; diff --git a/src/domain/reconstructionCoverage.test.ts b/src/domain/reconstructionCoverage.test.ts index 4c0b41831..ac7552571 100644 --- a/src/domain/reconstructionCoverage.test.ts +++ b/src/domain/reconstructionCoverage.test.ts @@ -286,14 +286,18 @@ describe("reconstruction coverage verifier selection", () => { }); }); -describe("reconstruction coverage verifier result ordering", () => { - it("preserves the first input result when verifier timestamps tie", () => { +describe("reconstruction coverage conflicting latest verifier observations", () => { + it("keeps conflicting tied assessments unknown regardless of input order", () => { const workspace = completeReconstructionCoverageData(); const result = workspace.verifier_results[0]; const boundary = workspace.boundaries[0]; if (result === undefined || boundary === undefined) throw new Error("Expected complete reconstruction coverage fixture"); - const failed = { ...result, status: "fail" as const }; + const failed = { + ...result, + status: "fail" as const, + evidence_ids: [reconstructionCoverageEvidenceId("1")], + }; const firstPass = createReconstructionCoverageData({ ...workspace, verifier_results: [result, failed], @@ -303,23 +307,109 @@ describe("reconstruction coverage verifier result ordering", () => { verifier_results: [failed, result], }); + const firstPassResult = evaluateReconstructionClosure( + firstPass, + boundary.boundary_id, + RECONSTRUCTION_COVERAGE_NOW, + ); + const firstFailResult = evaluateReconstructionClosure( + firstFail, + boundary.boundary_id, + RECONSTRUCTION_COVERAGE_NOW, + ); + expect(firstPassResult).toEqual(firstFailResult); + expect(firstPassResult).toMatchObject({ + status: "unknown", + reasons: [ + expect.objectContaining({ + code: "verifier-result-ambiguous", + subject_id: "claim.cli.help", + }), + ], + }); + expect(firstPassResult.evidence_ids).toEqual( + expect.arrayContaining([ + reconstructionCoverageEvidenceId("3"), + reconstructionCoverageEvidenceId("1"), + ]), + ); + }); +}); + +describe("reconstruction coverage equivalent latest verifier observations", () => { + it("coalesces equivalent equal-instant observations and retains all evidence", () => { + const workspace = completeReconstructionCoverageData(); + const result = workspace.verifier_results[0]; + const boundary = workspace.boundaries[0]; + if (result === undefined || boundary === undefined) + throw new Error("Expected complete reconstruction coverage fixture"); + const first = { + ...result, + observed_at: "2026-07-16T11:00:00.123456789012345678900Z", + }; + const equivalent = { + ...first, + observed_at: "2026-07-16T06:00:00.1234567890123456789-05:00", + covered_claim_ids: [...result.covered_claim_ids].reverse(), + covered_dimensions: [...result.covered_dimensions].reverse(), + artifact_sha256s: [...result.artifact_sha256s].reverse(), + owner_sha256s: [...result.owner_sha256s].reverse(), + evidence_ids: [reconstructionCoverageEvidenceId("1")], + }; + const forward = createReconstructionCoverageData({ + ...workspace, + verifier_results: [first, equivalent], + }); + const reversed = createReconstructionCoverageData({ + ...workspace, + verifier_results: [equivalent, first], + }); + const forwardResult = evaluateReconstructionClosure( + forward, + boundary.boundary_id, + RECONSTRUCTION_COVERAGE_NOW, + ); + const reversedResult = evaluateReconstructionClosure( + reversed, + boundary.boundary_id, + RECONSTRUCTION_COVERAGE_NOW, + ); + + expect(forwardResult).toEqual(reversedResult); + expect(forwardResult.status).toBe("ready"); + expect(forwardResult.evidence_ids).toEqual( + expect.arrayContaining([ + reconstructionCoverageEvidenceId("3"), + reconstructionCoverageEvidenceId("1"), + ]), + ); + }); +}); + +describe("reconstruction coverage verifier timestamp selection", () => { + it("lets a later unambiguous observation supersede an older tie", () => { + const workspace = completeReconstructionCoverageData(); + const result = workspace.verifier_results[0]; + const boundary = workspace.boundaries[0]; + if (result === undefined || boundary === undefined) + throw new Error("Expected complete reconstruction coverage fixture"); + const failed = { ...result, status: "fail" as const }; + const latestPass = { + ...result, + observed_at: "2026-07-16T11:30:00.000Z", + }; + const changed = createReconstructionCoverageData({ + ...workspace, + verifier_results: [result, failed, latestPass], + }); + expect( evaluateReconstructionClosure( - firstPass, - boundary.boundary_id, - RECONSTRUCTION_COVERAGE_NOW, - ).status, - ).toBe("ready"); - expect( - evaluateReconstructionClosure( - firstFail, + changed, boundary.boundary_id, RECONSTRUCTION_COVERAGE_NOW, ), - ).toMatchObject({ - status: "failed", - reasons: [expect.objectContaining({ code: "verifier-failed" })], - }); + ).toMatchObject({ status: "ready", reasons: [] }); }); it("orders offset-bearing verifier timestamps chronologically", () => { @@ -352,6 +442,68 @@ describe("reconstruction coverage verifier result ordering", () => { }); }); + it("selects the later result when timestamps differ below millisecond precision", () => { + const workspace = completeReconstructionCoverageData(); + const result = workspace.verifier_results[0]; + if (result === undefined) + throw new Error("Expected fixture verifier result"); + const changed = createReconstructionCoverageData({ + ...workspace, + verifier_results: [ + { ...result, observed_at: "2026-07-16T11:00:00.1231Z" }, + { + ...result, + observed_at: "2026-07-16T11:00:00.1239Z", + status: "fail", + }, + ], + }); + + expect( + evaluateReconstructionClosure( + changed, + "replacement.cli", + RECONSTRUCTION_COVERAGE_NOW, + ), + ).toMatchObject({ + status: "failed", + reasons: [expect.objectContaining({ code: "verifier-failed" })], + }); + }); +}); + +describe("reconstruction coverage verifier future timestamps", () => { + it("treats an observation beyond millisecond-precision now as future", () => { + const workspace = completeReconstructionCoverageData(); + const result = workspace.verifier_results[0]; + if (result === undefined) + throw new Error("Expected fixture verifier result"); + const changed = createReconstructionCoverageData({ + ...workspace, + verifier_results: [ + { ...result, observed_at: "2026-07-16T12:00:00.1239Z" }, + ], + }); + + expect( + evaluateReconstructionClosure( + changed, + "replacement.cli", + Date.parse("2026-07-16T12:00:00.123Z") + 0.5, + ), + ).toMatchObject({ + status: "unknown", + reasons: [expect.objectContaining({ code: "verifier-result-stale" })], + }); + }); + + it("rejects a non-finite evaluation clock", () => { + const workspace = completeReconstructionCoverageData(); + expect(() => + evaluateReconstructionClosure(workspace, "replacement.cli", Number.NaN), + ).toThrow("Expected finite epoch milliseconds."); + }); + it("rejects verifier observations from the future", () => { const workspace = completeReconstructionCoverageData(); const result = workspace.verifier_results[0]; diff --git a/src/domain/reconstructionCoverage.ts b/src/domain/reconstructionCoverage.ts index 485b66a5a..04913d4ae 100644 --- a/src/domain/reconstructionCoverage.ts +++ b/src/domain/reconstructionCoverage.ts @@ -19,7 +19,10 @@ import { } from "./reconstructionCoverageEvaluation.js"; import { digestSchema } from "./../domain/digests.js"; import { prefixedDigestSchema } from "./../domain/digests.js"; -import { offsetDateTimeSchema } from "./offsetDateTime.js"; +import { + offsetDateTimeInstantFromEpochMilliseconds, + offsetDateTimeSchema, +} from "./offsetDateTime.js"; const evidenceIdSchema = prefixedDigestSchema("ev"); const stableIdSchema = z @@ -213,6 +216,7 @@ const closureReasonSchema = z.strictObject({ "verifier-result-missing", "verifier-result-stale", "verifier-result-incompatible", + "verifier-result-ambiguous", "verifier-failed", "verifier-unknown", "active-unknown", @@ -274,10 +278,12 @@ export const evaluateReconstructionClosure = ( ); if (boundary === undefined) throw new TypeError(`Unknown reconstruction boundary: ${boundaryId}`); + const nowInstant = offsetDateTimeInstantFromEpochMilliseconds(nowEpochMs); const context: ReconstructionEvaluationContext = { coverage, boundary, nowEpochMs, + nowInstant, reasons: [], evidenceIds: new Set(), }; @@ -394,6 +400,7 @@ const closureStatus = ( [ "verifier-result-stale", "verifier-result-incompatible", + "verifier-result-ambiguous", "verifier-unknown", "active-unknown", "owner-path-unknown", diff --git a/src/domain/reconstructionCoverageEvaluation.ts b/src/domain/reconstructionCoverageEvaluation.ts index ea82e5636..f8a56b261 100644 --- a/src/domain/reconstructionCoverageEvaluation.ts +++ b/src/domain/reconstructionCoverageEvaluation.ts @@ -3,6 +3,16 @@ import type { ReconstructionCoverageData, ReconstructionVerifierContract, } from "./reconstructionCoverage.js"; +import { + compareOffsetDateTimeInstants, + offsetDateTimeInstantFromEpochMilliseconds, + type OffsetDateTimeInstant, +} from "./offsetDateTime.js"; +import { + latestVerifierObservationsByVerifier, + sameVerifierAssessment, + type VerifierObservation, +} from "./reconstructionCoverageVerifierResults.js"; export const recommendedReconstructionProbes = ( reasons: readonly ClosureReason[], @@ -29,6 +39,7 @@ export interface ReconstructionEvaluationContext { readonly coverage: ReconstructionCoverageData; readonly boundary: Boundary; readonly nowEpochMs: number; + readonly nowInstant: OffsetDateTimeInstant; readonly reasons: ClosureReason[]; readonly evidenceIds: Set; } @@ -184,7 +195,7 @@ interface VerifierIndexes { >; readonly latestResultsByVerifier: ReadonlyMap< string, - ReconstructionCoverageData["verifier_results"][number] + readonly VerifierObservation[] >; readonly artifactDigests: ReadonlySet; readonly ownerDigests: ReadonlySet; @@ -213,20 +224,6 @@ const createVerifierIndexes = ( contractsByClaim.set(claimId, contracts); } - const latestResultsByVerifier = new Map< - string, - ReconstructionCoverageData["verifier_results"][number] - >(); - for (const result of coverage.verifier_results) { - const latest = latestResultsByVerifier.get(result.verifier_id); - // Stable descending sort used to choose the first input record on ties. - if ( - latest === undefined || - Date.parse(result.observed_at) > Date.parse(latest.observed_at) - ) - latestResultsByVerifier.set(result.verifier_id, result); - } - const ownersBySurface = new Map< string, ReconstructionCoverageData["owners"][number][] @@ -239,7 +236,9 @@ const createVerifierIndexes = ( return { contractsByClaim, - latestResultsByVerifier, + latestResultsByVerifier: latestVerifierObservationsByVerifier( + coverage.verifier_results, + ), artifactDigests: new Set( coverage.artifacts.map(({ artifact_sha256: value }) => value), ), @@ -260,8 +259,10 @@ const evaluateVerifierResult = ( contract: ReconstructionVerifierContract, indexes: VerifierIndexes, ): void => { - const result = indexes.latestResultsByVerifier.get(contract.verifier_id); - if (result === undefined) { + const latestResults = indexes.latestResultsByVerifier.get( + contract.verifier_id, + ); + if (latestResults === undefined) { addReason( context, "verifier-result-missing", @@ -270,7 +271,26 @@ const evaluateVerifierResult = ( ); return; } - addEvidence(context, result.evidence_ids); + addEvidence( + context, + latestResults.flatMap(({ result }) => result.evidence_ids), + ); + const latest = latestResults[0]; + if (latest === undefined) return; + const { result } = latest; + if ( + !latestResults.every((candidate) => + sameVerifierAssessment(result, candidate.result), + ) + ) { + addReason( + context, + "verifier-result-ambiguous", + claim.claim_id, + "Latest verifier observations have conflicting assessment content.", + ); + return; + } if (!verifierResultIsCompatible(claim, contract, result, indexes)) { addReason( context, @@ -280,10 +300,14 @@ const evaluateVerifierResult = ( ); return; } - const observedAt = Date.parse(result.observed_at); + const cutoffEpochMs = context.nowEpochMs - contract.max_age_ms; if ( - observedAt > context.nowEpochMs || - context.nowEpochMs - observedAt > contract.max_age_ms + compareOffsetDateTimeInstants(latest.instant, context.nowInstant) > 0 || + (cutoffEpochMs >= -Number.MAX_SAFE_INTEGER && + compareOffsetDateTimeInstants( + latest.instant, + offsetDateTimeInstantFromEpochMilliseconds(cutoffEpochMs), + ) < 0) ) { addReason( context, diff --git a/src/domain/reconstructionCoverageVerifierResults.ts b/src/domain/reconstructionCoverageVerifierResults.ts new file mode 100644 index 000000000..de7f55874 --- /dev/null +++ b/src/domain/reconstructionCoverageVerifierResults.ts @@ -0,0 +1,57 @@ +import type { ReconstructionCoverageData } from "./reconstructionCoverage.js"; +import { uniqueSorted } from "./canonicalOrdering.js"; +import { + compareOffsetDateTimeInstants, + parseOffsetDateTimeInstant, + type OffsetDateTimeInstant, +} from "./offsetDateTime.js"; + +type VerifierResult = ReconstructionCoverageData["verifier_results"][number]; + +export interface VerifierObservation { + readonly result: VerifierResult; + readonly instant: OffsetDateTimeInstant; +} + +/** Index each verifier's latest timestamp group without relying on array order. */ +export const latestVerifierObservationsByVerifier = ( + results: readonly VerifierResult[], +): ReadonlyMap => { + const latestByVerifier = new Map(); + for (const result of results) { + const observation = { + result, + instant: parseOffsetDateTimeInstant(result.observed_at), + }; + const latest = latestByVerifier.get(result.verifier_id); + const latestInstant = latest?.[0]?.instant; + const comparison = + latestInstant === undefined + ? 1 + : compareOffsetDateTimeInstants(observation.instant, latestInstant); + if (latest === undefined || comparison > 0) + latestByVerifier.set(result.verifier_id, [observation]); + else if (comparison === 0) latest.push(observation); + } + return latestByVerifier; +}; + +/** Compare assessment content while excluding timestamp spelling and provenance. */ +export const sameVerifierAssessment = ( + left: VerifierResult, + right: VerifierResult, +): boolean => + verifierAssessmentIdentity(left) === verifierAssessmentIdentity(right); + +const verifierAssessmentIdentity = (result: VerifierResult): string => + JSON.stringify({ + verifier_id: result.verifier_id, + contract_sha256: result.contract_sha256, + status: result.status, + covered_claim_ids: uniqueSorted(result.covered_claim_ids), + covered_dimensions: uniqueSorted(result.covered_dimensions), + artifact_sha256s: uniqueSorted(result.artifact_sha256s), + owner_sha256s: uniqueSorted(result.owner_sha256s), + normalization_sha256: result.normalization_sha256, + repeats: result.repeats, + }); diff --git a/src/domain/referenceSourceImportParsing.ts b/src/domain/referenceSourceImportParsing.ts index 998e368c4..18f76a358 100644 --- a/src/domain/referenceSourceImportParsing.ts +++ b/src/domain/referenceSourceImportParsing.ts @@ -11,6 +11,7 @@ import { parserPluginsForPath, } from "./javascript/javascriptSourceParser.js"; import { unshadowedReferenceSourceRequireCalls } from "./referenceSourceRequireBindings.js"; +import { isRelativeJavaScriptModuleSpecifier } from "./javascript/javascriptModuleSpecifier.js"; import { isCallExpression, isExportAllDeclaration, @@ -60,7 +61,8 @@ export interface ReferenceSourceImportParseResult { readonly limitations: readonly string[]; } -const codeSourceLanguages = new Set(["JavaScript", "TypeScript", "JSX", "TSX"]); +export const PARSEABLE_REFERENCE_SOURCE_LANGUAGES: ReadonlySet = + new Set(["JavaScript", "TypeScript", "JSX", "TSX"]); const safeModuleName = (node: Node | null | undefined): string | undefined => { if (isStringLiteral(node)) return node.value; @@ -70,9 +72,11 @@ const safeModuleName = (node: Node | null | undefined): string | undefined => { const resolveSpecifier = ( specifier: string, ): ReferenceSourceImportResolution => { - if (specifier.startsWith(".") || specifier.startsWith("/")) return "internal"; - if (specifier.startsWith("node:") || specifier.startsWith("data:")) - return "external"; + if ( + isRelativeJavaScriptModuleSpecifier(specifier) || + specifier.startsWith("/") + ) + return "internal"; return "external"; }; @@ -314,7 +318,7 @@ export const parseReferenceSourceImports = ( bytes: Uint8Array, language: string | null, ): ReferenceSourceImportParseResult => { - if (language !== null && !codeSourceLanguages.has(language)) + if (language !== null && !PARSEABLE_REFERENCE_SOURCE_LANGUAGES.has(language)) return { relationships: [], parse_failures: [], limitations: [] }; let source: string; diff --git a/src/domain/residualUnknown.ts b/src/domain/residualUnknown.ts index 0819a3964..e5db1cc54 100644 --- a/src/domain/residualUnknown.ts +++ b/src/domain/residualUnknown.ts @@ -12,7 +12,7 @@ import { functionComparisonDimensionNameSchema } from "./functionComparisonSchem const evidenceIdSchema = prefixedDigestSchema("ev"); const unknownIdSchema = prefixedDigestSchema("unk"); const text = z.string().trim().min(1); -const environmentRequirementSchema = z.object({ +const environmentRequirementSchema = z.strictObject({ id: z.string().min(1).nullable(), platform: z.string().min(1).nullable(), architecture: z.string().min(1).nullable(), @@ -39,7 +39,7 @@ const stableUnknownId = ( ) .digest("hex")}`; -const probeSchema = z.object({ +const probeSchema = z.strictObject({ operation: z.string().min(1), rationale: text, }); @@ -60,17 +60,17 @@ const comparisonConclusionScopeSchema = z message: "Comparison dimensions must be sorted and unique", }); }); -const relationshipSchema = z.object({ +const relationshipSchema = z.strictObject({ type: z.enum(["depends-on", "related-to", "contradicts"]), unknown_id: unknownIdSchema, }); const resolutionSchema = z.discriminatedUnion("disposition", [ - z.object({ + z.strictObject({ disposition: z.literal("verified"), rationale: text, evidence_ids: z.array(evidenceIdSchema).min(1), }), - z.object({ + z.strictObject({ disposition: z.enum(["withdrawn", "out-of-scope"]), rationale: text, evidence_ids: z.array(evidenceIdSchema), @@ -78,7 +78,7 @@ const resolutionSchema = z.discriminatedUnion("disposition", [ ]); /** Strict durable record for one unresolved or evidence-qualified question. */ -const residualUnknownObjectSchema = z.object({ +const residualUnknownObjectSchema = z.strictObject({ unknown_id: unknownIdSchema, revision: z.number().int().min(1), previous_revision_digest: z diff --git a/src/domain/signals/signalDecoders.ts b/src/domain/signals/signalDecoders.ts new file mode 100644 index 000000000..ae6754cca --- /dev/null +++ b/src/domain/signals/signalDecoders.ts @@ -0,0 +1,86 @@ +import { z } from "zod"; +import { signalRecordingSchema } from "./signalRecording.js"; + +export const inspectSignalDecodersInputSchema = z.strictObject({ + decoder: z + .string() + .regex(/^[a-zA-Z0-9_+\x2d]+$/u) + .max(256) + .nullable() + .default(null) + .describe( + "Exact installed decoder ID for help; null searches the decoder catalog", + ), + query: z + .string() + .max(8192) + .default("") + .describe( + "Case-insensitive literal substring in decoder ID/name or help lines; empty selects all", + ), + offset: z + .number() + .int() + .nonnegative() + .max(Number.MAX_SAFE_INTEGER) + .default(0) + .describe( + "Number of matching decoders or help lines to skip; defaults to 0", + ), + limit: z + .number() + .int() + .positive() + .max(Number.MAX_SAFE_INTEGER) + .nullable() + .default(50) + .describe( + "Maximum matching decoders or help lines returned; null requests all remaining", + ), +}); +export type InspectSignalDecodersInput = z.infer< + typeof inspectSignalDecodersInputSchema +>; +export const signalDecodersSchema = z + .strictObject({ + selection: inspectSignalDecodersInputSchema, + decoders: z.array(z.strictObject({ id: z.string(), name: z.string() })), + help_lines: z.array( + z.strictObject({ + line_number: z.number().int().positive(), + text: z.string(), + }), + ), + output_window: z.strictObject({ + unit: z.enum(["decoders", "help-lines"]), + examined: z.number().int().nonnegative(), + matching: z.number().int().nonnegative(), + returned: z.number().int().nonnegative(), + has_more: z.boolean(), + }), + diagnostics: z.string(), + tool: signalRecordingSchema.shape.tool, + resource_limiter: signalRecordingSchema.shape.resource_limiter, + limits: signalRecordingSchema.shape.limits, + hardware_acquisition: z.literal("not-performed"), + }) + .superRefine((report, context) => { + const w = report.output_window; + const catalog = report.selection.decoder === null; + const remaining = Math.max(0, w.matching - report.selection.offset); + const expected = Math.min(remaining, report.selection.limit ?? remaining); + if ( + w.unit !== (catalog ? "decoders" : "help-lines") || + w.matching > w.examined || + w.returned !== expected || + (catalog ? report.decoders : report.help_lines).length !== expected || + (catalog ? report.help_lines : report.decoders).length !== 0 || + w.has_more !== remaining > expected + ) + context.addIssue({ + code: "custom", + path: ["output_window"], + message: + "Discovery coverage must match the selected page and result kind", + }); + }); diff --git a/src/domain/wasm/wasmArtifact.ts b/src/domain/wasm/wasmArtifact.ts index 254a55a3a..d8c89ddf3 100644 --- a/src/domain/wasm/wasmArtifact.ts +++ b/src/domain/wasm/wasmArtifact.ts @@ -1,5 +1,6 @@ import { z } from "zod"; import { createHash } from "node:crypto"; +import type { EvidenceSubjectTarget } from "../evidence.js"; import { localPathStringSchema } from "../localPath.js"; @@ -137,11 +138,20 @@ export type InspectWasmArtifactInput = z.infer< >; export type WasmArtifact = z.infer; -/** A WASM observation must identify the exact selected path and byte digest. */ +/** A WASM observation must identify the selected file path and byte digest. */ +export type WasmArtifactSubject = Pick< + EvidenceSubjectTarget, + "path" | "sha256" | "format" +>; +type WasmArtifactFileSubject = WasmArtifactSubject & { + readonly format: "file"; +}; + export const wasmArtifactMatchesSubject = ( artifact: WasmArtifact["artifact"], - subject: Pick | null | undefined, -): subject is Pick => + subject: WasmArtifactSubject | null | undefined, +): subject is WasmArtifactFileSubject => subject != null && subject.path === artifact.path && - subject.sha256 === artifact.sha256; + subject.sha256 === artifact.sha256 && + subject.format === "file"; diff --git a/src/domain/webModuleImports.test.ts b/src/domain/webModuleImports.test.ts index 26db977a1..c0bcabdbf 100644 --- a/src/domain/webModuleImports.test.ts +++ b/src/domain/webModuleImports.test.ts @@ -25,11 +25,18 @@ describe("native module syntax observations", () => { item.expression, ); }); - it("excludes erased TypeScript imports/exports and bundler inference", () => { + it("excludes whole type declarations and retains inline type dependency syntax", () => { const result = collectWebModuleImports( 'import type {T} from "types"; import {type X} from "also-types"; export type {T} from "export-types"; export {type Y} from "only-types"; import {type T, value} from "mixed"; __webpack_require__.e(4); __vitePreload(() => 1, ["chunk.js"]);', ); - expect(result.imports.map((item) => item.specifier)).toEqual(["mixed"]); + expect(result.imports.map((item) => item.specifier)).toEqual([ + "also-types", + "only-types", + "mixed", + ]); + expect(result.diagnostics).toContain( + "Compiler options are unavailable; inline type-only imports or re-exports may preserve a module side-effect dependency.", + ); }); it("uses UTF-16 source locations after astral characters", () => { const source = 'const emoji = "😀";\nimport "./x.js";'; diff --git a/src/domain/webModuleImports.ts b/src/domain/webModuleImports.ts index 026868955..0f9846871 100644 --- a/src/domain/webModuleImports.ts +++ b/src/domain/webModuleImports.ts @@ -4,8 +4,13 @@ import { traverseJavaScriptAst } from "./javascript/javascriptSemanticTraversal. import { parseJavaScriptSource } from "./javascript/javascriptSourceParser.js"; import type { WebModuleImport } from "./webModuleTrace.js"; import type { ExportedWebScript } from "./webScriptExport.js"; +import { + hasUncertainTypeOnlyModuleSideEffect, + isTypeOnlyExportDeclaration, + isTypeOnlyImportDeclaration, +} from "./javascript/javascriptModuleDeclaration.js"; -/** Collect native import syntax, excluding erased type-only references. */ +/** Collect module declarations, omitting whole-statement type-only forms. */ export const collectWebModuleImports = ( source: string, ): { @@ -55,35 +60,18 @@ export const collectWebModuleImports = ( traverseJavaScriptAst(ast, { enter: (node) => { if (node.type === "ImportDeclaration") { - if (node.importKind === "type" || node.importKind === "typeof") return; - if ( - node.specifiers.length > 0 && - node.specifiers.every( - (s) => - s.type === "ImportSpecifier" && - (s.importKind === "type" || s.importKind === "typeof"), - ) - ) - return; + if (isTypeOnlyImportDeclaration(node)) return; add("static-import", node.source); } else if ( node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration" ) { if ( - node.exportKind === "type" || + isTypeOnlyExportDeclaration(node) || node.source === null || node.source === undefined ) return; - if ( - node.type === "ExportNamedDeclaration" && - node.specifiers.length > 0 && - node.specifiers.every( - (s) => s.type === "ExportSpecifier" && s.exportKind === "type", - ) - ) - return; add("re-export", node.source); } else if (node.type === "ImportExpression") add("dynamic-import", node.source); @@ -99,7 +87,14 @@ export const collectWebModuleImports = ( return { imports, state: "parsed", - diagnostics: ast.errors?.map((error) => error.message) ?? [], + diagnostics: [ + ...(ast.errors?.map((error) => error.message) ?? []), + ...(hasUncertainTypeOnlyModuleSideEffect(ast.program) + ? [ + "Compiler options are unavailable; inline type-only imports or re-exports may preserve a module side-effect dependency.", + ] + : []), + ], }; }; diff --git a/src/domain/webNetworkCapture.ts b/src/domain/webNetworkCapture.ts index ed31d5c70..77752f8e5 100644 --- a/src/domain/webNetworkCapture.ts +++ b/src/domain/webNetworkCapture.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { jsonValueSchema } from "./jsonValue.js"; import { localPathStringSchema } from "./localPath.js"; +import { qlogCaptureFactsSchema } from "./qlogCapture.js"; /** Complete historical evidence budgets; exceeding a budget returns no partial capture. */ export const WEB_NETWORK_CAPTURE_LIMITS = { @@ -10,12 +11,19 @@ export const WEB_NETWORK_CAPTURE_LIMITS = { depth: 64, } as const; +export const WEB_NETWORK_CAPTURE_FORMATS = [ + "har", + "mitmproxy", + "saz", + "qlog", +] as const; + /** Inspect an explicit retained capture without contacting its recorded destinations. */ export const inspectWebNetworkCaptureInputSchema = z.strictObject({ capture_path: localPathStringSchema.describe( - "Absolute local HAR or mitmproxy capture path.", + "Absolute local HAR, mitmproxy, Fiddler SAZ or aioquic qlog capture path.", ), - format: z.enum(["har", "mitmproxy"]), + format: z.enum(WEB_NETWORK_CAPTURE_FORMATS), record_ordinals: z .array(z.number().int().nonnegative()) .min(1) @@ -31,6 +39,21 @@ export const inspectWebNetworkCaptureInputSchema = z.strictObject({ ), }); +/** Read declarations through their owning schema for service and adapter failures. */ +export const captureSensitiveValues = ( + rawInput: unknown, +): readonly string[] => { + const parsed = + inspectWebNetworkCaptureInputSchema.shape.sensitive_values.safeParse( + typeof rawInput === "object" && + rawInput !== null && + "sensitive_values" in rawInput + ? rawInput.sensitive_values + : undefined, + ); + return parsed.success ? parsed.data : []; +}; + const pointerSchema = z .string() .describe("RFC 6901 pointer in the producer's reported object."); @@ -53,21 +76,26 @@ const binaryBase = { pointer: pointerSchema, representation: z.enum(["producer-bytes", "har-base64-content"]), }; +const retainedBinaryDescriptorSchema = z.strictObject({ + ...binaryBase, + state: z.literal("retained"), + bytes: z.number().int().nonnegative(), + sha256: z.string().regex(/^[0-9a-f]{64}$/), +}); +const redactedBinaryDescriptorSchema = z.strictObject({ + ...binaryBase, + state: z.literal("redacted"), + bytes: z.null(), + sha256: z.null(), +}); +/** Exact byte facts shared by complete records and previews that omit content. */ +export const webNetworkCaptureBinaryDescriptorSchema = z.discriminatedUnion( + "state", + [retainedBinaryDescriptorSchema, redactedBinaryDescriptorSchema], +); const binarySchema = z.discriminatedUnion("state", [ - z.strictObject({ - ...binaryBase, - state: z.literal("retained"), - content_base64: z.string(), - bytes: z.number().int().nonnegative(), - sha256: z.string().regex(/^[0-9a-f]{64}$/), - }), - z.strictObject({ - ...binaryBase, - state: z.literal("redacted"), - content_base64: z.null(), - bytes: z.null(), - sha256: z.null(), - }), + retainedBinaryDescriptorSchema.extend({ content_base64: z.string() }), + redactedBinaryDescriptorSchema.extend({ content_base64: z.null() }), ]); const numberSchema = z.strictObject({ pointer: pointerSchema, @@ -84,6 +112,10 @@ export const webNetworkCaptureRecordSchema = z.strictObject({ reason: z.literal("explicit-sensitive-value"), }), z.strictObject({ kind: z.literal("json-pointer"), pointer: pointerSchema }), + z.strictObject({ + kind: z.literal("archive-members"), + members: z.array(z.string()).min(1), + }), z.strictObject({ kind: z.literal("byte-range"), offset: z.number().int().nonnegative(), @@ -97,69 +129,85 @@ export const webNetworkCaptureRecordSchema = z.strictObject({ limitations: z.array(z.string()), }); -/** Decoded records retain unique producer ordinals within their declared coverage. */ -export const webNetworkCapturePayloadSchema = z - .strictObject({ - decoder: z.strictObject({ - id: z.string().min(1), - name: z.string().min(1), - version: z.string().min(1), - }), - container: z.strictObject({ - reported: jsonValueSchema, - numeric_literals: z.array(numberSchema), - redactions: z.array(redactionSchema), - records_pointer: pointerSchema.nullable(), - }), - total_records: z.number().int().nonnegative(), - records: z.array(webNetworkCaptureRecordSchema), - }) - .superRefine((capture, context) => { - if (capture.records.length > capture.total_records) { +/** The selected offline parser profile, independent of authenticated producer identity. */ +export const webNetworkCaptureDecoderSchema = z.strictObject({ + id: z.string().min(1), + name: z.string().min(1), + version: z.string().min(1), +}); + +/** Source coverage is shared by every offline decoder. */ +const payloadShape = { + decoder: webNetworkCaptureDecoderSchema, + container: z.strictObject({ + reported: jsonValueSchema, + numeric_literals: z.array(numberSchema), + redactions: z.array(redactionSchema), + records_pointer: pointerSchema.nullable(), + }), + total_records: z.number().int().nonnegative(), + records: z.array(webNetworkCaptureRecordSchema), +}; +const refineCoverage = ( + capture: { total_records: number; records: { ordinal: number }[] }, + context: z.RefinementCtx, +): void => { + const seen = new Set(); + for (const [index, record] of capture.records.entries()) { + if (record.ordinal >= capture.total_records || seen.has(record.ordinal)) { context.addIssue({ code: "custom", - path: ["records"], - message: "Retained record count exceeds the declared capture total.", + path: ["records", index, "ordinal"], + message: + "Retained ordinals must be unique and within the declared capture total.", }); return; } - const seen = new Set(); - for (const [index, record] of capture.records.entries()) { - if (record.ordinal >= capture.total_records || seen.has(record.ordinal)) { - context.addIssue({ - code: "custom", - path: ["records", index, "ordinal"], - message: - "Retained ordinals must be unique and within the declared capture total.", - }); - return; - } - seen.add(record.ordinal); - } - }); - -/** Historical capture inspection has file identity, producer provenance and explicit unknowns. */ -export const webNetworkCaptureSchema = - webNetworkCapturePayloadSchema.safeExtend({ - artifact: z.strictObject({ - path: z - .string() - .describe( - "Selected artifact path; empty when explicitly excluded from Evidence.", - ), - sha256: z - .string() - .regex(/^[0-9a-f]{64}$/) - .nullable() - .describe( - "Observed artifact SHA-256; null only when explicitly excluded by a sensitive declaration.", - ), - bytes: z.number().int().nonnegative(), + seen.add(record.ordinal); + } +}; +/** Strict alternatives prevent undefined-valued facets from entering JSON Evidence. */ +export const webNetworkCapturePayloadSchema = z + .union([ + z.strictObject({ ...payloadShape, qlog: qlogCaptureFactsSchema }), + z.strictObject(payloadShape), + ]) + .superRefine(refineCoverage); +/** Caller-selected file identity; explicit exclusions remain unknown. */ +export const webNetworkCaptureArtifactSchema = z.strictObject({ + path: z + .string() + .describe( + "Selected artifact path; empty when explicitly excluded from Evidence.", + ), + sha256: z + .string() + .regex(/^[0-9a-f]{64}$/) + .nullable() + .describe("Observed SHA-256; null only when explicitly excluded."), + bytes: z.number().int().nonnegative(), +}); +const artifactShape = { + artifact: webNetworkCaptureArtifactSchema, + runtime_attribution: z.literal("unknown"), + limitations: z.array(z.string()), +}; +/** Qlog transport facts occur exactly on the qlog alternative. */ +export const webNetworkCaptureSchema = z + .discriminatedUnion("format", [ + z.strictObject({ + ...payloadShape, + ...artifactShape, + format: z.enum(["har", "mitmproxy", "saz"]), }), - format: z.enum(["har", "mitmproxy"]), - runtime_attribution: z.literal("unknown"), - limitations: z.array(z.string()), - }); + z.strictObject({ + ...payloadShape, + ...artifactShape, + format: z.literal("qlog"), + qlog: qlogCaptureFactsSchema, + }), + ]) + .superRefine(refineCoverage); export type InspectWebNetworkCaptureInput = z.output< typeof inspectWebNetworkCaptureInputSchema diff --git a/src/domain/webNetworkCaptureCoordinates.ts b/src/domain/webNetworkCaptureCoordinates.ts index 6cba46cd9..a975c6b4a 100644 --- a/src/domain/webNetworkCaptureCoordinates.ts +++ b/src/domain/webNetworkCaptureCoordinates.ts @@ -22,6 +22,8 @@ export const excludeCaptureCoordinates = ( const location = (record.location.kind === "json-pointer" && sensitive(record.location.pointer)) || + (record.location.kind === "archive-members" && + record.location.members.some(sensitive)) || (record.location.kind === "byte-range" && (sensitive(String(record.location.offset)) || sensitive(String(record.location.bytes)))) @@ -51,8 +53,30 @@ export const excludeCaptureCoordinates = ( numeric_literals: sidecars(value.container.numeric_literals), redactions: sidecars(value.container.redactions), }; + const qlog = + value.format === "qlog" + ? { + ...value.qlog, + traces: value.qlog.traces.map((trace) => { + if ( + trace.location.kind !== "json-pointer" || + !sensitive(trace.location.pointer) + ) + return trace; + excluded = true; + return { + ...trace, + location: { + kind: "unknown" as const, + reason: "explicit-sensitive-value" as const, + }, + }; + }), + } + : undefined; return { ...value, + ...(qlog === undefined ? {} : { qlog }), container, records, limitations: excluded diff --git a/src/dotnet/ManagedMemberInstructionDecoder.ts b/src/dotnet/ManagedMemberInstructionDecoder.ts index f638e3e83..7ef518733 100644 --- a/src/dotnet/ManagedMemberInstructionDecoder.ts +++ b/src/dotnet/ManagedMemberInstructionDecoder.ts @@ -265,6 +265,10 @@ type OperandResult = { type OperandReader = (il: Buffer, offset: number) => OperandResult; +// String(-0) loses a CIL constant's sign in both anchors and normalized hashes. +const floatingPointOperand = (value: number): string => + Object.is(value, -0) ? "-0" : String(value); + const FIXED_OPERAND_READERS = new Map([ [ "none", @@ -315,7 +319,7 @@ const FIXED_OPERAND_READERS = new Map([ (il, offset) => ({ next: offset + 4, anchorKind: "constant", - value: String(il.readFloatLE(offset)), + value: floatingPointOperand(il.readFloatLE(offset)), }), ], [ @@ -323,7 +327,7 @@ const FIXED_OPERAND_READERS = new Map([ (il, offset) => ({ next: offset + 8, anchorKind: "constant", - value: String(il.readDoubleLE(offset)), + value: floatingPointOperand(il.readDoubleLE(offset)), }), ], [ diff --git a/src/evaluation/CodexAgentEval.ts b/src/evaluation/CodexAgentEval.ts index bac8d8191..55ec8333e 100644 --- a/src/evaluation/CodexAgentEval.ts +++ b/src/evaluation/CodexAgentEval.ts @@ -1,10 +1,11 @@ import { - deliveredCodexEvidence, evaluateKnownAnswers, + parseCodexToolCall, type FixtureClaimExpectation, type KnownAnswerAssessment, + type ParsedCodexToolCall, } from "./KnownAnswerEvaluation.js"; -import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js"; +import { canonicalJson } from "../domain/comparisonSemantics.js"; import { TOOL_CONTRACTS } from "../contracts/toolContracts.js"; /** One REA MCP invocation observed in a Codex JSONL transcript. */ @@ -57,17 +58,6 @@ const textValue = (value: unknown): string | undefined => const numberValue = (value: unknown): number => typeof value === "number" && Number.isFinite(value) ? value : 0; -const canonicalValue = (value: unknown): unknown => { - if (Array.isArray(value)) return value.map(canonicalValue); - const object = record(value); - if (object === undefined) return value; - return Object.fromEntries( - Object.entries(object) - .sort(([left], [right]) => compareUnicodeCodePoints(left, right)) - .map(([key, child]) => [key, canonicalValue(child)]), - ); -}; - const toolResultError = ( item: Record, ): Record | undefined => { @@ -113,29 +103,18 @@ const toolResultFailed = ( ); }; -const callFromEvent = ( - event: Record, +const callFromParsed = ( + parsed: ParsedCodexToolCall | undefined, ): CodexMcpCall | undefined => { - const item = record( - event.type === "item.completed" - ? event.item - : event.type === "mcp_tool_call" - ? event - : undefined, - ); - if (item?.type !== "mcp_tool_call") return undefined; - const tool = textValue(item.tool) ?? textValue(item.name); - if (tool === undefined) return undefined; - const error = toolResultError(item); + if (parsed === undefined) return undefined; + const error = toolResultError(parsed.item); return { - id: textValue(item.id) ?? null, - server: textValue(item.server) ?? textValue(item.server_name) ?? null, - tool, - arguments: item.arguments ?? item.input ?? {}, - evidenceIds: deliveredCodexEvidence(event).map( - ({ evidence_id }) => evidence_id, - ), - error: toolResultFailed(item, error), + id: parsed.id, + server: parsed.server, + tool: parsed.tool, + arguments: parsed.arguments, + evidenceIds: parsed.evidence.map(({ evidence_id }) => evidence_id), + error: toolResultFailed(parsed.item, error), errorCode: textValue(error?.code) ?? null, }; }; @@ -163,16 +142,20 @@ interface EvaluationState { outputTokens: number; } -const consumeEvent = (state: EvaluationState, value: unknown): void => { +const consumeEvent = ( + state: EvaluationState, + value: unknown, + parsedCall: ParsedCodexToolCall | undefined, +): void => { const event = record(value); if (event === undefined) return; const completedItem = event.type === "item.completed" ? event.item : undefined; - const call = callFromEvent(event); + const call = callFromParsed(parsedCall); if (call !== undefined) { const identity = call.id ?? - `${call.server ?? ""}:${call.tool}:${JSON.stringify(canonicalValue(call.arguments))}`; + `${call.server ?? ""}:${call.tool}:${canonicalJson(call.arguments)}`; if (!state.seenCallIds.has(identity)) { state.seenCallIds.add(identity); state.calls.push(call); @@ -216,7 +199,10 @@ export const evaluateCodexEvents = ( cachedInputTokens: 0, outputTokens: 0, }; - for (const event of events) consumeEvent(state, event); + const parsedCalls = events.map(parseCodexToolCall); + events.forEach((event, index) => + consumeEvent(state, event, parsedCalls[index]), + ); const reaCalls = state.calls.filter( ({ server }) => server === null || server.toLowerCase() === "rea", @@ -228,7 +214,7 @@ export const evaluateCodexEvents = ( // useful verification, not a duplicate analysis or unchanged failed retry. const context = call.tool === "binary_session" ? `${String(targetRevision)}:` : ""; - const signature = `${context}${call.tool}:${JSON.stringify(canonicalValue(call.arguments))}`; + const signature = `${context}${call.tool}:${canonicalJson(call.arguments)}`; signatures.set(signature, (signatures.get(signature) ?? 0) + 1); if ( !call.error && @@ -271,7 +257,7 @@ export const evaluateCodexEvents = ( finalMessage, ); const factualAssessment = evaluateKnownAnswers( - events, + parsedCalls, finalMessage, options.fixtureClaims, ); diff --git a/src/evaluation/KnownAnswerEvaluation.ts b/src/evaluation/KnownAnswerEvaluation.ts index 807308b59..c6e4af72b 100644 --- a/src/evaluation/KnownAnswerEvaluation.ts +++ b/src/evaluation/KnownAnswerEvaluation.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import { parseEvidence, type Evidence } from "../domain/evidence.js"; import { jsonValueSchema, type JsonValue } from "../domain/jsonValue.js"; -import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js"; +import { canonicalJson } from "../domain/comparisonSemantics.js"; /** One closed fixture assertion and the producer facts that must support it. */ export interface FixtureClaimExpectation { @@ -104,23 +104,13 @@ const isRecord = (value: unknown): value is Record => typeof value === "object" && value !== null && !Array.isArray(value); const record = (value: unknown): Record | undefined => isRecord(value) ? value : undefined; -const canonicalValue = (value: JsonValue): JsonValue => { - if (Array.isArray(value)) return value.map(canonicalValue); - if (value === null || typeof value !== "object") return value; - return Object.fromEntries( - Object.entries(value) - .sort(([left], [right]) => compareUnicodeCodePoints(left, right)) - .map(([key, child]) => [key, canonicalValue(child)]), - ); -}; const sameJson = (left: unknown, right: unknown): boolean => { const parsedLeft = jsonValueSchema.safeParse(left); const parsedRight = jsonValueSchema.safeParse(right); return ( parsedLeft.success && parsedRight.success && - JSON.stringify(canonicalValue(parsedLeft.data)) === - JSON.stringify(canonicalValue(parsedRight.data)) + canonicalJson(parsedLeft.data) === canonicalJson(parsedRight.data) ); }; @@ -168,6 +158,16 @@ interface DeliveredEvidence { readonly conflicts: Set; } +/** One completed tool call, with aliases normalized and successful Evidence authenticated. */ +export interface ParsedCodexToolCall { + readonly item: Record; + readonly id: string | null; + readonly server: string | null; + readonly tool: string; + readonly arguments: JsonValue; + readonly evidence: readonly Evidence[]; +} + const consistentAliases = ( value: Record, left: string, @@ -177,30 +177,14 @@ const consistentAliases = ( value[right] === undefined || value[left] === value[right]; -const completedCall = (event: unknown): Record | undefined => { - const value = record(event); - const item = - value?.type === "item.completed" - ? record(value.item) - : value?.type === "mcp_tool_call" && value.status === "completed" - ? value - : undefined; - if (item?.type !== "mcp_tool_call") return undefined; - const server = item.server ?? item.server_name; - if ( - typeof server !== "string" || - server.toLowerCase() !== "rea" || - (item.status !== undefined && item.status !== "completed") || - (item.error !== undefined && item.error !== null) - ) - return undefined; - if ( - !consistentAliases(item, "server", "server_name") || - !consistentAliases(item, "tool", "name") - ) - return undefined; - return item; -}; +const consistentJsonFields = ( + value: Record, + left: string, + right: string, +): boolean => + value[left] === undefined || + value[right] === undefined || + sameJson(value[left], value[right]); const consistentJsonAliases = ( value: Record, @@ -215,6 +199,7 @@ const consistentJsonAliases = ( const evidenceFromCall = ( item: Record, + tool: string, ): Evidence | undefined => { if (!consistentJsonAliases(item, "result", "output")) return undefined; const result = record(item.result ?? item.output); @@ -254,22 +239,42 @@ const evidenceFromCall = ( // Transcript output is untrusted; invalid Evidence cannot support a claim. return undefined; } - if ((item.tool ?? item.name) !== evidence.operation) return undefined; + if (tool !== evidence.operation) return undefined; return evidence; }; -/** Authenticate completed REA deliveries for both citations and fixture grading. */ -export const deliveredCodexEvidence = (event: unknown): readonly Evidence[] => { - const item = completedCall(event); - if (item === undefined) return []; - const evidence = evidenceFromCall(item); - if (evidence === undefined) return []; +const completedToolItem = ( + event: unknown, +): Record | undefined => { + const value = record(event); + const wrapped = value?.type === "item.completed"; + const item = wrapped + ? record(value.item) + : value?.type === "mcp_tool_call" + ? value + : undefined; + if (item?.type !== "mcp_tool_call") return undefined; + const terminalStatus = + item.status === "completed" || item.status === "failed"; + if ( + (wrapped + ? item.status !== undefined && !terminalStatus + : !terminalStatus) || + !consistentAliases(item, "server", "server_name") || + !consistentAliases(item, "tool", "name") || + !consistentJsonFields(item, "arguments", "input") + ) + return undefined; + return item; +}; + +const artifactDelivery = (evidence: Evidence): readonly Evidence[] => { const records = [evidence]; - // Artifact inspection delivers its inventory Evidence inline. Bare links and - // arbitrary IDs in normalized facts are references, not delivered records. if (evidence.operation !== "inspect_artifact") return records; const substeps = record(evidence.normalized_result)?.substeps; if (!Array.isArray(substeps)) return records; + // Artifact inspection delivers linked inventory Evidence inline; bare IDs in + // normalized facts are references, not authenticated deliveries. for (const value of substeps) { const substep = record(value); if ( @@ -293,13 +298,56 @@ export const deliveredCodexEvidence = (event: unknown): readonly Evidence[] => { return records; }; +/** Parse one completed transcript call and authenticate any successful REA Evidence. */ +export const parseCodexToolCall = ( + event: unknown, +): ParsedCodexToolCall | undefined => { + const item = completedToolItem(event); + if (item === undefined) return undefined; + const status = item.status; + const server = item.server ?? item.server_name; + const tool = item.tool ?? item.name; + if ( + ((item.server !== undefined || item.server_name !== undefined) && + typeof server !== "string") || + typeof tool !== "string" || + tool.length === 0 + ) + return undefined; + const argumentsValue = + item.arguments !== undefined + ? item.arguments + : item.input !== undefined + ? item.input + : {}; + const parsedArguments = jsonValueSchema.safeParse(argumentsValue); + if (!parsedArguments.success) return undefined; + const parsed: ParsedCodexToolCall = { + item, + id: typeof item.id === "string" && item.id.length > 0 ? item.id : null, + server: typeof server === "string" ? server : null, + tool, + arguments: parsedArguments.data, + evidence: [], + }; + if ( + parsed.server?.toLowerCase() !== "rea" || + status === "failed" || + (item.error !== undefined && item.error !== null) + ) + return parsed; + const evidence = evidenceFromCall(item, tool); + if (evidence === undefined) return parsed; + return { ...parsed, evidence: artifactDelivery(evidence) }; +}; + const collectDeliveredEvidence = ( - events: readonly unknown[], + calls: readonly (ParsedCodexToolCall | undefined)[], ): DeliveredEvidence => { const records = new Map(); const conflicts = new Set(); - for (const event of events) { - for (const evidence of deliveredCodexEvidence(event)) { + for (const call of calls) { + for (const evidence of call?.evidence ?? []) { const previous = records.get(evidence.evidence_id); if (previous !== undefined && !sameJson(previous, evidence)) conflicts.add(evidence.evidence_id); @@ -401,7 +449,7 @@ const assessClaim = ( /** Grade closed answers only against configured fixture truth and delivered authenticated Evidence. */ export const evaluateKnownAnswers = ( - events: readonly unknown[], + calls: readonly (ParsedCodexToolCall | undefined)[], finalMessage: string, expectations: readonly FixtureClaimExpectation[] | undefined, ): KnownAnswerAssessment => { @@ -441,7 +489,7 @@ export const evaluateKnownAnswers = ( manifestFailures.push(`unknown_claim:${claim.id}`); submitted.set(claim.id, claim); } - const delivered = collectDeliveredEvidence(events); + const delivered = collectDeliveredEvidence(calls); const claims = expectations.map((expected) => assessClaim(expected, submitted.get(expected.id), delivered), ); diff --git a/src/evm/EvmoleFailures.ts b/src/evm/EvmoleFailures.ts index 2677a3e71..63c6578aa 100644 --- a/src/evm/EvmoleFailures.ts +++ b/src/evm/EvmoleFailures.ts @@ -39,6 +39,9 @@ export const evmInterfaceFailure = ( limiter = "/usr/bin/prlimit", fileFailure?: EvmFileSizeFailureEvidence, ): AnalysisError => { + const cleanup = + cause instanceof ArtifactReaderFailure ? cause.cleanup : undefined; + const cleanupOptions = cleanup === undefined ? {} : { cleanup }; if (cause instanceof AnalysisError) return cause; if (cause instanceof OwnedCommandFailure) { const outputOptions = @@ -64,12 +67,15 @@ export const evmInterfaceFailure = ( { operation: "inspect_evm_interface", cause }, ); if (cause.reason === "cancelled") - return new AnalysisCancelledError("inspect_evm_interface", outputOptions); + return new AnalysisCancelledError("inspect_evm_interface", { + ...outputOptions, + ...cleanupOptions, + }); if (cause.reason === "timeout") return new AnalysisTimeoutError( "inspect_evm_interface", EVM_INTERFACE_LIMITS.timeoutMs, - outputOptions, + { ...outputOptions, ...cleanupOptions }, ); if (cause.reason === "output-limit") return new AnalysisOutputError( @@ -122,25 +128,33 @@ export const evmInterfaceFailure = ( } if (cause instanceof ArtifactReaderFailure) { if (cause.reason === "cancelled") - return new AnalysisCancelledError("inspect_evm_interface"); + return new AnalysisCancelledError("inspect_evm_interface", { + cause, + ...cleanupOptions, + }); if (cause.reason === "integrity") return new AnalysisArtifactChangedError( "inspect_evm_interface", path, cause.message, - { cause }, + { cause, ...cleanupOptions }, ); if ( phase === "artifact-read" && ["limit", "path", "format"].includes(cause.reason) ) - return new AnalysisInputError("inspect_evm_interface", { cause }, [ - { - path: ["path"], - reason: cause.reason === "limit" ? "out_of_range" : "invalid_format", - message: cause.message, - }, - ]); + return new AnalysisInputError( + "inspect_evm_interface", + { cause, ...cleanupOptions }, + [ + { + path: ["path"], + reason: + cause.reason === "limit" ? "out_of_range" : "invalid_format", + message: cause.message, + }, + ], + ); } if (phase === "artifact-read" && cause instanceof Error && "code" in cause) { if (cause.code === "EACCES" || cause.code === "EPERM") @@ -148,22 +162,27 @@ export const evmInterfaceFailure = ( "inspect_evm_interface", path, cause.code, - { cause }, + { cause, ...cleanupOptions }, ); if (cause.code === "ENOENT" || cause.code === "ENOTDIR") - return new AnalysisInputError("inspect_evm_interface", { cause }, [ - { - path: ["path"], - reason: "invalid_value", - message: `Selected bytecode carrier could not be read (${String(cause.code)}): ${path}.`, - }, - ]); + return new AnalysisInputError( + "inspect_evm_interface", + { cause, ...cleanupOptions }, + [ + { + path: ["path"], + reason: "invalid_value", + message: `Selected bytecode carrier could not be read (${String(cause.code)}): ${path}.`, + }, + ], + ); } return new ProviderAdapterError( EVMOLE_PROVIDER_IDENTITY.id, "inspect_evm_interface", { cause, + ...cleanupOptions, diagnostics: { phase, path, diff --git a/src/evm/EvmoleInterfaceProvider.ts b/src/evm/EvmoleInterfaceProvider.ts index 03731a92a..c59427e6a 100644 --- a/src/evm/EvmoleInterfaceProvider.ts +++ b/src/evm/EvmoleInterfaceProvider.ts @@ -6,11 +6,15 @@ import { fileURLToPath } from "node:url"; import { z } from "zod"; import { createAnalysisExecution, - type AnalysisExecution, type ExecutionOptions, } from "../application/AnalysisProvider.js"; -import type { EvmInterfacePort } from "../application/evm/EvmInterfacePort.js"; +import type { + EvmInterfaceExecution, + EvmInterfacePort, +} from "../application/evm/EvmInterfacePort.js"; import { readStableArtifact } from "../artifacts/readStableArtifact.js"; +import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; +import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; import { OwnedCommandFailure } from "../process/OwnedCommand.js"; import type { AnalysisError, @@ -76,6 +80,7 @@ type Launcher = NonNullable[2]>["launcher"]; /** Run unchanged EVMole/WASM in an owned worker; no target, chain or network execution. */ export class EvmoleInterfaceProvider implements EvmInterfacePort { + readonly #resources = new ArtifactResourceScope(); #tail: Promise = Promise.resolve(); #closing = false; #closePromise: Promise | undefined; @@ -98,11 +103,16 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { inspect( input: InspectEvmInterfaceInput, options?: ExecutionOptions, - ): Promise> { + ): Promise> { if (this.#closing) return Promise.resolve(err(this.#closedError())); - const operation = this.#tail.then(() => - this.#closing ? err(this.#closedError()) : this.#inspect(input, options), - ); + const operation = this.#tail.then(async () => { + if (this.#closing) return err(this.#closedError()); + try { + return await this.#resources.run(() => this.#inspect(input, options)); + } catch (cause: unknown) { + return err(evmInterfaceFailure(cause, "artifact-read", input.path)); + } + }); this.#tail = operation.then( () => undefined, () => undefined, @@ -113,7 +123,7 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { async #inspect( input: InspectEvmInterfaceInput, options?: ExecutionOptions, - ): Promise> { + ): Promise> { const pending = await this.#retire(); if (pending !== undefined) return err(pending); let root: Pick | undefined; @@ -123,7 +133,7 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { let workerLimits: EvmWorkerLimits | undefined; const limiter = this.environment.REA_EVM_PRLIMIT_COMMAND ?? "/usr/bin/prlimit"; - let result: Result; + let result: Result; try { if (options?.signal?.aborted) throw new AnalysisCancelledError(OPERATION); if (process.platform !== "linux" || process.arch !== "x64") @@ -178,6 +188,8 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { input.path, EVM_INTERFACE_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); phase = "worker"; root = await this.createRuntime(); @@ -241,15 +253,27 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { replyPath, EVM_INTERFACE_LIMITS.outputBytes, options?.signal, + undefined, + this.#resources, ); reply = replySchema.parse(JSON.parse(file.bytes.toString("utf8"))); } catch (cause: unknown) { + const cleanup = + cause instanceof ArtifactReaderFailure ? cause.cleanup : undefined; if (options?.signal?.aborted) - throw new AnalysisCancelledError(OPERATION, { capturedOutput }); + throw new AnalysisCancelledError(OPERATION, { + cause, + capturedOutput, + ...(cleanup === undefined ? {} : { cleanup }), + }); throw new AnalysisOutputError( OPERATION, `Owned interface worker reply failed for ${input.path}: ${cause instanceof Error ? cause.message : String(cause)}`, - { cause, capturedOutput }, + { + cause, + capturedOutput, + ...(cleanup === undefined ? {} : { cleanup }), + }, ); } if (!reply.ok) { @@ -353,6 +377,7 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { if (cause instanceof OwnedCommandFailure) processOwner = cause.cleanupOwner; let fileFailure: EvmFileSizeFailureEvidence | undefined; + let markerCleanupFailure: ArtifactReaderFailure | undefined; if ( cause instanceof OwnedCommandFailure && cause.snapshot?.exitCode === EVM_FILE_SIZE_FAILURE_EXIT && @@ -363,6 +388,9 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { const marker = await readStableArtifact( join(root.path, "resource.failure"), 1, + undefined, + undefined, + this.#resources, ); if (!marker.bytes.equals(Buffer.from("F"))) throw new Error( @@ -370,6 +398,14 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { ); fileFailure = { verified: true, failure: null }; } catch (markerFailure: unknown) { + if ( + markerFailure instanceof ArtifactReaderFailure && + markerFailure.cleanup !== undefined + ) + markerCleanupFailure = ArtifactReaderFailure.withCleanup( + cause, + markerFailure.cleanup, + ); fileFailure = { verified: false, failure: @@ -380,23 +416,36 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { } } result = err( - options?.signal?.aborted && - (cause === options.signal.reason || - (cause instanceof Error && cause.name === "AbortError")) - ? new AnalysisCancelledError( - OPERATION, - retainedOutput === undefined - ? undefined - : { capturedOutput: retainedOutput }, - ) - : evmInterfaceFailure( - cause, - phase, + markerCleanupFailure !== undefined + ? evmInterfaceFailure( + markerCleanupFailure, + "artifact-read", input.path, workerLimits, limiter, fileFailure, - ), + ) + : options?.signal?.aborted && + (cause === options.signal.reason || + (cause instanceof Error && cause.name === "AbortError")) + ? new AnalysisCancelledError(OPERATION, { + cause, + ...(retainedOutput === undefined + ? {} + : { capturedOutput: retainedOutput }), + ...(cause instanceof ArtifactReaderFailure && + cause.cleanup !== undefined + ? { cleanup: cause.cleanup } + : {}), + }) + : evmInterfaceFailure( + cause, + phase, + input.path, + workerLimits, + limiter, + fileFailure, + ), ); } if (processOwner !== undefined) { @@ -445,8 +494,37 @@ export class EvmoleInterfaceProvider implements EvmInterfacePort { this.#closing = true; this.#closePromise ??= this.#tail .then(async () => { - const failure = await this.#retire(); - if (failure !== undefined) throw failure; + const outcomes = await Promise.allSettled([ + this.#retire(), + this.#resources.close(), + ]); + const failures = outcomes.flatMap((outcome) => + outcome.status === "rejected" + ? [outcome.reason] + : outcome.value === undefined + ? [] + : [outcome.value], + ); + if (failures.length > 0) { + const resources = failures.flatMap((failure) => + failure instanceof ProviderCleanupError + ? failure.cleanupResources + : failure instanceof ArtifactReaderFailure && + failure.cleanup !== undefined + ? failure.cleanup.resources + : ["artifact-resources"], + ); + throw new ProviderCleanupError( + EVMOLE_PROVIDER_IDENTITY.id, + [...new Set(resources)], + { + failures: failures.map((failure) => + failure instanceof Error ? failure.message : String(failure), + ), + }, + { operation: OPERATION, cause: new AggregateError(failures) }, + ); + } }) .catch((cause: unknown) => { this.#closePromise = undefined; diff --git a/src/filesystem/RegularFile.ts b/src/filesystem/RegularFile.ts index a3037c728..4942e2e46 100644 --- a/src/filesystem/RegularFile.ts +++ b/src/filesystem/RegularFile.ts @@ -1,6 +1,6 @@ import { constants } from "node:fs"; import type { BigIntStats, Stats } from "node:fs"; -import { open, type FileHandle } from "node:fs/promises"; +import { lstat, open, type FileHandle } from "node:fs/promises"; import { OwnedFileHandle } from "./OwnedFileHandle.js"; @@ -74,6 +74,16 @@ export const openRegularFile = async ( options.signal?.throwIfAborted(); if (!metadata.isFile()) throw new NonRegularFileReadError(path, metadata.isDirectory()); + // O_NOFOLLOW is unavailable on Windows. Recheck the name only on hosts + // where open could have followed a symlink, while the descriptor is owned. + if (options.symlinks === "reject" && (constants.O_NOFOLLOW ?? 0) === 0) { + const named = await lstat(path); + options.signal?.throwIfAborted(); + if (named.isSymbolicLink()) + throw new NonRegularFileReadError(path, false); + if (!sameRegularFileState(metadata, named)) + throw new RegularFileChangedError(path); + } return handle; } catch (cause: unknown) { try { diff --git a/src/firmware/FirmwareCommand.ts b/src/firmware/FirmwareCommand.ts index b5db919f5..1604de901 100644 --- a/src/firmware/FirmwareCommand.ts +++ b/src/firmware/FirmwareCommand.ts @@ -176,11 +176,11 @@ export const runFirmwareCommand = async (context: { }; let failure: unknown; try { - const deadline = Date.now() + FIRMWARE_LIMITS.timeoutMs; + const deadline = performance.now() + FIRMWARE_LIMITS.timeoutMs; while (!(await supervisor.waitForOutputClose(100))) { checkDiagnostics(); if (signal.aborted) throw new AnalysisCancelledError(operation); - if (Date.now() >= deadline) + if (performance.now() >= deadline) throw new AnalysisTimeoutError(operation, FIRMWARE_LIMITS.timeoutMs); if (context.outputBudget !== undefined) await inventoryFirmwareOutput( diff --git a/src/firmware/FirmwareFiles.ts b/src/firmware/FirmwareFiles.ts index 10201905e..d20226e76 100644 --- a/src/firmware/FirmwareFiles.ts +++ b/src/firmware/FirmwareFiles.ts @@ -213,19 +213,15 @@ export const inventoryFirmwareOutput = async ( }); if (handle === undefined) continue; const names: string[] = []; - try { - for await (const entry of handle) { - throwIfFirmwareInventoryCancelled(signal, operation); - count++; - if (count > maxEntries) - throw new AnalysisOutputError( - operation, - `Staging entry budget exceeded (${maxEntries})`, - ); - names.push(entry.name); - } - } finally { - await handle.close().catch(() => undefined); + for await (const entry of handle) { + throwIfFirmwareInventoryCancelled(signal, operation); + count++; + if (count > maxEntries) + throw new AnalysisOutputError( + operation, + `Staging entry budget exceeded (${maxEntries})`, + ); + names.push(entry.name); } for (const name of names.sort()) { const path = join(directory, name); diff --git a/src/firmware/FirmwarePublication.ts b/src/firmware/FirmwarePublication.ts index bc53084b1..b2bc4ddd5 100644 --- a/src/firmware/FirmwarePublication.ts +++ b/src/firmware/FirmwarePublication.ts @@ -96,7 +96,7 @@ export const publishFirmwareExtraction = async (context: { published_bytes: files.reduce((sum, file) => sum + file.size, 0), }); context.signal.throwIfAborted(); - await tree.commit(); + await tree.commit(context.signal); return result; } catch (cause: unknown) { if (cause instanceof SafeOutputTreeCreationFailure) tree = cause.tree; diff --git a/src/flutter/FlutterBuildProvider.ts b/src/flutter/FlutterBuildProvider.ts index 2c088b2c9..9a6e6fe50 100644 --- a/src/flutter/FlutterBuildProvider.ts +++ b/src/flutter/FlutterBuildProvider.ts @@ -23,6 +23,7 @@ import { AnalysisUnsupportedTargetError, } from "../domain/analysisErrorCore.js"; import { AnalysisProtocolError } from "../domain/analysisErrorCore.js"; +import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js"; import { AnalysisError } from "../domain/analysisErrorBase.js"; import { err, ok, type Result } from "../domain/result.js"; import { @@ -759,7 +760,7 @@ export class FlutterBuildProvider { toolchain_capped: value.libflutter.toolchainCapped, }, })) - .sort((left, right) => left.abi.localeCompare(right.abi)); + .sort((left, right) => compareUnicodeCodePoints(left.abi, right.abi)); const flutterDetected = abis.some((entry) => entry.libapp.present); const partial = abis.some( @@ -871,7 +872,7 @@ export class FlutterBuildProvider { (left, right) => (preference.indexOf(left.abi) + 1 || preference.length + 1) - (preference.indexOf(right.abi) + 1 || preference.length + 1) || - left.abi.localeCompare(right.abi), + compareUnicodeCodePoints(left.abi, right.abi), )[0]! : candidates.find((candidate) => candidate.abi === abi); if (selected === undefined) diff --git a/src/frida/FridaInstrumentationManager.ts b/src/frida/FridaInstrumentationManager.ts index 406258e5a..22b38c442 100644 --- a/src/frida/FridaInstrumentationManager.ts +++ b/src/frida/FridaInstrumentationManager.ts @@ -83,8 +83,8 @@ interface ManagedSession extends ManagedRemoteConnection { readonly pid: number; readonly mode: "attach" | "spawn"; readonly scripts: Map; - readonly messages: JsonValue[]; - readonly messagesByScript: Map; + readonly messages: MessageFifo; + readonly messagesByScript: Map>; state: "paused" | "running" | "detached"; targetResumeObserved: boolean; resumeAfterDetachPending: boolean; @@ -277,7 +277,7 @@ export class FridaInstrumentationManager implements FridaInstrumentationPort { pid, mode: input.mode, scripts: new Map(), - messages: [], + messages: new MessageFifo(), messagesByScript: new Map(), state: input.mode === "spawn" ? "paused" : "running", targetResumeObserved: false, @@ -373,7 +373,7 @@ export class FridaInstrumentationManager implements FridaInstrumentationPort { .digest("hex"); const scriptId = randomUUID(); const scriptName = `rea-${scriptId}`; - managed.messagesByScript.set(scriptId, []); + managed.messagesByScript.set(scriptId, new MessageFifo()); let nativeScript: Script | undefined; const onMessage = (message: FridaMessage, data: Buffer | null): void => { this.#recordMessage(managed, scriptId, message, data); @@ -397,7 +397,7 @@ export class FridaInstrumentationManager implements FridaInstrumentationPort { sourceKind: source.sourceKind, sourcePath: source.sourceKind === "file" ? source.path : null, sourceSha256, - messages: [...(managed.messagesByScript.get(scriptId) ?? [])], + messages: managed.messagesByScript.get(scriptId)?.toArray() ?? [], messagesTruncated: managed.messagesTruncated, }); } catch (cause: unknown) { @@ -517,7 +517,9 @@ export class FridaInstrumentationManager implements FridaInstrumentationPort { scriptId: id, name, })), - messages: [...managed.messages], + messages: managed.messages + .toArray() + .map(({ observation }) => observation), messagesTruncated: managed.messagesTruncated, }; } @@ -851,30 +853,21 @@ export class FridaInstrumentationManager implements FridaInstrumentationPort { return; } while ( - managed.messages.length > 0 && + managed.messages.size > 0 && managed.capturedBytes + charge > MAX_SESSION_CAPTURE_BYTES ) { const removed = managed.messages.shift(); if (removed !== undefined) { - managed.capturedBytes -= Buffer.byteLength(JSON.stringify(removed)); - if ( - typeof removed === "object" && - removed !== null && - !Array.isArray(removed) && - typeof removed.script_id === "string" - ) { - const scriptMessages = managed.messagesByScript.get( - removed.script_id, - ); - const index = scriptMessages?.indexOf(removed) ?? -1; - if (scriptMessages !== undefined && index >= 0) { - scriptMessages.splice(index, 1); - } - } + managed.capturedBytes -= removed.charge; + // Both queues are in arrival order, so the globally oldest message is + // also the oldest one retained for its script. + const scriptMessages = managed.messagesByScript.get(removed.scriptId); + if (scriptMessages?.peek() === removed.observation) + scriptMessages.shift(); } managed.messagesTruncated = true; } - managed.messages.push(observation); + managed.messages.push({ observation, scriptId, charge }); managed.messagesByScript.get(scriptId)?.push(observation); managed.capturedBytes += charge; } @@ -1240,3 +1233,49 @@ const providerError = ( const errorMessage = (cause: unknown): string => cause instanceof Error ? cause.message : String(cause); + +interface CapturedMessage { + readonly observation: JsonValue; + readonly scriptId: string; + /** Serialized bytes charged against the session capture budget. */ + readonly charge: number; +} + +/** + * Arrival-ordered queue whose eviction advances a head offset. A full capture + * budget evicts on every message, and `Array#shift` would copy every retained + * message each time. + */ +class MessageFifo { + #items: (T | undefined)[] = []; + #head = 0; + + get size(): number { + return this.#items.length - this.#head; + } + + push(item: T): void { + this.#items.push(item); + } + + peek(): T | undefined { + return this.#items[this.#head]; + } + + shift(): T | undefined { + if (this.#head >= this.#items.length) return undefined; + const item = this.#items[this.#head]; + this.#items[this.#head] = undefined; + this.#head += 1; + // Compacting once half the slots are evicted keeps eviction amortized O(1). + if (this.#head * 2 >= this.#items.length) { + this.#items = this.#items.slice(this.#head); + this.#head = 0; + } + return item; + } + + toArray(): T[] { + return this.#items.slice(this.#head) as T[]; + } +} diff --git a/src/generatedPackageMetadata.ts b/src/generatedPackageMetadata.ts index 1af9203ad..bada60663 100644 --- a/src/generatedPackageMetadata.ts +++ b/src/generatedPackageMetadata.ts @@ -5,5 +5,5 @@ export const PACKAGE_METADATA = { serverSdkVersion: "2.3.1", clientSdkVersion: "2.3.1", coreSdkVersion: "2.3.1", - skillVersion: "40", + skillVersion: "41", } as const; diff --git a/src/ghidra/GhidraAnalysisProfile.ts b/src/ghidra/GhidraAnalysisProfile.ts index 60edb0971..fd7cdff11 100644 --- a/src/ghidra/GhidraAnalysisProfile.ts +++ b/src/ghidra/GhidraAnalysisProfile.ts @@ -123,6 +123,8 @@ export const resolveGhidraAnalysisProfile = async ( call_relationship_coverage: "resolved-call-reference-diagnostics-v1", string_inventory_evidence: "defined-data-coverage-v1", location_resolution: "explicit-address-exact-entry-symbol-first-v3", + procedure_file_offset_resolution: + "address-first-unique-target-source-mapping-v2", instruction_flow_evidence: "decoded-return-pcode-v1", instruction_references: "exact-address-incoming-v1", function_boundary_observations: "ghidra-terminal-call-limitations-v1", @@ -212,6 +214,8 @@ export const resolveGhidraAnalysisProfile = async ( call_relationship_coverage: "resolved-call-reference-diagnostics-v1", string_inventory_evidence: "defined-data-coverage-v1", location_resolution: "explicit-address-exact-entry-symbol-first-v3", + procedure_file_offset_resolution: + "address-first-unique-target-source-mapping-v2", instruction_flow_evidence: "decoded-return-pcode-v1", instruction_references: "exact-address-incoming-v1", function_boundary_observations: "ghidra-terminal-call-limitations-v1", diff --git a/src/ghidra/GhidraAnalysisSeeds.test.ts b/src/ghidra/GhidraAnalysisSeeds.test.ts index 8af76a4da..37437ebf7 100644 --- a/src/ghidra/GhidraAnalysisSeeds.test.ts +++ b/src/ghidra/GhidraAnalysisSeeds.test.ts @@ -196,7 +196,7 @@ describe("Ghidra seed profile", () => { const host: GhidraInstallationHost = { platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/src/ghidra/GhidraDoctor.test.ts b/src/ghidra/GhidraDoctor.test.ts index e1ea7fe37..69b9acb62 100644 --- a/src/ghidra/GhidraDoctor.test.ts +++ b/src/ghidra/GhidraDoctor.test.ts @@ -1,9 +1,10 @@ -import { describe, expect, it } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { runDoctor, type DoctorHost } from "../application/Doctor.js"; import { createDoctorHostFixture } from "../application/Doctor.fixture.js"; import { providerRegistrationEnvironment } from "../application/SetupRegistrationEnvironment.js"; import { WINDOWS_NATIVE_AUTHORITY_UNAVAILABLE_REASON } from "../process/WindowsAuthority.js"; +import * as windowsAuthority from "../process/WindowsAuthority.js"; import { inspectGhidraInstallation, type GhidraInstallationHost, @@ -15,7 +16,7 @@ const INSTALL = "/opt/ghidra_12.1.4_PUBLIC"; const installationHost = ( overrides: Partial = {}, ): GhidraInstallationHost => ({ - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", @@ -111,7 +112,9 @@ describe("Ghidra doctor integration", () => { "wrong version", inspection( { installDir: INSTALL }, - { readText: () => "application.version=11.4\n" }, + { + readText: () => "application.version=11.4\napplication.java.min=21\n", + }, ), "ghidra-version", ], @@ -136,6 +139,14 @@ describe("Ghidra doctor integration", () => { ), "ghidra-java", ], + [ + "missing Java minimum", + inspection( + { installDir: INSTALL }, + { readText: () => "application.version=12.1.4\n" }, + ), + "ghidra-java", + ], [ "unsupported architecture", inspection({ installDir: INSTALL, architecture: "arm" }), @@ -163,6 +174,16 @@ describe("Ghidra doctor integration", () => { }); describe("Windows Ghidra doctor authority", () => { + beforeEach(() => { + vi.spyOn(windowsAuthority, "hasWindowsNativeAuthority").mockReturnValue( + false, + ); + vi.spyOn( + windowsAuthority, + "windowsNativeAuthorityUnavailableReason", + ).mockReturnValue(WINDOWS_NATIVE_AUTHORITY_UNAVAILABLE_REASON); + }); + afterEach(() => vi.restoreAllMocks()); it("distinguishes a valid Windows installation from unavailable native authority", async () => { const ghidra = inspection({ installDir: "C:\\tools\\ghidra_12.1.4_PUBLIC", diff --git a/src/ghidra/GhidraFunctionValues.test.ts b/src/ghidra/GhidraFunctionValues.test.ts index 662db0a26..75d59c97f 100644 --- a/src/ghidra/GhidraFunctionValues.test.ts +++ b/src/ghidra/GhidraFunctionValues.test.ts @@ -42,6 +42,30 @@ const parseFunctionValueFixture = ( }; describe("Ghidra function-analysis result values", () => { + it("preserves file-offset resolution in Evidence locations and rejects inexact offsets", () => { + const selection = { + file_offset: 0x210, + mapped_address: "0x140001010", + procedure_address: "0x140001010", + }; + const wire = { value: "return 42;", limitations: [], selection }; + expect(parseGhidraFunctionResult("procedure_assembly", wire)).toMatchObject( + { ok: false, error: { _tag: "AnalysisOutputError" } }, + ); + const parsed = parseGhidraFunctionResult("procedure_pseudo_code", wire); + if (!parsed.ok) throw parsed.error; + expect(parsed.value.locations).toEqual([ + { kind: "file-offset", offset: 0x210 }, + { kind: "address", address: "0x140001010" }, + { kind: "address", address: "0x140001010" }, + ]); + expect( + parseGhidraFunctionResult("procedure_pseudo_code", { + ...wire, + selection: { ...selection, file_offset: Number.MAX_SAFE_INTEGER + 1 }, + }), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisOutputError" } }); + }); it.each([...observationOperations])( "requires the function-observation limitations envelope for %s", (operation) => { diff --git a/src/ghidra/GhidraFunctionValues.ts b/src/ghidra/GhidraFunctionValues.ts index 8876e31ae..d45e41ba9 100644 --- a/src/ghidra/GhidraFunctionValues.ts +++ b/src/ghidra/GhidraFunctionValues.ts @@ -26,6 +26,7 @@ import { } from "../domain/jsonValue.js"; import { nativeApiBoundarySchema } from "../domain/native/nativeApiBoundary.js"; import { nativeValueFlowSchema } from "../domain/native/nativeValueFlow.js"; +import type { EvidenceLocation } from "../domain/evidence.js"; import { err, ok, type Result } from "../domain/result.js"; import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; import { @@ -399,11 +400,19 @@ const functionBoundaryObservationOperations: ReadonlySet["selection"]; }; if (functionBoundaryObservationOperations.has(operation)) { const envelope = functionObservationEnvelope.safeParse(value); - if (!envelope.success) + if ( + !envelope.success || + (operation !== "procedure_pseudo_code" && + envelope.data.selection !== undefined) + ) return err( new AnalysisOutputError( operation, "Ghidra bridge omitted the function observation envelope", - { cause: envelope.error }, + envelope.success ? undefined : { cause: envelope.error }, ), ); observation = envelope.data; @@ -434,6 +450,24 @@ export const parseGhidraFunctionResult = ( ? ok({ value: jsonValueSchema.parse(parsed.data), limitations: observation.limitations, + ...(observation.selection === undefined + ? {} + : { + locations: [ + { + kind: "file-offset" as const, + offset: observation.selection.file_offset, + }, + { + kind: "address" as const, + address: observation.selection.mapped_address, + }, + { + kind: "address" as const, + address: observation.selection.procedure_address, + }, + ], + }), }) : err( new AnalysisOutputError( diff --git a/src/ghidra/GhidraInstallation.test.ts b/src/ghidra/GhidraInstallation.test.ts index 185c71973..776c10308 100644 --- a/src/ghidra/GhidraInstallation.test.ts +++ b/src/ghidra/GhidraInstallation.test.ts @@ -5,12 +5,15 @@ import { projectGhidraDoctorInspection } from "./GhidraDoctor.js"; import { ghidraJavaEnvironment, inspectGhidraInstallation, + type GhidraExecutableHeaderProbe, type GhidraInstallationHost, type GhidraJavaObservation, } from "./GhidraInstallation.js"; import { SUPPORTED_GHIDRA_JAVA_MAJOR, SUPPORTED_GHIDRA_VERSION, + ghidraApplicationProperties, + ghidraJavaRequirement, } from "./GhidraInstallationPolicy.js"; const INSTALL = "/opt/ghidra"; @@ -23,6 +26,11 @@ const WINDOWS_PROPERTIES = `${WINDOWS_INSTALL}\\Ghidra\\application.properties`; const WINDOWS_HEADLESS = `${WINDOWS_INSTALL}\\support\\analyzeHeadless.bat`; const WINDOWS_DECOMPILER = `${WINDOWS_INSTALL}\\Ghidra\\Features\\Decompiler\\os\\win_x86_64\\decompile.exe`; +const headerProbe = (bytes: Buffer): GhidraExecutableHeaderProbe => ({ + bytes, + size: bytes.length, +}); + const JAVA: GhidraJavaObservation = { version: "21.0.11", major: SUPPORTED_GHIDRA_JAVA_MAJOR, @@ -36,7 +44,7 @@ const host = ( ): GhidraInstallationHost => ({ readText: (path) => path === PROPERTIES - ? `application.version=${SUPPORTED_GHIDRA_VERSION}\n` + ? `application.version=${SUPPORTED_GHIDRA_VERSION}\napplication.java.min=${String(SUPPORTED_GHIDRA_JAVA_MAJOR)}\n` : undefined, executable: (path) => path === HEADLESS || path === MAC_DECOMPILER || path === LINUX_DECOMPILER, @@ -184,7 +192,7 @@ describe("Ghidra installation inspection", () => { architecture: "x64", readText: (path) => path === WINDOWS_PROPERTIES - ? `application.version=${SUPPORTED_GHIDRA_VERSION}\n` + ? `application.version=${SUPPORTED_GHIDRA_VERSION}\napplication.java.min=21\n` : undefined, executable: (path) => path === WINDOWS_HEADLESS || path === WINDOWS_DECOMPILER, @@ -269,7 +277,9 @@ describe("Ghidra installation rejection diagnostics", () => { platform: "linux" as const, architecture: "x64" as const, }, - override: { readText: () => "application.version=11.4\n" }, + override: { + readText: () => "application.version=11.4\napplication.java.min=21\n", + }, failed: "version", code: "unsupported_version", }, @@ -344,6 +354,167 @@ describe("Ghidra installation rejection diagnostics", () => { }); describe("Ghidra release line and JDK bounds", () => { + it("uses Java Properties last-key, delimiter, escape, and continuation rules", () => { + const properties = ghidraApplicationProperties( + [ + "application.version=11.4", + "# comment ending with a slash " + "\\", + "application.\\u0076ersion : 12.\\", + " 1.\\u0034", + "! another comment " + "\\", + "application.java.\\u006din\t21", + "application.java.max=", + ].join("\n"), + ); + expect(properties).toEqual({ + providerVersion: "12.1.4", + javaMinimum: { status: "major", major: 21 }, + javaMaximum: { status: "absent" }, + parseError: null, + }); + expect( + ghidraApplicationProperties("application.version=12.1.4").javaMinimum, + ).toEqual({ + status: "absent", + }); + expect( + ghidraApplicationProperties( + "application.version=12.1.4\napplication.java.min=\n", + ).javaMinimum, + ).toEqual({ status: "unresolved", raw: "" }); + expect( + ghidraApplicationProperties("application.version=12.1.4\\") + .providerVersion, + ).toBe("12.1.4"); + expect( + ghidraApplicationProperties("application.version=12.\\\n #.1") + .providerVersion, + ).toBe("12.#.1"); + expect( + ghidraApplicationProperties( + "application.version=12.\\\n\napplication.version=12.1.4", + ).providerVersion, + ).toBe("12.1.4"); + }); + + it("matches Ghidra integer Java bounds and zero maximum semantics", () => { + const properties = ghidraApplicationProperties( + "application.java.min=21.0\napplication.java.max=0\n", + ); + expect(properties.javaMinimum).toEqual({ + status: "unresolved", + raw: "21.0", + }); + expect(properties.javaMaximum).toEqual({ status: "absent" }); + expect( + ghidraApplicationProperties("application.java.max=+0").javaMaximum, + ).toEqual({ + status: "absent", + }); + expect( + ghidraApplicationProperties("application.java.max=+0").javaMaximum, + ).toEqual({ status: "absent" }); + expect( + ghidraApplicationProperties("application.java.min=+21").javaMinimum, + ).toEqual({ + status: "major", + major: 21, + }); + expect( + ghidraApplicationProperties("application.java.min=٢١").javaMinimum, + ).toEqual({ + status: "major", + major: 21, + }); + expect( + ghidraApplicationProperties("application.java.min=21").javaMinimum, + ).toEqual({ + status: "major", + major: 21, + }); + expect( + ghidraApplicationProperties("application.java.max=+0").javaMaximum, + ).toEqual({ + status: "unresolved", + raw: "+0", + }); + expect( + ghidraApplicationProperties("application.java.min=②").javaMinimum, + ).toEqual({ + status: "unresolved", + raw: "②", + }); + expect( + ghidraApplicationProperties("application.java.min=2147483648") + .javaMinimum, + ).toEqual({ status: "unresolved", raw: "2147483648" }); + }); + + it("keeps an unavailable properties file unresolved for Java admission", () => { + expect(ghidraJavaRequirement(undefined).unresolved).toBe( + "application.properties is unavailable", + ); + }); + + it("preserves property value trailing whitespace instead of normalizing it", () => { + const properties = ghidraApplicationProperties( + "application.version=12.1.4 \napplication.java.min=21 \n", + ); + expect(properties.providerVersion).toBe("12.1.4 "); + expect(properties.javaMinimum).toEqual({ + status: "unresolved", + raw: "21 ", + }); + expect(properties.parseError).toBeNull(); + }); +}); + +describe("Ghidra malformed property admission", () => { + it("fails installation and doctor admission closed on malformed Unicode escapes", () => { + const result = inspectGhidraInstallation( + { + environment: {}, + installDir: INSTALL, + platform: "linux", + architecture: "x64", + }, + host({ + readText: () => + "application.version=12.1.4\nbroken=\\u12G4\napplication.java.min=17\n", + }), + ); + expect(result.status).toBe("unavailable"); + expect(result.providerVersion).toBeNull(); + expect(result.checks).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: "version", + status: "failed", + code: "version_unresolved", + detail: expect.stringContaining("Malformed Unicode escape"), + }), + expect.objectContaining({ + name: "java", + status: "failed", + code: "version_unresolved", + remediation: expect.stringContaining( + "application.properties parse failed", + ), + }), + ]), + ); + expect(projectGhidraDoctorInspection(result)).toMatchObject({ + available: false, + registrationEnvironment: {}, + checks: expect.arrayContaining([ + expect.objectContaining({ name: "version", ok: false }), + expect.objectContaining({ name: "java", ok: false }), + ]), + }); + }); +}); + +describe("Ghidra installation version admission", () => { it.each([ { name: "JDK above the installation maximum", @@ -361,16 +532,23 @@ describe("Ghidra release line and JDK bounds", () => { failed: "java", code: "version_unresolved", }, + { + name: "missing Java minimum", + readText: () => "application.version=12.1.4\n", + probeJava: () => JAVA, + failed: "java", + code: "version_unresolved", + }, { name: "unparseable Ghidra version", - readText: () => "application.version=latest\n", + readText: () => "application.version=latest\napplication.java.min=21\n", probeJava: () => JAVA, failed: "version", code: "version_unresolved", }, { name: "different Ghidra line", - readText: () => "application.version=12.2.0\n", + readText: () => "application.version=12.2.0\napplication.java.min=21\n", probeJava: () => JAVA, failed: "version", code: "unsupported_version", @@ -416,7 +594,7 @@ describe("Ghidra release line and JDK bounds", () => { }); }); - it("honors an installation that declares a lower Java minimum", () => { + it("accepts a lower Java minimum declared by the installation", () => { expect( inspectGhidraInstallation( { @@ -543,7 +721,7 @@ describe("Ghidra FAT native decompiler admission", () => { platform: "darwin", architecture: "arm64", }, - host({ executableHeader: () => ({ bytes, size: bytes.length }) }), + host({ executableHeader: () => headerProbe(bytes) }), ); expect(result.status).toBe(status); expect( @@ -561,7 +739,7 @@ describe("Ghidra FAT native decompiler admission", () => { platform: "darwin", architecture: "arm64", }, - host({ executableHeader: () => ({ bytes, size: bytes.length }) }), + host({ executableHeader: () => headerProbe(bytes) }), ); expect(result.status).toBe("available"); expect( @@ -581,9 +759,7 @@ describe("Ghidra native decompiler admission", () => { architecture: "x64" as const, }, executableHeader: (path: string) => - path === LINUX_DECOMPILER - ? { bytes: elf(1, 1, 8), size: 52 } - : undefined, + path === LINUX_DECOMPILER ? headerProbe(elf(1, 1, 8)) : undefined, }, { name: "a Linux x86-64 decompiler at the macOS arm64 path", @@ -594,9 +770,7 @@ describe("Ghidra native decompiler admission", () => { architecture: "arm64" as const, }, executableHeader: (path: string) => - path === MAC_DECOMPILER - ? { bytes: elf(2, 1, 62), size: 52 } - : undefined, + path === MAC_DECOMPILER ? headerProbe(elf(2, 1, 62)) : undefined, }, { name: "a macOS arm64 decompiler at the Linux x64 path", @@ -608,7 +782,7 @@ describe("Ghidra native decompiler admission", () => { }, executableHeader: (path: string) => path === LINUX_DECOMPILER - ? { bytes: thinMach(0xcffaedfe, 0x0100000c), size: 32 } + ? headerProbe(thinMach(0xcffaedfe, 0x0100000c)) : undefined, }, ])("distinguishes $name", ({ options, executableHeader }) => { @@ -632,9 +806,7 @@ describe("Ghidra native decompiler admission", () => { }, host({ executableHeader: (path: string) => - path === LINUX_DECOMPILER - ? { bytes: elf(2, 1, 62), size: 52 } - : undefined, + path === LINUX_DECOMPILER ? headerProbe(elf(2, 1, 62)) : undefined, }), ); expect(result.status).toBe("available"); @@ -678,7 +850,7 @@ describe("Ghidra native decompiler admission", () => { }, host({ executableHeader: (path: string) => - path === MAC_DECOMPILER ? { bytes, size: bytes.length } : undefined, + path === MAC_DECOMPILER ? headerProbe(bytes) : undefined, }), ); expect(result.status).toBe("available"); @@ -701,9 +873,7 @@ describe("Ghidra native decompiler admission", () => { }, host({ executableHeader: (path: string) => - path === MAC_DECOMPILER - ? { bytes: elf(2, 1, 62), size: 52 } - : undefined, + path === MAC_DECOMPILER ? headerProbe(elf(2, 1, 62)) : undefined, }), ); expect(result.status).toBe("unavailable"); diff --git a/src/ghidra/GhidraInstallation.ts b/src/ghidra/GhidraInstallation.ts index 713fe820f..c6ca5212d 100644 --- a/src/ghidra/GhidraInstallation.ts +++ b/src/ghidra/GhidraInstallation.ts @@ -641,14 +641,20 @@ const versionCheck = ( properties: GhidraApplicationProperties | undefined, ): GhidraInstallationCheck => { const raw = properties?.providerVersion; + const parseError = properties?.parseError; return installationCheck({ name: "version", - passed: ghidraReleaseAccepted(raw), + passed: parseError == null && ghidraReleaseAccepted(raw), code: - ghidraReleaseCompatibility(raw).status === "unsupported" - ? "unsupported_version" - : "version_unresolved", - detail: ghidraVersionDetail(raw), + parseError != null + ? "version_unresolved" + : ghidraReleaseCompatibility(raw).status === "unsupported" + ? "unsupported_version" + : "version_unresolved", + detail: + parseError == null + ? ghidraVersionDetail(raw) + : `application.properties could not be parsed: ${parseError}`, remediation: `Install a Ghidra ${ghidraReleaseLine()} release (verified with ${SUPPORTED_GHIDRA_VERSION}), or update REA for another Ghidra line.`, }); }; @@ -701,7 +707,9 @@ const javaRemediation = ( const systemGhidraInstallationHost = (): GhidraInstallationHost => ({ readText(path) { try { - return readFileSync(path, "utf8"); + // Ghidra loads this file with Properties.load(InputStream), which maps + // bytes as ISO-8859-1 rather than decoding UTF-8. + return readFileSync(path).toString("latin1"); } catch (cause: unknown) { // best-effort cleanup: optional install probing; unreadable means unknown. void cause; diff --git a/src/ghidra/GhidraInstallationPolicy.ts b/src/ghidra/GhidraInstallationPolicy.ts index bd19dc1d1..8a35c66c3 100644 --- a/src/ghidra/GhidraInstallationPolicy.ts +++ b/src/ghidra/GhidraInstallationPolicy.ts @@ -1,10 +1,8 @@ +import { parseGhidraJavaProperties } from "./GhidraJavaProperties.js"; + /** Ghidra build whose bridge behavior this REA release verifies. */ export const SUPPORTED_GHIDRA_VERSION = "12.1.4"; -/** - * JDK major used when an installation omits `application.java.min`. - * Admission uses that installation's `application.java.min` and - * `application.java.max`. An empty maximum means the release sets no upper bound. - */ +/** Verified JDK major; admission uses the installation's declared bounds. */ export const SUPPORTED_GHIDRA_JAVA_MAJOR = 21; /** Numeric Ghidra release read from `application.version`. */ @@ -40,30 +38,49 @@ type GhidraJavaBound = | { readonly status: "unresolved"; readonly raw: string }; /** JDK majors this installation admits, after reading its own properties. */ -export interface GhidraJavaRequirement { - readonly minimumMajor: number; - readonly maximumMajor: number | null; - readonly unresolved: string | null; -} +export type GhidraJavaRequirement = + | { + readonly minimumMajor: number; + readonly maximumMajor: number | null; + readonly unresolved: null; + } + | { readonly unresolved: string }; /** Version and Java bounds read from one `application.properties` file. */ export interface GhidraApplicationProperties { readonly providerVersion: string | null; readonly javaMinimum: GhidraJavaBound; readonly javaMaximum: GhidraJavaBound; + /** A malformed Java properties escape invalidates the entire file. */ + readonly parseError: string | null; } const GHIDRA_RELEASE_PATTERN = /^(\d+)\.(\d+)(?:\.(\d+))?([-+].*)?$/u; -const JAVA_MAJOR_PATTERN = /^(\d+)(?:\.\d+)*$/u; /** Read the version and Java bounds Ghidra publishes for one installation. */ export const ghidraApplicationProperties = ( content: string, -): GhidraApplicationProperties => ({ - providerVersion: propertyValue(content, "application.version"), - javaMinimum: parseJavaBound(propertyValue(content, "application.java.min")), - javaMaximum: parseJavaBound(propertyValue(content, "application.java.max")), -}); +): GhidraApplicationProperties => { + const parsed = parseGhidraJavaProperties(content); + if (!parsed.ok) + return { + providerVersion: null, + javaMinimum: { status: "unresolved", raw: parsed.error }, + javaMaximum: { status: "unresolved", raw: parsed.error }, + parseError: parsed.error, + }; + const providerVersion = parsed.value.get("application.version"); + const minimum = parsed.value.get("application.java.min"); + const maximum = parsed.value.get("application.java.max"); + return { + providerVersion: providerVersion ?? null, + javaMinimum: + minimum === undefined ? { status: "absent" } : parseJavaBound(minimum), + // Ghidra uses an explicitly empty maximum to mean no upper bound. + javaMaximum: parseJavaMaximum(maximum), + parseError: null, + }; +}; /** Classify `application.version` against the verified release line. */ export const ghidraReleaseCompatibility = ( @@ -130,14 +147,21 @@ export const ghidraReleaseAccepted = ( export const ghidraJavaRequirement = ( properties: GhidraApplicationProperties | undefined, ): GhidraJavaRequirement => { - const minimum = properties?.javaMinimum ?? { status: "absent" }; - const maximum = properties?.javaMaximum ?? { status: "absent" }; + if (properties?.parseError !== null && properties?.parseError !== undefined) + return unresolvedJavaRequirement( + `application.properties parse failed: ${properties.parseError}`, + ); + if (properties === undefined) + return unresolvedJavaRequirement("application.properties is unavailable"); + const minimum = properties.javaMinimum; + const maximum = properties.javaMaximum; if (minimum.status === "unresolved") return unresolvedJavaRequirement(`application.java.min=${minimum.raw}`); + if (minimum.status === "absent") + return unresolvedJavaRequirement("application.java.min is missing"); if (maximum.status === "unresolved") return unresolvedJavaRequirement(`application.java.max=${maximum.raw}`); - const minimumMajor = - minimum.status === "major" ? minimum.major : SUPPORTED_GHIDRA_JAVA_MAJOR; + const minimumMajor = minimum.major; const maximumMajor = maximum.status === "major" ? maximum.major : null; if (maximumMajor !== null && maximumMajor < minimumMajor) return unresolvedJavaRequirement( @@ -187,14 +211,56 @@ const parseGhidraRelease = (raw: string): GhidraReleaseVersion | undefined => { return patch === undefined ? undefined : { major, minor, patch }; }; -const parseJavaBound = (raw: string | null): GhidraJavaBound => { - if (raw === null) return { status: "absent" }; - const major = integerGroup(JAVA_MAJOR_PATTERN.exec(raw)?.[1]); +const parseJavaBound = (raw: string): GhidraJavaBound => { + const major = parseJavaInteger(raw); return major === undefined ? { status: "unresolved", raw } : { status: "major", major }; }; +const parseJavaMaximum = (raw: string | undefined): GhidraJavaBound => { + if (raw === undefined || raw === "") return { status: "absent" }; + const bound = parseJavaBound(raw); + return bound.status === "major" && bound.major === 0 + ? { status: "absent" } + : bound; +}; + +const parseJavaInteger = (raw: string): number | undefined => { + let index = 0; + let sign = 1; + if (raw[index] === "+" || raw[index] === "-") { + if (raw[index] === "-") sign = -1; + index += 1; + } + if (index === raw.length) return undefined; + const limit = sign < 0 ? 2_147_483_648 : 2_147_483_647; + let value = 0; + for (; index < raw.length; index += 1) { + const character = raw[index]; + if (character === undefined) return undefined; + const digit = javaDecimalDigit(character); + if (digit === undefined) return undefined; + if (value > Math.floor((limit - digit) / 10)) return undefined; + value = value * 10 + digit; + } + return sign * value; +}; + +/** Match Integer.parseInt(charAt) for BMP Decimal_Number characters. */ +const javaDecimalDigit = (character: string): number | undefined => { + const code = character.charCodeAt(0); + if (code >= 48 && code <= 57) return code - 48; + if (!/^\p{Decimal_Number}$/u.test(character)) return undefined; + let blockStart = code; + while ( + blockStart > 0 && + /^\p{Decimal_Number}$/u.test(String.fromCharCode(blockStart - 1)) + ) + blockStart -= 1; + return (code - blockStart) % 10; +}; + const integerGroup = (value: string | undefined): number | undefined => { if (value === undefined) return undefined; const parsed = Number(value); @@ -204,17 +270,7 @@ const integerGroup = (value: string | undefined): number | undefined => { const unresolvedJavaRequirement = ( unresolved: string, ): GhidraJavaRequirement => ({ - minimumMajor: SUPPORTED_GHIDRA_JAVA_MAJOR, - maximumMajor: null, unresolved, }); -const propertyValue = (content: string, name: string): string | null => { - for (const line of content.split(/\r?\n/u)) { - const separator = line.indexOf("="); - if (separator < 0 || line.slice(0, separator).trim() !== name) continue; - const value = line.slice(separator + 1).trim(); - return value.length === 0 ? null : value; - } - return null; -}; +/** Parse Java Properties.load(InputStream) syntax from its ISO-8859-1 text. */ diff --git a/src/ghidra/GhidraJavaProperties.ts b/src/ghidra/GhidraJavaProperties.ts new file mode 100644 index 000000000..ab3b7bead --- /dev/null +++ b/src/ghidra/GhidraJavaProperties.ts @@ -0,0 +1,115 @@ +import { err, ok, type Result } from "../domain/result.js"; + +/** Parse Java Properties.load(InputStream) syntax from its ISO-8859-1 text. */ +export const parseGhidraJavaProperties = ( + content: string, +): Result, string> => { + const values = new Map(); + for (const line of logicalPropertyLines(content)) { + let start = 0; + while (isPropertyWhitespace(line[start])) start += 1; + if (start === line.length || line[start] === "#" || line[start] === "!") + continue; + let end = start; + let escaped = false; + while (end < line.length) { + const character = line[end]; + if ( + !escaped && + (character === "=" || + character === ":" || + isPropertyWhitespace(character)) + ) + break; + if (character === "\\") escaped = !escaped; + else escaped = false; + end += 1; + } + let valueStart = end; + while (isPropertyWhitespace(line[valueStart])) valueStart += 1; + if (line[valueStart] === "=" || line[valueStart] === ":") valueStart += 1; + while (isPropertyWhitespace(line[valueStart])) valueStart += 1; + const key = decodePropertyEscapes(line.slice(start, end)); + if (!key.ok) return err(key.error); + const value = decodePropertyEscapes(line.slice(valueStart)); + if (!value.ok) return err(value.error); + values.set(key.value, value.value); + } + return ok(values); +}; + +const isPropertyWhitespace = (value: string | undefined): boolean => + value === " " || value === "\t" || value === "\f"; + +/** Join odd-backslash continuations while stripping leading continuation space. */ +function* logicalPropertyLines(content: string): Generator { + let physicalStart = 0; + let logical = ""; + let continuing = false; + while (physicalStart <= content.length) { + let physicalEnd = physicalStart; + while ( + physicalEnd < content.length && + content[physicalEnd] !== "\n" && + content[physicalEnd] !== "\r" + ) + physicalEnd += 1; + let line = content.slice(physicalStart, physicalEnd); + let leading = 0; + while (isPropertyWhitespace(line[leading])) leading += 1; + const comment = + !continuing && (line[leading] === "#" || line[leading] === "!"); + if (continuing) line = line.slice(leading); + let continued = false; + if (!comment) { + let slashes = 0; + for ( + let index = line.length - 1; + index >= 0 && line[index] === "\\"; + index -= 1 + ) + slashes += 1; + continued = slashes % 2 === 1; + logical += continued ? line.slice(0, -1) : line; + } + if (!continued) { + yield logical; + logical = ""; + } + continuing = continued; + if (physicalEnd === content.length) break; + physicalStart = + content[physicalEnd] === "\r" && content[physicalEnd + 1] === "\n" + ? physicalEnd + 2 + : physicalEnd + 1; + } + // Properties.load still consumes the accumulated line when EOF follows a + // continuation marker; the marker itself was already removed above. + if (continuing) yield logical; +} + +const decodePropertyEscapes = (value: string): Result => { + let result = ""; + for (let index = 0; index < value.length; index += 1) { + const character = value[index]; + if (character !== "\\") { + result += character; + continue; + } + const escaped = value[++index]; + if (escaped === undefined) + return err("Trailing escape in Java properties value"); + if (escaped === "t") result += "\t"; + else if (escaped === "n") result += "\n"; + else if (escaped === "r") result += "\r"; + else if (escaped === "f") result += "\f"; + else if (escaped === "u") { + const digits = value.slice(index + 1, index + 5); + if (digits.length !== 4 || !/^[0-9a-f]{4}$/iu.test(digits)) + return err("Malformed Unicode escape in Java properties file"); + result += String.fromCharCode(Number.parseInt(digits, 16)); + index += 4; + } else result += escaped; + } + return ok(result); +}; diff --git a/src/ghidra/GhidraLanguageOverride.test.ts b/src/ghidra/GhidraLanguageOverride.test.ts index a355b39fa..5f90a1454 100644 --- a/src/ghidra/GhidraLanguageOverride.test.ts +++ b/src/ghidra/GhidraLanguageOverride.test.ts @@ -42,7 +42,7 @@ const X86_LDEFS = ` const host: GhidraInstallationHost = { platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/src/ghidra/GhidraMipsProfile.test.ts b/src/ghidra/GhidraMipsProfile.test.ts index 31a121cd1..ae72a3069 100644 --- a/src/ghidra/GhidraMipsProfile.test.ts +++ b/src/ghidra/GhidraMipsProfile.test.ts @@ -19,7 +19,7 @@ import { ghidraProfileLanguageOverride } from "./GhidraAnalysisProfile.js"; const host: GhidraInstallationHost = { platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/src/ghidra/GhidraProvider.behavior.test.ts b/src/ghidra/GhidraProvider.behavior.test.ts index 8b9c25461..3979222d9 100644 --- a/src/ghidra/GhidraProvider.behavior.test.ts +++ b/src/ghidra/GhidraProvider.behavior.test.ts @@ -38,7 +38,7 @@ const INSTALL = "/opt/ghidra_12.1.4_PUBLIC"; const installationHost = (): GhidraInstallationHost => ({ platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/src/ghidra/GhidraProviderClient.ts b/src/ghidra/GhidraProviderClient.ts index 5a4f4eafd..5911985df 100644 --- a/src/ghidra/GhidraProviderClient.ts +++ b/src/ghidra/GhidraProviderClient.ts @@ -32,6 +32,7 @@ import { AnalysisTimeoutError, } from "../domain/analysisErrorCore.js"; import type { AnalysisError } from "../domain/analysisErrorBase.js"; +import type { EvidenceLocation } from "../domain/evidence.js"; import { jsonValueSchema, type JsonValue } from "../domain/jsonValue.js"; import { ProviderAdapterError } from "../domain/providerAdapterError.js"; import { err, ok, type Result } from "../domain/result.js"; @@ -678,10 +679,12 @@ export const createGhidraProviderClient = (input: { normalized: JsonValue, rawResult: JsonValue, observationLimitations: readonly string[] = [], + locations: readonly EvidenceLocation[] = [], ) => { const relationshipCoverage = relationshipCoverageFor(operation); return createAnalysisExecution(normalized, committedProfile.provider, { rawResult, + locations, analysisProfile: committedProfile, ...(relationshipCoverage === undefined ? {} : { relationshipCoverage }), limitations: [ @@ -776,11 +779,13 @@ export const createGhidraProviderClient = (input: { ); let normalized: JsonValue; let observationLimitations: readonly string[] = []; + let observationLocations: readonly EvidenceLocation[] = []; if (isGhidraFunctionOperation(operation)) { const result = parseGhidraFunctionResult(operation, called.value); if (!result.ok) return result; normalized = result.value.value; observationLimitations = result.value.limitations; + observationLocations = result.value.locations ?? []; } else { const result = parseGhidraInventoryResult(operation, called.value); if (!result.ok) return result; @@ -875,6 +880,7 @@ export const createGhidraProviderClient = (input: { normalized, called.value, observationLimitations, + observationLocations, ), ); }, diff --git a/src/ghidra/GhidraPspExtension.ts b/src/ghidra/GhidraPspExtension.ts index 1a3769378..9c017f367 100644 --- a/src/ghidra/GhidraPspExtension.ts +++ b/src/ghidra/GhidraPspExtension.ts @@ -13,6 +13,7 @@ import { import type { AnalysisError } from "../domain/analysisErrorBase.js"; import { err, ok, type Result } from "../domain/result.js"; import type { GhidraInstallationInspection } from "./GhidraInstallation.js"; +import { parseGhidraJavaProperties } from "./GhidraJavaProperties.js"; /** Installed processor code and data, distinct from REA's analysis-extension ABI. */ export const ghidraPspExtensionSchema = z.strictObject({ @@ -88,7 +89,7 @@ export const inspectGhidraPspExtension = async ( throw new Error("The installed Allegrex extension has no loader JAR."); const hash = createHash("sha256"); let bytesRead = 0; - let properties = ""; + let properties = Buffer.alloc(0); for (const relative of files) { signal?.throwIfAborted(); const path = join(root, relative); @@ -135,22 +136,22 @@ export const inspectGhidraPspExtension = async ( ); bytesRead += before.size; if (relative === "extension.properties") - properties = Buffer.concat(chunks).toString("utf8"); + properties = Buffer.concat(chunks); } finally { await handle.close(); } } // Ghidra's extension.properties version is the compatible Ghidra version, // not the extension release (e.g. v21.4); content identity supplies the latter. - const property = (name: string): string => { - const values = properties.split(/\r?\n/u).flatMap((line) => { - const match = /^\s*([A-Za-z][A-Za-z0-9]*)\s*=\s*(.*?)\s*$/u.exec(line); - return match?.[1] === name ? [match[2] ?? ""] : []; - }); - if (values.length !== 1) - throw new Error(`Allegrex extension must declare exactly one ${name}.`); - return values[0] ?? ""; - }; + const parsedProperties = parseGhidraJavaProperties( + properties.toString("latin1"), + ); + if (!parsedProperties.ok) + throw new Error( + `Invalid Allegrex extension properties: ${parsedProperties.error}`, + ); + const property = (name: string): string | undefined => + parsedProperties.value.get(name); if ( property("name") !== "ghidra-allegrex" || property("version") !== ghidraVersion diff --git a/src/ghidra/GhidraRiscvProfile.test.ts b/src/ghidra/GhidraRiscvProfile.test.ts index 9bbb65cf3..881ba0078 100644 --- a/src/ghidra/GhidraRiscvProfile.test.ts +++ b/src/ghidra/GhidraRiscvProfile.test.ts @@ -53,7 +53,7 @@ const RISCV_LDEFS = ` const host: GhidraInstallationHost = { platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/src/ghidra/GhidraSnapshotCache.test.ts b/src/ghidra/GhidraSnapshotCache.test.ts index 703bb4906..9cf5c24ad 100644 --- a/src/ghidra/GhidraSnapshotCache.test.ts +++ b/src/ghidra/GhidraSnapshotCache.test.ts @@ -39,7 +39,8 @@ const fixture = (version = "12.1.4") => { { platform: "linux", architecture: "x64", - readText: () => `application.version=${version}\n`, + readText: () => + `application.version=${version}\napplication.java.min=21\n`, executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/src/go/GoBinaryProvider.ts b/src/go/GoBinaryProvider.ts index a1c0cc6a3..466136f3f 100644 --- a/src/go/GoBinaryProvider.ts +++ b/src/go/GoBinaryProvider.ts @@ -1,5 +1,7 @@ import { readStableArtifact } from "../artifacts/readStableArtifact.js"; +import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; +import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; import type { ExecutionOptions } from "../application/AnalysisProvider.js"; import type { GoBinaryPort } from "../application/go/GoBinaryPort.js"; import { AnalysisError } from "../domain/analysisErrorBase.js"; @@ -18,6 +20,7 @@ import { type InspectGoBinaryInput, } from "../domain/go/goBinary.js"; import { ProviderAdapterError } from "../domain/providerAdapterError.js"; +import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import { err, ok, type Result } from "../domain/result.js"; import { readGoBinaryImage, @@ -36,13 +39,19 @@ const OPERATION = "inspect_go_binary"; const INPUT_BYTES = 256 * 1024 * 1024; const OUTPUT_BYTES = 8 * 1024 * 1024; -const failureFor = ( +const failureForPrimary = ( cause: unknown, path: string, signal?: AbortSignal, ): AnalysisError => { if (cause instanceof AnalysisError) return cause; - if (signal?.aborted) return new AnalysisCancelledError(OPERATION); + if (cause instanceof ArtifactReaderFailure && cause.reason === "integrity") + return new AnalysisArtifactChangedError(OPERATION, path, cause.message, { + cause, + }); + if (cause instanceof ArtifactReaderFailure && cause.reason === "cancelled") + return new AnalysisCancelledError(OPERATION, { cause }); + if (signal?.aborted) return new AnalysisCancelledError(OPERATION, { cause }); if (cause instanceof GoBinaryResourceFailure) return new AnalysisResourceConstraintError( OPERATION, @@ -64,12 +73,6 @@ const failureFor = ( }, ]); if (cause instanceof ArtifactReaderFailure) { - if (cause.reason === "integrity") - return new AnalysisArtifactChangedError(OPERATION, path, cause.message, { - cause, - }); - if (cause.reason === "cancelled") - return new AnalysisCancelledError(OPERATION); if (cause.reason === "limit") return new AnalysisResourceConstraintError( OPERATION, @@ -110,6 +113,23 @@ const failureFor = ( }); }; +const failureFor = ( + cause: unknown, + path: string, + signal?: AbortSignal, +): AnalysisError => { + const primary = failureForPrimary(cause, path, signal); + if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) + return primary; + const cleanup = new ProviderCleanupError( + GO_BINARY_PROVIDER_IDENTITY.id, + cause.cleanup.resources, + { reason: cause.cleanup.reason }, + { operation: OPERATION, cause }, + ); + return analysisErrorWithCleanupFailure(primary, cleanup, OPERATION); +}; + const outputLimit = (path: string) => new AnalysisResourceConstraintError( OPERATION, @@ -121,6 +141,11 @@ const outputLimit = (path: string) => /** Stable in-process metadata inspection without subprocesses, temporary files or Go installation. */ export class GoBinaryProvider implements GoBinaryPort { readonly identity = GO_BINARY_PROVIDER_IDENTITY; + readonly #resources = new ArtifactResourceScope(); + + close(): Promise { + return this.#resources.close(); + } /** Read complete compiler/module metadata while preserving original byte identity and source ranges. */ async inspect( @@ -128,10 +153,14 @@ export class GoBinaryProvider implements GoBinaryPort { options?: ExecutionOptions, ): Promise> { try { - const snapshot = await readStableArtifact( - input.path, - INPUT_BYTES, - options?.signal, + const snapshot = await this.#resources.run(() => + readStableArtifact( + input.path, + INPUT_BYTES, + options?.signal, + undefined, + this.#resources, + ), ); options?.signal?.throwIfAborted(); const image = readGoBinaryImage(snapshot.bytes); diff --git a/src/hopper/BridgeLauncher.ts b/src/hopper/BridgeLauncher.ts index 8201ee2df..043d394a4 100644 --- a/src/hopper/BridgeLauncher.ts +++ b/src/hopper/BridgeLauncher.ts @@ -413,6 +413,8 @@ const launchHopperProcess = async (input: { runId: input.session.runId, expectedCommand: ownershipCommand, hostEnvironment: input.options.environment, + // The helper observes EOF when this REA process exits, including SIGKILL. + stdin: "pipe", ...(input.signal === undefined ? {} : { signal: input.signal }), }); return spawn(input.argumentsForTarget); @@ -434,6 +436,7 @@ export const linuxDemoLaunch = ( return undefined; const helperArguments = [ options.demoHelperPath, + "--owner-stdin", "--strategy", strategy ?? "direct", ...(strategy === "user-mount-namespace" ? ["--mount-private-x11"] : []), diff --git a/src/ida/IdaNativeProtocol.test.ts b/src/ida/IdaNativeProtocol.test.ts index f90673031..d59f598dd 100644 --- a/src/ida/IdaNativeProtocol.test.ts +++ b/src/ida/IdaNativeProtocol.test.ts @@ -375,6 +375,42 @@ describe("native IDA query identity", () => { ); }); +describe("native IDA callee truncation", () => { + it("rejects native successes without an explicit truncation marker and preserves upstream failures", async () => { + const { client, producer } = await fixture(); + const previous = producer.overrideCall; + try { + producer.overrideCall = (name, args) => + name === "callees" + ? [{ callees: [], error: null }] + : previous?.(name, args); + for (const operation of [ + "procedure_callees", + "analyze_function", + ] as const) { + const result = await client.execute(operation, { procedure: "main" }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toBeInstanceOf(AnalysisProtocolError); + expect(result.error.message).toContain("truncation marker"); + } + } + producer.overrideCall = (name, args) => + name === "callees" + ? [{ callees: null, error: "callee database failure" }] + : previous?.(name, args); + const result = await client.execute("procedure_callees", { + procedure: "main", + }); + expect(result.ok).toBe(false); + if (!result.ok) + expect(result.error.message).toContain("callee database failure"); + } finally { + await client.close(); + } + }); +}); + describe("native IDA callee lookup batches", () => { it("batches unique callees and binds reordered replies to their source queries", async () => { const { client, producer } = await fixture(); diff --git a/src/ida/IdaNativeProtocol.ts b/src/ida/IdaNativeProtocol.ts index 711383f8e..a7ac782d5 100644 --- a/src/ida/IdaNativeProtocol.ts +++ b/src/ida/IdaNativeProtocol.ts @@ -63,7 +63,21 @@ const nativeErrorSchema = z .nullish() .transform((value) => value ?? undefined); export const nativeCalleesSchema = z - .array(modernCalleesSchema.element.extend({ error: nativeErrorSchema })) + .array( + modernCalleesSchema.element + .extend({ error: nativeErrorSchema }) + .transform((page) => { + if ( + page.error === undefined && + page.callees !== null && + page.more === undefined + ) + throw new AnalysisProtocolError( + "Native IDA callees omitted an explicit truncation marker.", + ); + return page; + }), + ) .length(1); export const nativeXrefsSchema = z .array(modernXrefsSchema.element.extend({ error: nativeErrorSchema })) diff --git a/src/ida/IdaWorkspace.ts b/src/ida/IdaWorkspace.ts index 0b3c36231..c7d9e642c 100644 --- a/src/ida/IdaWorkspace.ts +++ b/src/ida/IdaWorkspace.ts @@ -85,8 +85,10 @@ export class IdaWorkspace { slice === undefined ? position + bytes.length : Math.min(position + bytes.length, slice.offset + slice.size); - const admitted = bytes.subarray(start - position, end - position); - if (admitted.length > 0) { + // A chunk after the slice has end < position, and a negative subarray + // bound would count from the chunk's end instead of being empty. + if (end > start) { + const admitted = bytes.subarray(start - position, end - position); inputHash.update(admitted); await input.write(admitted); } diff --git a/src/ida/IdaWorkspaceThinning.test.ts b/src/ida/IdaWorkspaceThinning.test.ts index 7feca3ddc..baba6e145 100644 --- a/src/ida/IdaWorkspaceThinning.test.ts +++ b/src/ida/IdaWorkspaceThinning.test.ts @@ -5,7 +5,7 @@ import { afterEach, describe, expect, it } from "vitest"; import { parseBinaryTarget } from "../application/BinaryTargetResolver.js"; import { parseExecutableHeader } from "../domain/binaryTarget.js"; -import { fat } from "../domain/binaryTarget.fixture.js"; +import { fat, thinMach } from "../domain/binaryTarget.fixture.js"; import { createIdaTarget, RecordingIdaMcp, @@ -35,6 +35,46 @@ const universalTarget = async (hostArchitecture: "arm64" | "x64") => { return { bytes, target: resolved.value }; }; +/** One slice of a synthetic universal file: CPU type, offset and size. */ +interface Layout { + readonly cpu: number; + readonly offset: number; + readonly size: number; + readonly alignmentExponent?: number; +} + +/** + * Write a universal file whose slices span more than one 64 KiB read, each + * filled with its own byte so bytes outside the selected slice are visible. + */ +const largeUniversalTarget = async ( + layout: readonly Layout[], + hostArchitecture: "arm64" | "x64", +) => { + const directory = await createTestTempDirectory("rea-ida-thin-large-"); + roots.push(directory); + const path = join(directory, "universal"); + const total = Math.max(...layout.map(({ offset, size }) => offset + size)); + const bytes = Buffer.alloc(total); + bytes.writeUInt32BE(0xcafebabe, 0); + bytes.writeUInt32BE(layout.length, 4); + layout.forEach(({ cpu, offset, size, alignmentExponent = 14 }, index) => { + const entry = 8 + index * 20; + bytes.writeUInt32BE(cpu, entry); + bytes.writeUInt32BE(offset, entry + 8); + bytes.writeUInt32BE(size, entry + 12); + bytes.writeUInt32BE(alignmentExponent, entry + 16); + bytes.fill(0x11 * (index + 1), offset, offset + size); + thinMach(0xfeedfacf, cpu).copy(bytes, offset); + }); + await writeFile(path, bytes); + const resolved = await parseBinaryTarget(path, { hostArchitecture }); + if (!resolved.ok) throw resolved.error; + if (resolved.value.format !== "mach-o-universal") + throw new Error("the universal fixture did not resolve as a FAT container"); + return { bytes, target: resolved.value }; +}; + describe("IDA workspace input thinning", () => { it.skipIf(process.platform === "win32")( "thins the selected arm64 slice into the private headless input", @@ -78,6 +118,63 @@ describe("IDA workspace input thinning", () => { }, ); + it.skipIf(process.platform === "win32")( + "copies exactly the selected slice when later slices follow it across read boundaries", + async () => { + const { bytes, target } = await largeUniversalTarget( + [ + { + cpu: 0x01000007, + offset: 4096, + size: 8480, + alignmentExponent: 12, + }, + { cpu: 0x0100000c, offset: 16384, size: 33464 }, + { cpu: 0x00000007, offset: 65536, size: 33464 }, + ], + "arm64", + ); + const workspace = await IdaWorkspace.allocate(target); + roots.push(workspace.directory); + await workspace.copyInput(); + + const input = await readFile(workspace.inputPath); + const { offset, size } = target.universalSlice; + expect(size, "the arm64 slice is selected").toBe(33464); + expect(input.length, "no byte after the slice is copied").toBe(size); + expect(input.equals(bytes.subarray(offset, offset + size))).toBe(true); + expect(workspace.inputSha256).toBe( + createHash("sha256") + .update(bytes.subarray(offset, offset + size)) + .digest("hex"), + ); + await workspace.remove(); + }, + ); + + it.skipIf(process.platform === "win32")( + "copies exactly the first slice when it is selected and others follow", + async () => { + const { bytes, target } = await largeUniversalTarget( + [ + { cpu: 0x01000007, offset: 16384, size: 37456 }, + { cpu: 0x0100000c, offset: 65536, size: 33464 }, + ], + "x64", + ); + const workspace = await IdaWorkspace.allocate(target); + roots.push(workspace.directory); + await workspace.copyInput(); + + const input = await readFile(workspace.inputPath); + const { offset, size } = target.universalSlice; + expect(size, "the x86_64 slice is selected").toBe(37456); + expect(input.length, "no byte after the slice is copied").toBe(size); + expect(input.equals(bytes.subarray(offset, offset + size))).toBe(true); + await workspace.remove(); + }, + ); + it("keeps a whole-file copy for thin targets", async () => { const { root, target } = await createIdaTarget("arm64"); roots.push(root); diff --git a/src/javascript/analysis/JavaScriptAnalysisWorker.ts b/src/javascript/analysis/JavaScriptAnalysisWorker.ts index c02ddaa3e..6a587915b 100644 --- a/src/javascript/analysis/JavaScriptAnalysisWorker.ts +++ b/src/javascript/analysis/JavaScriptAnalysisWorker.ts @@ -27,10 +27,8 @@ import { ProviderAdapterError } from "../../domain/providerAdapterError.js"; import { ProviderCleanupError } from "../../domain/providerCleanupError.js"; import { ok, err, type Result } from "../../domain/result.js"; import { javaScriptRuntime } from "../../domain/runtimeVersion.js"; -import { - PrivateRuntimeRoot, - PrivateRuntimeRootUnavailableError, -} from "../../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRoot } from "../../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRootUnavailableError } from "../../process/PrivateRuntimeRootUnavailableError.js"; import { javaScriptWorkerMemoryLimitBytes } from "../../process/JavaScriptWorkerMemoryLimit.js"; import { ProviderProcessSupervisor, @@ -735,7 +733,7 @@ export class JavaScriptAnalysisWorker { PROVIDER, OPERATION, cause.message, - { cause }, + { cause, retryable: cause.retryable }, ) : new ProviderAdapterError(PROVIDER, OPERATION, { cause, diff --git a/src/javascript/analysis/JavaScriptAnalysisWorkerSchemas.ts b/src/javascript/analysis/JavaScriptAnalysisWorkerSchemas.ts index b666cfa9b..84a63d79b 100644 --- a/src/javascript/analysis/JavaScriptAnalysisWorkerSchemas.ts +++ b/src/javascript/analysis/JavaScriptAnalysisWorkerSchemas.ts @@ -475,7 +475,9 @@ const origin = z .strictObject({ specifier: z.string(), importedPath: strings, - resolutionMode: z.enum(["import", "require"]).optional(), + resolutionMode: z + .enum(["import", "require", "compiler-dependent"]) + .optional(), }) .transform(({ resolutionMode, ...rest }) => ({ ...rest, @@ -530,7 +532,9 @@ const coverage = z }); const moduleLink = z .strictObject({ - resolutionMode: z.enum(["import", "require"]).optional(), + resolutionMode: z + .enum(["import", "require", "compiler-dependent"]) + .optional(), kind: z.enum([ "import", "type-import", diff --git a/src/javascript/recovery/RecoveryFiles.ts b/src/javascript/recovery/RecoveryFiles.ts index 0503a83e1..c64f011b4 100644 --- a/src/javascript/recovery/RecoveryFiles.ts +++ b/src/javascript/recovery/RecoveryFiles.ts @@ -279,6 +279,6 @@ export const checkRecoveryDeadline = ( signal?: AbortSignal, ): void => { checkRecoveryCancellation(signal); - if (Date.now() >= deadline) + if (performance.now() >= deadline) throw new AnalysisTimeoutError(OPERATION, RECOVERY_LIMITS.timeoutMs); }; diff --git a/src/javascript/recovery/WakaruCommand.test.ts b/src/javascript/recovery/WakaruCommand.test.ts index 08e43e44a..8dcb74be4 100644 --- a/src/javascript/recovery/WakaruCommand.test.ts +++ b/src/javascript/recovery/WakaruCommand.test.ts @@ -33,7 +33,7 @@ it("rejects an exhausted shared execution budget before launching the next comma arguments: ["--version"], cwd: "/tmp/unused", environment: {}, - deadline: Date.now() - 1, + deadline: performance.now() - 1, launcher: async () => { throw new Error("An expired budget must not launch"); }, @@ -52,7 +52,7 @@ it("preserves caller cancellation before acquiring an expired execution budget", arguments: ["--version"], cwd: "/tmp/unused", environment: {}, - deadline: Date.now() - 1, + deadline: performance.now() - 1, signal: AbortSignal.abort(), launcher: async () => { throw new Error("A cancelled request must not launch"); @@ -86,7 +86,7 @@ const commandFixture = ( arguments: ["--version"], cwd: "/tmp/unused", environment: {}, - deadline: Date.now() + 5_000, + deadline: performance.now() + 5_000, launcher, }, }; @@ -140,7 +140,7 @@ it("enforces the shared deadline while exited output streams remain open", async }); try { await expect( - runWakaruCommand({ ...context, deadline: Date.now() + 50 }), + runWakaruCommand({ ...context, deadline: performance.now() + 50 }), ).rejects.toMatchObject({ _tag: "AnalysisTimeoutError", operation: "recover_javascript_sources", diff --git a/src/javascript/recovery/WakaruProvider.ts b/src/javascript/recovery/WakaruProvider.ts index 7a51c8bd5..e25812663 100644 --- a/src/javascript/recovery/WakaruProvider.ts +++ b/src/javascript/recovery/WakaruProvider.ts @@ -9,7 +9,11 @@ import type { import { SafeOutputTree } from "../../artifacts/SafeOutputTree.js"; import { SafeOutputTreeCreationFailure } from "../../artifacts/SafeOutputTreeCreationFailure.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; -import { AnalysisOutputError } from "../../domain/analysisErrorCore.js"; +import { + AnalysisCancelledError, + AnalysisOutputError, +} from "../../domain/analysisErrorCore.js"; +import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; import { javascriptRecoveryResultSchema, type JavaScriptRecoveryInput, @@ -100,7 +104,7 @@ export class WakaruProvider implements JavaScriptRecoveryPort { let tree: SafeOutputTree | undefined; let failed: { readonly cause: unknown } | undefined; let execution: AnalysisExecution | undefined; - const deadline = Date.now() + RECOVERY_LIMITS.timeoutMs; + const deadline = performance.now() + RECOVERY_LIMITS.timeoutMs; try { checkRecoveryCancellation(options?.signal); const engine = await resolveWakaruCommand(this.environment); @@ -139,12 +143,16 @@ export class WakaruProvider implements JavaScriptRecoveryPort { await rm(root, { recursive: true, force: true }); root = undefined; checkRecoveryDeadline(deadline, options?.signal); - await tree.commit(); + await tree.commit(options?.signal); } catch (cause: unknown) { failed = { cause }; } if (failed !== undefined) { - const failure = failed.cause; + const failure = + failed.cause instanceof ArtifactReaderFailure && + failed.cause.reason === "cancelled" + ? new AnalysisCancelledError(OPERATION, { cause: failed.cause }) + : failed.cause; const residuals: string[] = []; const cleanupFailures: { resource: string; reason: string }[] = []; const cleanupOwner = diff --git a/src/javascript/sourceMaps/DecodedSourceMap.ts b/src/javascript/sourceMaps/DecodedSourceMap.ts index 60bfcfc0e..e9ed304e1 100644 --- a/src/javascript/sourceMaps/DecodedSourceMap.ts +++ b/src/javascript/sourceMaps/DecodedSourceMap.ts @@ -19,31 +19,6 @@ export const isBeforeSourceMapLeafStop = ( ); }; -/** Resolve one declaration with the same pinned upstream implementation used by full maps. */ -export const resolveSourceMapSource = ( - source: string | null, - sourceRoot: string | null | undefined, - mapUrl: string, -): string => { - const map = new TraceMap( - { - version: 3, - names: [], - sources: [source ?? ""], - ...(sourceRoot == null ? {} : { sourceRoot }), - mappings: "", - }, - mapUrl, - ); - const resolved = map.resolvedSources[0]; - if (resolved === undefined) - throw new SourceMapFormatFailure( - "format", - "Source-map resolver did not return the requested source identity.", - ); - return resolved; -}; - /** Decode leaf mappings and validate producer indices before any consumer publishes them. */ export const decodeValidatedSourceMapLeaves = ( leaves: readonly SourceMapLeaf[], diff --git a/src/javascript/sourceMaps/SourceMapCommand.ts b/src/javascript/sourceMaps/SourceMapCommand.ts index e86954106..9e8837952 100644 --- a/src/javascript/sourceMaps/SourceMapCommand.ts +++ b/src/javascript/sourceMaps/SourceMapCommand.ts @@ -16,10 +16,8 @@ import { ProviderCleanupError } from "../../domain/providerCleanupError.js"; import type { JsonValue } from "../../domain/jsonValue.js"; import { err, ok, type Result } from "../../domain/result.js"; import { WEB_SOURCE_MAP_LIMITS } from "../../domain/webSourceLocation.js"; -import { - PrivateRuntimeRoot, - PrivateRuntimeRootUnavailableError, -} from "../../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRoot } from "../../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRootUnavailableError } from "../../process/PrivateRuntimeRootUnavailableError.js"; import { ProviderStartupDeadline } from "../../process/ProviderDeadline.js"; import { javaScriptWorkerMemoryLimitBytes } from "../../process/JavaScriptWorkerMemoryLimit.js"; import { cleanupOwnedProcessGroup } from "../../process/ProcessOwnership.js"; @@ -261,7 +259,7 @@ class OwnedCodec implements SourceMapCleanupOwner { PROVIDER, OPERATION, cause.message, - { cause }, + { cause, retryable: cause.retryable }, ) : new ProviderAdapterError(PROVIDER, OPERATION, { cause, diff --git a/src/mcpDoctor.ts b/src/mcpDoctor.ts index 62a588280..d7bf1e366 100644 --- a/src/mcpDoctor.ts +++ b/src/mcpDoctor.ts @@ -1,6 +1,7 @@ import { Client } from "@modelcontextprotocol/client"; import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; import { Formatter, Help, z } from "incur"; +import { performance } from "node:perf_hooks"; import { resolve } from "node:path"; import { CATALOG_IDENTITY } from "./catalogIdentity.js"; @@ -74,14 +75,15 @@ interface McpDoctorCheck { /** Diagnose the actual production stdio adapter with one startup-bounded SDK session. */ export const runProductionMcpDoctor = async (options: McpDoctorOptions) => { const deadline = - Date.now() + (options.deadlineMs ?? MCP_STARTUP_POLICY.doctorDeadlineMs); + performance.now() + + (options.deadlineMs ?? MCP_STARTUP_POLICY.doctorDeadlineMs); const controller = new AbortController(); const timer = setTimeout( () => controller.abort(new Error("Production MCP doctor deadline expired")), - Math.max(1, deadline - Date.now()), + Math.max(1, Math.ceil(deadline - performance.now())), ); const stderr = captureStderr(); - const transport = new TrackedStdioClientTransport({ + const transport = new OwnedStdioClientTransport({ command: options.command, args: [...options.args], cwd: options.cwd, @@ -90,21 +92,20 @@ export const runProductionMcpDoctor = async (options: McpDoctorOptions) => { }); transport.stderr?.on("data", stderr.append); const client = new Client({ name: "rea-mcp-doctor", version: "1" }); + let result: ProductionMcpDoctorResult; + let cleanupFailure: { readonly cause: unknown } | undefined; try { await client.connect( transport, requestOptions(deadline, controller.signal), ); - return { - ...(await inspectProductionMcpSession( - client, - deadline, - controller.signal, - )), - diagnostics: stderr.value(), - }; + result = await inspectProductionMcpSession( + client, + deadline, + controller.signal, + ); } catch (cause: unknown) { - return { + result = { healthy: false, adapter: "production-stdio" as const, server: null, @@ -118,14 +119,71 @@ export const runProductionMcpDoctor = async (options: McpDoctorOptions) => { detail: errorMessage(cause), }, ], - diagnostics: stderr.value(), }; } finally { clearTimeout(timer); - await closeMcpChild(client, transport); + try { + await client.close(); + } catch (cause: unknown) { + cleanupFailure = { cause }; + } + try { + // An interrupted connect can clear the client's transport reference + // before its startup child is closed. The transport retains that child. + await transport.close(); + } catch (cause: unknown) { + cleanupFailure = { + cause: + cleanupFailure === undefined || cleanupFailure.cause === cause + ? cause + : new AggregateError( + [cleanupFailure.cause, cause], + `MCP client and transport cleanup failed: ${errorMessage(cleanupFailure.cause)}; ${errorMessage(cause)}`, + ), + }; + } } + if (cleanupFailure !== undefined) + result = { + ...result, + healthy: false, + checks: [ + ...result.checks, + { + name: "cleanup", + ok: false, + detail: `MCP stdio cleanup failed: ${errorMessage(cleanupFailure.cause)}`, + }, + ], + }; + return { ...result, diagnostics: stderr.value() }; }; +type ProductionMcpDoctorResult = + | Awaited> + | { + readonly healthy: false; + readonly adapter: "production-stdio"; + readonly server: null; + readonly inventory: null; + readonly identity: null; + readonly request_flow: { + readonly tool: "binary_session"; + readonly ok: false; + }; + readonly checks: readonly McpDoctorCheck[]; + }; + +/** Join SDK-triggered and caller-triggered close calls for the same child. */ +class OwnedStdioClientTransport extends StdioClientTransport { + #closePromise: Promise | undefined; + + override close(): Promise { + this.#closePromise ??= super.close(); + return this.#closePromise; + } +} + const inspectProductionMcpSession = async ( client: Client, deadline: number, @@ -385,7 +443,7 @@ const isOutputFormat = (value: string | undefined): value is OutputFormat => const requestOptions = (deadline: number, signal: AbortSignal) => ({ signal, - timeout: Math.max(1, deadline - Date.now()), + timeout: Math.max(1, Math.ceil(deadline - performance.now())), }); const targetFreeEnvironment = ( @@ -428,61 +486,3 @@ const isRecord = (value: unknown): value is Readonly> => const errorMessage = (cause: unknown): string => cause instanceof Error ? cause.message : String(cause); - -class TrackedStdioClientTransport extends StdioClientTransport { - spawnedPid: number | null = null; - - override async start(): Promise { - await super.start(); - this.spawnedPid = this.pid; - } -} - -const closeMcpChild = async ( - client: Client, - transport: TrackedStdioClientTransport, -): Promise => { - const pid = transport.spawnedPid ?? transport.pid; - await Promise.allSettled([client.close()]); - await Promise.allSettled([transport.close()]); - if (pid === null || !(await processExists(pid))) return; - await terminateProcess(pid, "SIGTERM"); - if (await waitForProcessExit(pid, 1_000)) return; - await terminateProcess(pid, "SIGKILL"); - await waitForProcessExit(pid, 1_000); -}; - -const terminateProcess = async ( - pid: number, - signal: NodeJS.Signals, -): Promise => { - try { - process.kill(pid, signal); - } catch (cause: unknown) { - if (!(cause instanceof Error && "code" in cause && cause.code === "ESRCH")) - throw cause; - } -}; - -const waitForProcessExit = async ( - pid: number, - timeoutMs: number, -): Promise => { - const deadline = Date.now() + timeoutMs; - do { - if (!(await processExists(pid))) return true; - await new Promise((resolve) => setTimeout(resolve, 20)); - } while (Date.now() < deadline); - return !(await processExists(pid)); -}; - -const processExists = async (pid: number): Promise => { - try { - process.kill(pid, 0); - return true; - } catch (cause: unknown) { - if (cause instanceof Error && "code" in cause && cause.code === "ESRCH") - return false; - throw cause; - } -}; diff --git a/src/native/AppleDispatchCoverage.ts b/src/native/AppleDispatchCoverage.ts index c49e35acc..a6c68ca51 100644 --- a/src/native/AppleDispatchCoverage.ts +++ b/src/native/AppleDispatchCoverage.ts @@ -42,14 +42,62 @@ export const pushDispatchCoverage = (input: { vtables, swift, } = input; + const classOwnedMethods = result.objc_dispatch_implementations.filter( + ({ category }) => category === undefined, + ); + const classRecords = [ + ...result.objc_classes.flatMap((record) => + record.decode?.status === "decoded" + ? [] + : [ + `class ${record.name}: ${record.decode?.reason ?? record.decode?.status ?? "decode_status_missing"}`, + ], + ), + ...result.objc_protocol_records.flatMap((record) => + record.decode.status === "decoded" + ? [] + : [ + `protocol ${record.name}: ${record.decode.reason ?? record.decode.status}`, + ], + ), + ...classOwnedMethods.flatMap((record) => + record.decode.status === "decoded" + ? [] + : [ + `method ${record.class_name} ${record.method_type} ${record.selector}: ${record.decode.reason ?? record.decode.status}`, + ], + ), + ...result.objc_ivars.flatMap((record) => + record.decode.status === "decoded" + ? [] + : [ + `ivar ${record.class_name}.${record.name}: ${record.decode.reason ?? record.decode.status}`, + ], + ), + ]; + const classReasons = [ + ...failures, + ...classRecords, + ...(truncated ? ["max_records_reached"] : []), + ]; + const categoryMethods = result.objc_dispatch_implementations.filter( + ({ category }) => category !== undefined, + ); + const categoryMethodReasons = categoryMethods.flatMap((record) => + record.decode.status === "decoded" + ? [] + : [ + `category method ${record.category} ${record.class_name} ${record.method_type} ${record.selector}: ${record.decode.reason ?? record.decode.status}`, + ], + ); result.coverage.push({ facet: "objc_class_method_ivar_metadata", - status: failures.length > 0 || truncated ? "partial" : "complete", - reason: - [...failures, ...(truncated ? ["max_records_reached"] : [])].join("; ") || - null, + status: classReasons.length > 0 ? "partial" : "complete", + reason: classReasons.join("; ") || null, examined, - decoded: result.objc_classes.length, + decoded: result.objc_classes.filter( + ({ decode }) => decode?.status === "decoded", + ).length, }); result.coverage.push({ facet: "binary_relative_pointers", @@ -79,13 +127,18 @@ export const pushDispatchCoverage = (input: { status: truncated || categoryFailures.length > 0 || - result.objc_categories.some(({ decode }) => decode.status !== "decoded") + result.objc_categories.some( + ({ decode }) => decode.status !== "decoded", + ) || + categoryMethodReasons.length > 0 ? "partial" : "complete", reason: - [...categoryFailures, ...(truncated ? ["max_records_reached"] : [])].join( - "; ", - ) || null, + [ + ...categoryFailures, + ...categoryMethodReasons, + ...(truncated ? ["max_records_reached"] : []), + ].join("; ") || null, examined: categoriesExamined, decoded: result.objc_categories.filter( ({ decode }) => decode.status === "decoded", @@ -110,7 +163,7 @@ export const pushDispatchCoverage = (input: { : "complete", reason: fixupReason.length > 0 ? fixupReason : null, examined: fixups.examined, - decoded: fixups.issues.length > 0 ? 0 : fixups.examined, + decoded: fixups.decoded, }); result.coverage.push({ facet: "swift_generic_resilient_witnesses_overrides_async_coroutines", diff --git a/src/native/AppleDispatchMetadata.test.ts b/src/native/AppleDispatchMetadata.test.ts index 6791ba1b0..244a35aeb 100644 --- a/src/native/AppleDispatchMetadata.test.ts +++ b/src/native/AppleDispatchMetadata.test.ts @@ -2,7 +2,10 @@ import { describe, expect, it } from "vitest"; import { decodeAppleDispatchMetadata } from "./AppleDispatchMetadata.js"; const base = 0x100000000n; -const fixture = (relative = false) => { +const fixture = ( + relative = false, + category?: "partial-method" | "unmapped-pointer", +) => { const bytes = Buffer.alloc(4096); const u32 = (offset: number, value: number) => bytes.writeUInt32LE(value, offset); @@ -11,19 +14,26 @@ const fixture = (relative = false) => { u32(0, 0xfeedfacf); u32(4, 0x0100000c); u32(16, 1); - u32(20, 152); + u32(20, category === undefined ? 152 : 232); u32(32, 0x19); - u32(36, 152); + u32(36, category === undefined ? 152 : 232); bytes.write("__DATA", 40); ptr(56, 0); bytes.writeBigUInt64LE(4096n, 64); bytes.writeBigUInt64LE(4096n, 80); u32(92, 5); - u32(96, 1); + u32(96, category === undefined ? 1 : 2); bytes.write("__objc_classlist", 104); bytes.write("__DATA", 120); ptr(136, 0x180); bytes.writeBigUInt64LE(8n, 144); + if (category !== undefined) { + bytes.write("__objc_catlist", 184); + bytes.write("__DATA", 200); + ptr(216, 0xb00); + bytes.writeBigUInt64LE(8n, 224); + u32(232, 0xb00); + } u32(152, 0x180); ptr(0x180, 0x200); ptr(0x200, 0x280); @@ -86,10 +96,58 @@ const fixture = (relative = false) => { bytes.write("FixtureProtocol\0", 0x900); bytes.write("requiredAction:\0", 0x920); bytes.write("optionalAction:\0", 0x940); + if (category !== undefined) { + if (category === "unmapped-pointer") { + bytes.writeBigUInt64LE(0xffffffffffffffffn, 0xb00); + } else { + ptr(0xb00, 0xb40); + ptr(0xb40, 0xbc0); + ptr(0xb48, 0x200); + ptr(0xb50, 0xb80); + u32(0xb80, 24); + u32(0xb84, 1); + ptr(0xb88, 0x460); + ptr(0xb90, 0x5c0); + bytes.writeBigUInt64LE(0xffffffffffffffffn, 0xb98); + bytes.write("FixtureCategory\0", 0xbc0); + } + } return bytes; }; const provenance = { path: "/fixture/app", sha256: "a".repeat(64) }; -describe("chained Apple dispatch binary metadata", () => { +describe("Apple dispatch pointer fixup metadata", () => { + it("keeps decoded bindings and their coverage when an independent stream fails", () => { + const bytes = fixture(); + bytes.writeUInt32LE(2, 16); + bytes.writeUInt32LE(200, 20); + bytes.writeUInt32LE(0x80000022, 184); + bytes.writeUInt32LE(48, 188); + const bindings = Buffer.from([ + 0x40, + ...Buffer.from("_OBJC_CLASS_$_NSObject\0"), + 0x70, + 0x88, + 0x04, + 0x90, + 0x00, + ]); + bindings.copy(bytes, 0xc00); + bytes[0xc80] = 0xd0; + bytes.writeUInt32LE(0xc00, 200); + bytes.writeUInt32LE(bindings.length, 204); + bytes.writeUInt32LE(0xc80, 208); + bytes.writeUInt32LE(1, 212); + + const result = decodeAppleDispatchMetadata(bytes, 100, provenance); + expect(result.objc_classes[0]).toMatchObject({ + name: "Fixture", + super_class: "NSObject", + }); + expect( + result.coverage.find(({ facet }) => facet === "pointer_fixups"), + ).toMatchObject({ status: "partial", examined: 2, decoded: 1 }); + }); + it("keeps absolute metadata pointers between declared chained fixups", () => { const bytes = fixture(); bytes.writeUInt32LE(2, 16); @@ -120,7 +178,7 @@ describe("chained Apple dispatch binary metadata", () => { }); expect( result.coverage.find(({ facet }) => facet === "pointer_fixups"), - ).toMatchObject({ status: "complete" }); + ).toMatchObject({ status: "complete", examined: 1, decoded: 1 }); }); }); describe("Apple dispatch binary metadata", () => { @@ -221,6 +279,9 @@ describe("Apple dispatch binary metadata", () => { }); }, ); +}); + +describe("Apple dispatch coverage ownership", () => { it("keeps unsupported pointers and record truncation explicit", () => { const bytes = fixture(); bytes.writeBigUInt64LE(0xffffffffffffffffn, 0x498); @@ -229,6 +290,14 @@ describe("Apple dispatch binary metadata", () => { implementation_address: null, decode: { status: "partial" }, }); + expect( + result.coverage.find( + ({ facet }) => facet === "objc_class_method_ivar_metadata", + ), + ).toMatchObject({ + status: "partial", + reason: expect.stringContaining("method Fixture instance performAction:"), + }); const truncated = decodeAppleDispatchMetadata(fixture(), 1, provenance); expect(truncated.coverage[0]?.reason).toContain("max_records_reached"); expect( @@ -237,6 +306,67 @@ describe("Apple dispatch binary metadata", () => { ), ).toMatchObject({ status: "partial", reason: "max_records_reached" }); }); + it("keeps partial category methods in category coverage only", () => { + const baseline = decodeAppleDispatchMetadata(fixture(), 100, provenance); + const result = decodeAppleDispatchMetadata( + fixture(false, "partial-method"), + 100, + provenance, + ); + + expect(result.objc_dispatch_implementations).toContainEqual( + expect.objectContaining({ + category: "FixtureCategory", + decode: { + status: "partial", + reason: "implementation_pointer_unmapped_or_encoded", + }, + }), + ); + const baselineClassCoverage = baseline.coverage.find( + ({ facet }) => facet === "objc_class_method_ivar_metadata", + ); + const classCoverage = result.coverage.find( + ({ facet }) => facet === "objc_class_method_ivar_metadata", + ); + expect(baselineClassCoverage).toBeDefined(); + expect(classCoverage).toEqual(baselineClassCoverage); + expect( + result.coverage.find( + ({ facet }) => facet === "objc_properties_categories", + ), + ).toMatchObject({ + status: "partial", + reason: expect.stringContaining("category method FixtureCategory"), + }); + }); + it("keeps malformed category pointers out of class failure coverage", () => { + const baseline = decodeAppleDispatchMetadata(fixture(), 100, provenance); + const result = decodeAppleDispatchMetadata( + fixture(false, "unmapped-pointer"), + 100, + provenance, + ); + const baselineClassCoverage = baseline.coverage.find( + ({ facet }) => facet === "objc_class_method_ivar_metadata", + ); + const classCoverage = result.coverage.find( + ({ facet }) => facet === "objc_class_method_ivar_metadata", + ); + expect(baselineClassCoverage).toBeDefined(); + expect(classCoverage).toEqual(baselineClassCoverage); + expect( + result.coverage.find( + ({ facet }) => facet === "objc_properties_categories", + ), + ).toMatchObject({ + status: "partial", + reason: expect.stringContaining("category_decode_failed"), + }); + }); +}); + +describe("malformed Apple dispatch metadata", () => { it("rejects malformed command and section boundaries", () => { const bytes = fixture(); bytes.writeUInt32LE(7, 36); diff --git a/src/native/AppleMachoFixups.test.ts b/src/native/AppleMachoFixups.test.ts index 40c50c59b..bf4ae348f 100644 --- a/src/native/AppleMachoFixups.test.ts +++ b/src/native/AppleMachoFixups.test.ts @@ -149,6 +149,64 @@ const SEGMENTS: Segment[] = [ { address: BASE + 0x4000n, size: 0x4000n, offset: 0x4000, executable: false }, ]; +describe("independent chained segment coverage", () => { + it("counts successfully decoded chained segments alongside an unsupported segment", () => { + const starts = 28; + const startsSize = 4 + 2 * 4; + const firstInfo = starts + startsSize; + const secondInfo = firstInfo + 24; + const imports = secondInfo + 24; + const data = Buffer.alloc(0x3000); + data.writeUInt32LE(starts, 4); + data.writeUInt32LE(imports, 8); + data.writeUInt32LE(imports, 12); + data.writeUInt32LE(1, 20); + data.writeUInt32LE(2, starts); + data.writeUInt32LE(firstInfo - starts, starts + 4); + data.writeUInt32LE(secondInfo - starts, starts + 8); + for (const [info, format, segmentOffset] of [ + [firstInfo, 6, 0], + [secondInfo, 99, 0x1000], + ] as const) { + data.writeUInt32LE(24, info); + data.writeUInt16LE(0x1000, info + 4); + data.writeUInt16LE(format, info + 6); + data.writeBigUInt64LE(BigInt(segmentOffset), info + 8); + data.writeUInt16LE(1, info + 20); + data.writeUInt16LE(8, info + 22); + } + const segments: Segment[] = [ + { address: BASE, size: 0x1000n, offset: 0x1000, executable: false }, + { + address: BASE + 0x1000n, + size: 0x1000n, + offset: 0x2000, + executable: false, + }, + ]; + const fixups = parsePointerFixups( + data, + { + chained: { offset: 0, size: imports }, + binds: [], + rebases: [], + dylibs: [], + }, + segments, + BASE, + ); + + expect(fixups).toMatchObject({ examined: 2, decoded: 1 }); + expect(fixups.issues).toMatchObject([ + { code: "unsupported_pointer_format" }, + ]); + expect(fixups.decode(BASE + 8n, 0n)).toEqual({ + kind: "rebase", + target: BASE, + }); + }); +}); + describe("pointer fixup tables", () => { it("reports unsupported pointer formats even when no pointer is visited", () => { const data = chainedData(1); @@ -196,20 +254,27 @@ describe("pointer fixup tables", () => { { chained: { offset: 0, size: 128 }, binds: [], - rebases: [], + rebases: [{ offset: 8, size: 12 }], dylibs: [], }, SEGMENTS, BASE, ); + expect(fixups).toMatchObject({ + examined: 1, + decoded: 1, + unreadRebaseBytes: 12, + }); expect(fixups.decode(BASE + 0x4008n, field(1n, 63))).toMatchObject({ kind: "bind", symbol: "_OBJC_CLASS_$_NSObject", }); expect(fixups.issues).toEqual([]); + expect(fixups.decoded).toBe(1); expect(fixups.decode(BASE + 0x4008n, 1n | field(1n, 63))).toMatchObject({ kind: "unsupported", }); + expect(fixups.decoded).toBe(0); expect(fixups.issues).toMatchObject([ { code: "chained_pointer_decode_failed" }, ]); diff --git a/src/native/AppleMachoFixups.ts b/src/native/AppleMachoFixups.ts index 2ec711cc8..09080ec1d 100644 --- a/src/native/AppleMachoFixups.ts +++ b/src/native/AppleMachoFixups.ts @@ -42,6 +42,8 @@ export interface PointerFixups { readonly issues: readonly DecodeIssue[]; /** Fixup segments or bind streams this reader walked. */ readonly examined: number; + /** Fully decoded fixup segments or bind streams, in the same units as `examined`. */ + readonly decoded: number; /** Rebase opcode bytes present in the load command and not decoded. */ readonly unreadRebaseBytes: number; /** Decode the pointer stored at `address` whose raw 64-bit value is `raw`. */ @@ -260,6 +262,7 @@ const readChainedPage = ( const chainedFixups = ( image: FixupImage, range: { readonly offset: number; readonly size: number }, + unreadRebaseBytes: number, ): PointerFixups => { const { bytes, segments, dylibs, baseAddress } = image; const base = range.offset; @@ -400,19 +403,25 @@ const chainedFixups = ( ] : [], ); - const examinedViews = new Set(); - for (const chain of ranges) { + const examinedViews = new Map(); + const decodedRanges = new Set(); + for (const [chainIndex, chain] of ranges.entries()) { // Unknown formats retain their compact starts table; only a queried page // needs its NONE/presence value. Do not expand unsupported declarations. if (POINTER_FORMATS[chain.format] === undefined) continue; - const view = `${chain.pageStarts}:${chain.segment.offset}:${chain.segment.size}:${chain.segment.address}`; - if (examinedViews.has(view)) continue; - examinedViews.add(view); + const view = `${chain.pageStarts}:${chain.segment.offset}:${chain.segment.size}:${chain.segment.address}:${chain.format}:${chain.pageSize}:${chain.pageCount}`; + const prior = examinedViews.get(view); + if (prior !== undefined) { + if (prior) decodedRanges.add(chainIndex); + continue; + } + let complete = true; for (let page = 0; page < chain.pageCount; page++) { const start = bytes.readUInt16LE(chain.pageStarts + page * 2); if (start === 0xffff) continue; const facts = pageFacts(chain, page, start); if (facts.failure !== undefined) { + complete = false; issues.push( issue( "pointer_fixups", @@ -427,6 +436,8 @@ const chainedFixups = ( break; } } + examinedViews.set(view, complete); + if (complete) decodedRanges.add(chainIndex); } const failures = issues.map(({ message }) => message); return { @@ -435,13 +446,17 @@ const chainedFixups = ( failures, issues, examined: Math.max(ranges.length, 1), - unreadRebaseBytes: 0, + get decoded() { + return ranges.length === 0 ? 1 : decodedRanges.size; + }, + unreadRebaseBytes, decode(address, raw) { - const chain = ranges.find( + const chainIndex = ranges.findIndex( ({ segment }) => address >= segment.address && address < segment.address + segment.size, ); + const chain = ranges[chainIndex]; // Pointers outside fixup segments, such as in __TEXT, are stored plainly. if (chain === undefined) return { kind: "rebase", target: raw }; const within = Number(address - chain.segment.address); @@ -486,6 +501,7 @@ const chainedFixups = ( ); failures.push(reason); } + decodedRanges.delete(chainIndex); return { kind: "unsupported", reason }; } }, @@ -684,10 +700,7 @@ export const parsePointerFixups = ( 0, ); if (commands.chained !== null) { - const chained = chainedFixups(image, commands.chained); - return unreadRebaseBytes === 0 - ? chained - : { ...chained, unreadRebaseBytes }; + return chainedFixups(image, commands.chained, unreadRebaseBytes); } if (commands.binds.length === 0) return { @@ -696,14 +709,17 @@ export const parsePointerFixups = ( failures: [], issues: [], examined: 0, + decoded: 0, unreadRebaseBytes, decode: (_address, raw) => ({ kind: "rebase", target: raw }), }; const binds: BindRun[] = []; const failures: string[] = []; + let decoded = 0; for (const stream of commands.binds) try { readBindStream(image, stream, binds); + decoded++; } catch (cause: unknown) { failures.push( `${stream.stream} bind opcodes: ${cause instanceof Error ? cause.message : String(cause)}`, @@ -717,6 +733,7 @@ export const parsePointerFixups = ( issue("pointer_fixups", "bind_stream_decode_failed", message), ), examined: commands.binds.length, + decoded, unreadRebaseBytes, decode(address, raw) { let match: BindRun | undefined; diff --git a/src/native/AppleMachoSelection.test.ts b/src/native/AppleMachoSelection.test.ts index 5c19026e0..af2d0be55 100644 --- a/src/native/AppleMachoSelection.test.ts +++ b/src/native/AppleMachoSelection.test.ts @@ -7,9 +7,13 @@ import { fatImage, machoImage, } from "../artifacts/apple/MachoImage.fixture.js"; -import { parseMachoLayout } from "./AppleMachoSelection.js"; +import { parseMachoLayout, selectMachoSlice } from "./AppleMachoSelection.js"; import { decodeAppleDispatchMetadata } from "./AppleDispatchMetadata.js"; +/** macOS 27 system binaries ship CPU_SUBTYPE_ARM64E_X1 (12) with the PAC ABI bit. */ +const ARM64E_X1 = { type: 0x0100000c, subtype: 0x8000000c } as const; +const X86_64H = { type: 0x01000007, subtype: 8 } as const; + describe("native Mach-O slice selection", () => { it("preserves high-bit section-name bytes instead of ASCII-folding metadata names", () => { const segment = Buffer.alloc(152); @@ -68,6 +72,48 @@ describe("native Mach-O slice selection", () => { /not aligned/u, ); }); + + it.each([ + { layout: "arm64e, arm64e.x1", cpus: [CPU.arm64e, ARM64E_X1], index: 0 }, + { layout: "arm64e.x1, arm64e", cpus: [ARM64E_X1, CPU.arm64e], index: 1 }, + { layout: "arm64, arm64e.x1", cpus: [CPU.arm64, ARM64E_X1], index: 0 }, + { layout: "arm64e.x1, arm64", cpus: [ARM64E_X1, CPU.arm64], index: 1 }, + { + layout: "x86_64, arm64e, arm64e.x1", + cpus: [CPU.x86_64, CPU.arm64e, ARM64E_X1], + index: 1, + }, + { + layout: "x86_64h, x86_64", + cpus: [X86_64H, CPU.x86_64], + index: 1, + architecture: "x86_64", + }, + ])( + "selects one slice when FAT slices $layout share a CPU type", + ({ cpus, index, architecture = "arm64" }) => { + const fat = Buffer.from( + fatImage(cpus.map((cpu) => ({ cpu, bytes: machoImage({ cpu }) }))), + ); + expect(selectMachoSlice(fat, architecture).fatDeclaration).toMatchObject({ + index, + cpuSubtype: cpus[index]?.subtype, + }); + expect(parseMachoLayout(fat, architecture).segments).toEqual([]); + }, + ); + + it("rejects slices of the requested CPU type that share a subtype", () => { + const fat = fatImage( + [CPU.arm64e, CPU.arm64e].map((cpu) => ({ + cpu, + bytes: machoImage({ cpu }), + })), + ); + expect(() => parseMachoLayout(Buffer.from(fat), "arm64")).toThrow( + /Ambiguous FAT architecture slice/u, + ); + }); }); describe("native Mach-O fixup load command boundaries", () => { diff --git a/src/native/AppleMachoSelection.ts b/src/native/AppleMachoSelection.ts index 9ee93f995..c0c68068d 100644 --- a/src/native/AppleMachoSelection.ts +++ b/src/native/AppleMachoSelection.ts @@ -1,7 +1,13 @@ import type { FixupCommands } from "./AppleMachoFixups.js"; +import { + MACHO_ARCHITECTURE_POLICIES, + machoSubtypeRank, +} from "./MachoArchitectureSelection.js"; +import { machoCpuSubtypeBase } from "../domain/apple/machoCpuIdentity.js"; import { readFatSliceDeclarations, validateFatSlice, + type FatSliceDeclaration, } from "../domain/apple/machoContainer.js"; /** One mapped Mach-O segment with file-backed VA range. */ @@ -90,32 +96,44 @@ export const selectMachoSlice = ( const headerEnd = 8 + count * stride; if (count > 128 || headerEnd > bytes.length) throw malformed("Malformed FAT architecture table"); - const cpu = MACHO_CPU_TYPE[architecture]; - if (cpu === undefined) throw invalid("Requested FAT architecture is absent"); + const policy = MACHO_ARCHITECTURE_POLICIES[architecture]; + if (policy === undefined) + throw invalid("Requested FAT architecture is absent"); const declarations = readFatSliceDeclarations(bytes.subarray(8, headerEnd), { count, wide: fat64, littleEndian, }); if (declarations.status !== "parsed") throw malformed(declarations.reason); - let selected: MachoSlice | undefined; + let best: FatSliceDeclaration | undefined; + let bestRank = Number.POSITIVE_INFINITY; + let ambiguous = false; for (const declaration of declarations.slices) { const issue = validateFatSlice(declaration, bytes.length, headerEnd); if (issue !== null) throw malformed(issue); - if (declaration.cpuType !== cpu) continue; - if (selected !== undefined) - throw invalid("Ambiguous FAT architecture slice"); - selected = { - slice: declaration.offset, - sliceEnd: declaration.offset + declaration.size, - fatDeclaration: { - ...declaration, - tableEnd: headerEnd, - }, - }; + if (declaration.cpuType !== policy.cpuType) continue; + const rank = machoSubtypeRank(policy, declaration.cpuSubtype); + if (best !== undefined && rank >= bestRank) { + // Equal ranks keep FAT table order unless the slices share a subtype. + if ( + rank === bestRank && + machoCpuSubtypeBase(declaration.cpuSubtype) === + machoCpuSubtypeBase(best.cpuSubtype) + ) + ambiguous = true; + continue; + } + best = declaration; + bestRank = rank; + ambiguous = false; } - if (selected === undefined) - throw invalid("Requested FAT architecture is absent"); + if (best === undefined) throw invalid("Requested FAT architecture is absent"); + if (ambiguous) throw invalid("Ambiguous FAT architecture slice"); + const selected: MachoSlice = { + slice: best.offset, + sliceEnd: best.offset + best.size, + fatDeclaration: { ...best, tableEnd: headerEnd }, + }; if (selected.slice + 4 > bytes.length) throw malformed("Truncated Mach-O header"); const sliceMagic = bytes.readUInt32LE(selected.slice); @@ -126,13 +144,6 @@ export const selectMachoSlice = ( return selected; }; -/** CPU types admitted by `machArchitecture` in the domain binary target parser. */ -const MACHO_CPU_TYPE: Readonly> = { - x86: 7, - x86_64: 0x01000007, - arm: 12, - arm64: 0x0100000c, -}; const MH_MAGIC = 0xfeedface; const MH_CIGAM = 0xcefaedfe; diff --git a/src/native/AppleObjcCategories.ts b/src/native/AppleObjcCategories.ts index bd936e0ce..7beb7fc03 100644 --- a/src/native/AppleObjcCategories.ts +++ b/src/native/AppleObjcCategories.ts @@ -23,7 +23,6 @@ export const decodeObjcCategories = (input: { readonly sections: readonly Section[]; readonly read: ObjcDispatchReaders; readonly result: ObjcSwiftMetadata; - readonly failures: string[]; readonly issues: DecodeIssue[]; readonly admit: () => boolean; /** Decode a method list into implementations attributed to the category. */ @@ -37,7 +36,7 @@ export const decodeObjcCategories = (input: { /** Name of a class defined in this image, from its class_ro_t. */ readonly localClassName: (address: bigint) => string; }): number => { - const { read, result, failures } = input; + const { read, result } = input; let examined = 0; for (const section of input.sections.filter( ({ name }) => name === "__objc_catlist", @@ -93,7 +92,6 @@ export const decodeObjcCategories = (input: { }); } catch (cause: unknown) { const message = cause instanceof Error ? cause.message : String(cause); - failures.push(`Category at 0x${field.toString(16)}: ${message}`); input.issues.push( issue( "objc_properties_categories", diff --git a/src/native/AppleObjcDispatchFacets.ts b/src/native/AppleObjcDispatchFacets.ts index 14f0b42b8..b52545840 100644 --- a/src/native/AppleObjcDispatchFacets.ts +++ b/src/native/AppleObjcDispatchFacets.ts @@ -335,7 +335,6 @@ export const decodeObjcDispatchFacets = (input: { sections, read, result, - failures, issues: categoryIssues, admit: () => budget.admit(), methods, diff --git a/src/native/AppleSwiftVtables.test.ts b/src/native/AppleSwiftVtables.test.ts index dbb1c12b5..fb1615820 100644 --- a/src/native/AppleSwiftVtables.test.ts +++ b/src/native/AppleSwiftVtables.test.ts @@ -67,6 +67,7 @@ describe("Swift vtable coverage facts: unresolved Swift dispatch slots", () => { issues: [], decode: (_address, raw) => ({ kind: "rebase", target: raw }), examined: 0, + decoded: 0, unreadRebaseBytes: 0, }, swift: { @@ -181,6 +182,7 @@ describe("Swift vtable coverage facts: unsupported pointer fixup coverage", () = reason: "Unsupported chained pointer format 99", }), examined: 0, + decoded: 0, unreadRebaseBytes: 0, }, swift: { diff --git a/src/native/CommandRunner.ts b/src/native/CommandRunner.ts index e9775d1b7..ccd49c570 100644 --- a/src/native/CommandRunner.ts +++ b/src/native/CommandRunner.ts @@ -4,6 +4,7 @@ import { createReadStream } from "node:fs"; import { realpath } from "node:fs/promises"; import { err, ok, type Result } from "../domain/result.js"; +import { DarwinProcessOwnershipInspectionError } from "../process/DarwinProcessRunTokenReader.js"; import { OwnedCommandFailure, runOwnedCommand, @@ -39,6 +40,7 @@ export interface NativeCommandCapture { export class NativeCommandFailure extends Error { readonly cleanupOwner: ProviderProcessSupervisor | undefined; readonly cleanupFailures: readonly NativeCommandCleanupFailure[]; + readonly detail: string | null; constructor( readonly tool: string, @@ -58,6 +60,7 @@ export class NativeCommandFailure extends Error { super(`Native command ${tool} failed: ${reason}`, options); this.cleanupOwner = options?.cleanupOwner; this.cleanupFailures = options?.cleanupFailures ?? []; + this.detail = options?.detail ?? null; } } @@ -67,6 +70,8 @@ export interface NativeCommandFailureOptions extends ErrorOptions { readonly cleanupOwner?: ProviderProcessSupervisor; /** All owners still incomplete after a preflight retry blocked this command. */ readonly cleanupFailures?: readonly NativeCommandCleanupFailure[]; + /** Host-side reason the command could not be supervised, such as a missing ownership helper compiler. */ + readonly detail?: string; } /** One failed cleanup attempt; the runner retains `owner` until it is verified stopped. */ @@ -310,6 +315,9 @@ export const resolveXcrunTool = async ( ...(found.error.cleanupFailures.length === 0 ? {} : { cleanupFailures: found.error.cleanupFailures }), + ...(found.error.detail === null + ? {} + : { detail: found.error.detail }), }, found.error.capture, found.error.cleanupFailure, @@ -449,7 +457,16 @@ const captureProcess = async ( ), ); } - return err(new NativeCommandFailure(tool, "io", null, { cause })); + return err( + new NativeCommandFailure(tool, "io", null, { + cause, + // Process supervision needs the Darwin ownership helper; its typed + // message names the compiler or SDK prerequisite to fix. + ...(cause instanceof DarwinProcessOwnershipInspectionError + ? { detail: cause.message } + : {}), + }), + ); } }; diff --git a/src/native/MachoArchitectureSelection.ts b/src/native/MachoArchitectureSelection.ts new file mode 100644 index 000000000..14c5f696f --- /dev/null +++ b/src/native/MachoArchitectureSelection.ts @@ -0,0 +1,80 @@ +import { machoCpuSubtypeBase } from "../domain/apple/machoCpuIdentity.js"; +import type { LipoArchitecture } from "./parsers/lipo.js"; + +interface MachoArchitecturePolicy { + readonly cpuType: number; + readonly subtypes: readonly { + readonly subtype: number; + readonly name: string; + }[]; + readonly variantName?: RegExp; +} + +/** One preference order for FAT subtype identities and Apple tool slice names. */ +export const MACHO_ARCHITECTURE_POLICIES: Readonly< + Record +> = { + x86: { cpuType: 7, subtypes: [{ subtype: 3, name: "i386" }] }, + x86_64: { + cpuType: 0x01000007, + subtypes: [{ subtype: 3, name: "x86_64" }], + }, + arm: { cpuType: 12, subtypes: [], variantName: /^arm$/u }, + arm64: { + cpuType: 0x0100000c, + subtypes: [ + { subtype: 0, name: "arm64" }, + { subtype: 2, name: "arm64e" }, + { subtype: 1, name: "arm64v8" }, + ], + variantName: /^arm64e\.[A-Za-z0-9_]+$/u, + }, +}; + +/** Unlisted subtypes follow the preferred slices in FAT table order. */ +export const machoSubtypeRank = ( + policy: MachoArchitecturePolicy, + subtype: number, +): number => { + const rank = policy.subtypes.findIndex( + (candidate) => candidate.subtype === machoCpuSubtypeBase(subtype), + ); + return rank < 0 ? policy.subtypes.length : rank; +}; + +/** Select a tool spelling using the same preference order as FAT selection. */ +export const selectMachoArchitectureName = ( + policy: MachoArchitecturePolicy, + available: readonly LipoArchitecture[], +): string | undefined => { + let selected: string | undefined; + let bestRank = Number.POSITIVE_INFINITY; + for (const architecture of available) { + if ( + architecture.cpu_type_code !== null && + architecture.cpu_type_code !== policy.cpuType + ) + continue; + const namedSubtype = policy.subtypes.find( + ({ name }) => name === architecture.name, + ); + const recognizedName = + namedSubtype !== undefined || policy.variantName?.test(architecture.name); + if ( + !recognizedName && + (architecture.cpu_type_code === null || + architecture.cpu_subtype_base === null) + ) + continue; + // Parsed identity is authoritative. Names support thin/partial lipo records. + const subtype = architecture.cpu_subtype_base ?? namedSubtype?.subtype; + const rank = + subtype === undefined + ? policy.subtypes.length + : machoSubtypeRank(policy, subtype); + if (rank >= bestRank) continue; + selected = architecture.name; + bestRank = rank; + } + return selected; +}; diff --git a/src/native/NativeMacOSProvider.ts b/src/native/NativeMacOSProvider.ts index 1d1c2a36c..a59ec90a7 100644 --- a/src/native/NativeMacOSProvider.ts +++ b/src/native/NativeMacOSProvider.ts @@ -966,6 +966,7 @@ const translateCommandFailure = ( signal: failure.capture?.signal ?? null, stdout_bytes: failure.capture?.stdoutBytes ?? 0, stderr_bytes: failure.capture?.stderrBytes ?? 0, + ...(failure.detail === null ? {} : { detail: failure.detail }), }, }); }; diff --git a/src/native/NativeMachoInspection.test.ts b/src/native/NativeMachoInspection.test.ts index 4ed533c2e..640e540be 100644 --- a/src/native/NativeMachoInspection.test.ts +++ b/src/native/NativeMachoInspection.test.ts @@ -1,7 +1,18 @@ import { describe, expect, it } from "vitest"; -import { AnalysisCancelledError } from "../domain/analysisErrorCore.js"; +import { + CPU, + LC, + dylibCommand, + fatImage, + machoImage, +} from "../artifacts/apple/MachoImage.fixture.js"; +import { + AnalysisCancelledError, + AnalysisOutputError, +} from "../domain/analysisErrorCore.js"; import { err, ok } from "../domain/result.js"; +import { parseMachoLayout, selectMachoSlice } from "./AppleMachoSelection.js"; import type { NativeCommandCapture } from "./CommandRunner.js"; import { inspectNativeMacho } from "./NativeMachoInspection.js"; import { @@ -75,6 +86,62 @@ describe("Mach-O tool architecture selection", () => { "/fixture/app", ]); }); + + it.each([ + { names: ["arm64v8", "arm64e"], selected: "arm64e" }, + { names: ["arm64e", "arm64v8"], selected: "arm64e" }, + { names: ["arm64v8", "arm64e", "arm64"], selected: "arm64" }, + { names: ["arm64v8"], selected: "arm64v8" }, + { names: ["arm64v8", "arm64e.x1"], selected: "arm64v8" }, + { names: ["arm64e.x1", "arm64v8"], selected: "arm64v8" }, + { names: ["arm64v8", "arm64e.v1"], selected: "arm64e.v1" }, + { names: ["arm64e.v1", "arm64v8"], selected: "arm64e.v1" }, + ] as const)( + "keeps inspection and dispatch on $selected for FAT order $names", + async ({ names, selected }) => { + const cpus = { + arm64: CPU.arm64, + arm64v8: { type: CPU.arm64.type, subtype: 1 }, + arm64e: CPU.arm64e, + "arm64e.x1": { type: CPU.arm64.type, subtype: 0x8000000c }, + "arm64e.v1": { type: CPU.arm64.type, subtype: 0x81000002 }, + }; + const slices = names.map((name) => { + const cpu = cpus[name]; + return { + cpu, + bytes: machoImage({ + cpu, + commands: [dylibCommand(LC.LOAD_DYLIB, `/fixture/${name}.dylib`)], + }), + }; + }); + const fat = Buffer.from(fatImage(slices)); + const lipo = names + .map( + (name, index) => + `architecture ${name}\n cputype ${cpus[name].type}\n cpusubtype ${cpus[name].subtype}\n offset ${(index + 1) * 4096}\n size ${slices[index]?.bytes.length}\n align 2^12\n`, + ) + .join(""); + const { commands } = await inspect(lipo, "arm64"); + expect(commands.find(({ tool }) => tool === "otool")?.args).toEqual([ + "-h", + "-l", + "-arch", + selected.split(".")[0], + "/fixture/app", + ]); + expect(commands.find(({ tool }) => tool === "dyld_info")?.args).toContain( + selected, + ); + expect(selectMachoSlice(fat, "arm64").slice).toBe( + (names.findIndex((name) => name === selected) + 1) * 4096, + ); + expect(parseMachoLayout(fat, "arm64").fixups.dylibs).toEqual([ + `/fixture/${selected}.dylib`, + ]); + }, + ); }); describe("Mach-O UUID reconciliation", () => { @@ -186,3 +253,64 @@ describe("Mach-O UUID reconciliation", () => { ); }); }); + +describe("Mach-O slice command scheduling", () => { + const SLICE_TOOLS = ["otool", "nm", "dyld_info", "dyld_info", "dwarfdump"]; + + /** Finish later-launched slice commands first and record overlap. */ + const reorderingRunner = (failing: ReadonlySet = new Set()) => { + const fixtures = new NativeFixtureRunner(); + let inFlight = 0; + let maxInFlight = 0; + let launched = 0; + const run = async (tool: string, args: readonly string[]) => { + if (tool === "file" || tool === "lipo") return fixtures.run(tool, args); + const order = launched++; + inFlight += 1; + maxInFlight = Math.max(maxInFlight, inFlight); + for (let turn = 0; turn < 12 - order * 2; turn += 1) + await new Promise((resolve) => setImmediate(resolve)); + inFlight -= 1; + if (failing.has(tool)) + return err(new AnalysisOutputError("inspect_macho", `${tool} failed`)); + return fixtures.run(tool, args); + }; + return { run, maxInFlight: () => maxInFlight }; + }; + + const inspectWith = (run: ReturnType["run"]) => + inspectNativeMacho({ + target: nativeMachoTarget("/fixture/app"), + run, + invocation: (capture) => ({ + tool: capture.tool, + command: [capture.executable, ...capture.arguments], + tool_version: capture.toolVersion, + version_reason: capture.versionReason, + executable_sha256: capture.executableSha256, + exit: { code: capture.exitCode, signal: capture.signal }, + stdout_bytes: capture.stdoutBytes, + stderr_bytes: capture.stderrBytes, + }), + }); + + it("runs independent slice commands together and keeps provenance in declared order", async () => { + const runner = reorderingRunner(); + const result = await inspectWith(runner.run); + if (!result.ok) throw result.error; + expect(runner.maxInFlight()).toBe(SLICE_TOOLS.length + 1); + expect(result.value.result).toMatchObject({ + provenance: ["file", "lipo", ...SLICE_TOOLS, "vtool"].map((tool) => ({ + tool, + })), + }); + }); + + it("reports the first failing slice command in declared order", async () => { + const runner = reorderingRunner(new Set(["nm", "dwarfdump"])); + const result = await inspectWith(runner.run); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error).toMatchObject({ reason: "nm failed" }); + }); +}); diff --git a/src/native/NativeMachoInspection.ts b/src/native/NativeMachoInspection.ts index 2ec6cd4a9..5fca089cb 100644 --- a/src/native/NativeMachoInspection.ts +++ b/src/native/NativeMachoInspection.ts @@ -9,8 +9,15 @@ import { import { jsonValueSchema, type JsonValue } from "../domain/jsonValue.js"; import { err, ok, type Result } from "../domain/result.js"; import type { NativeCommandCapture } from "./CommandRunner.js"; +import { + MACHO_ARCHITECTURE_POLICIES, + selectMachoArchitectureName, +} from "./MachoArchitectureSelection.js"; import { parseDyldSymbols } from "./parsers/dyldInfo.js"; -import { parseLipoArchitectures } from "./parsers/lipo.js"; +import { + parseLipoArchitectures, + type LipoArchitecture, +} from "./parsers/lipo.js"; import { withoutEchoedPathHeader } from "./parsers/echoedPath.js"; import { parseOtoolLoadCommands } from "./parsers/otool.js"; import { reconcileMachoUuid } from "./parsers/machoUuid.js"; @@ -68,8 +75,7 @@ export const inspectNativeMacho = async ( const lipo = captures.find(({ tool }) => tool === "lipo"); if (lipo === undefined) throw new TypeError("Missing lipo capture"); const architectures = parseLipoArchitectures(lipo.stdout); - const availableArchitectures = architectures.map(({ name }) => name); - const selection = selectArchitecture(context.target, availableArchitectures); + const selection = selectArchitecture(context.target, architectures); if (selection.status === "absent") return err( new AnalysisOutputError( @@ -79,8 +85,11 @@ export const inspectNativeMacho = async ( ); const selectedArchitecture = selection.status === "selected" ? selection.architecture : null; - for (const [tool, prefix] of REQUIRED_SLICE_COMMANDS) { - const captured = await context.run( + const runSliceCommand = ([tool, prefix]: readonly [ + string, + readonly string[], + ]) => + context.run( tool, [ ...prefix, @@ -89,20 +98,18 @@ export const inspectNativeMacho = async ( ], context.signal, ); + // Slice commands only read the selected artifact, so launch them together. + // Every launch settles before return; declared order fixes provenance and + // which failure is reported. + const [required, optional] = await Promise.all([ + Promise.all(REQUIRED_SLICE_COMMANDS.map(runSliceCommand)), + runSliceCommand(OPTIONAL_VTOOL_COMMAND), + ]); + for (const captured of required) { if (!captured.ok) return err(captured.error); captures.push(captured.value); } const limitations: string[] = []; - const [tool, prefix] = OPTIONAL_VTOOL_COMMAND; - const optional = await context.run( - tool, - [ - ...prefix, - ...selectedArchitectureArguments(tool, selectedArchitecture), - context.target.path, - ], - context.signal, - ); if (optional.ok) captures.push(optional.value); else if (optional.error._tag === "AnalysisCapabilityUnavailableError") limitations.push(VTOOL_UNAVAILABLE_LIMITATION); @@ -396,25 +403,24 @@ type ArchitectureSelection = const selectArchitecture = ( target: BinaryTarget, - available: readonly string[], + available: readonly LipoArchitecture[], ): ArchitectureSelection => { - if (target.kind !== "executable" || target.availableArchitectures.length < 2) + // BinaryTarget lists CPU families and lipo lists slices. A universal file + // can hold several slices of one family (arm64e and arm64e.x1), and slice + // tools without -arch print every slice. + if ( + target.kind !== "executable" || + (target.availableArchitectures.length < 2 && available.length < 2) + ) return { status: "unfiltered" }; const normalized = target.architecture === "x86" ? "i386" : target.architecture; - if (available.includes(normalized)) - return { status: "selected", architecture: normalized }; - // BinaryTarget intentionally normalizes ARM64 CPU subtypes. Recover the - // concrete arm64e slice name from lipo before invoking slice-aware tools. - if (normalized === "arm64") { - const arm64e = available.find((architecture) => architecture === "arm64e"); - if (arm64e !== undefined) - return { status: "selected", architecture: arm64e }; - const variant = available.find((architecture) => - /^arm64e\.[A-Za-z0-9_]+$/u.test(architecture), - ); - if (variant !== undefined) - return { status: "selected", architecture: variant }; - } + const policy = MACHO_ARCHITECTURE_POLICIES[target.architecture]; + const selected = + policy === undefined + ? available.find(({ name }) => name === normalized)?.name + : selectMachoArchitectureName(policy, available); + if (selected !== undefined) + return { status: "selected", architecture: selected }; return { status: "absent", architecture: normalized }; }; diff --git a/src/native/NativeUiObservation.test.ts b/src/native/NativeUiObservation.test.ts index d2238bd01..527afd8db 100644 --- a/src/native/NativeUiObservation.test.ts +++ b/src/native/NativeUiObservation.test.ts @@ -35,6 +35,37 @@ const validPng = Buffer.from( "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jv4sAAAAASUVORK5CYII=", "base64", ); +it.each([ + { offset: 8, value: 12 }, + { offset: 16, value: 0x8000_0000 }, + { offset: 20, value: 0x8000_0000 }, +])( + "rejects invalid IHDR metadata with a matching digest", + async ({ offset, value }) => { + const bytes = Buffer.from(validPng); + bytes.writeUInt32BE(value, offset); + const screenshot = { + mime_type: "image/png", + base64: bytes.toString("base64"), + sha256: createHash("sha256").update(bytes).digest("hex"), + width: bytes.readUInt32BE(16), + height: bytes.readUInt32BE(20), + }; + const result = await observeNativeUi( + target, + "observe_native_ui", + { ...scope, screenshot: true }, + { + environment: {}, + invoke: async () => ({ + ok: true, + result: { ...snapshot, screenshot }, + }), + }, + ); + expect(result.ok).toBe(false); + }, +); describe("native UI screenshot validation", () => { it("rejects malformed or mismatched screenshot bytes from the helper", async () => { const screenshot = { diff --git a/src/native/parsers/codesign.ts b/src/native/parsers/codesign.ts index 3a39a389e..74a472f33 100644 --- a/src/native/parsers/codesign.ts +++ b/src/native/parsers/codesign.ts @@ -16,14 +16,11 @@ export const parseCodeSignature = ( unsigned: boolean, executablePaths: readonly string[] = [], ): Omit => { - const { identifier, fields } = splitEchoedValues( - output.replaceAll("\r\n", "\n"), - executablePaths, - ); + const { identifier, fields } = splitEchoedValues(output, executablePaths); const values = new Map(); const authorities: string[] = []; const cdhashes: string[] = []; - for (const line of fields.split("\n")) { + for (const line of fields.split(/\r?\n/u)) { if (line.startsWith("CodeDirectory ")) { values.set("CodeDirectory", line.slice("CodeDirectory ".length)); continue; @@ -65,12 +62,20 @@ const splitEchoedValues = ( text: string, executablePaths: readonly string[], ): { readonly identifier: string | undefined; readonly fields: string } => { - const executable = executablePaths - .map((path) => `Executable=${path}\n`) - .find((line) => text.startsWith(line)); let rest = text; - if (executable !== undefined) rest = text.slice(executable.length); - else if (text.startsWith("Executable=")) { + // Frame the exact source path before interpreting record separators. A CRLF + // inside that path or the signing identifier is payload, not a line ending. + let newline: string | undefined; + for (const path of executablePaths) { + const prefix = `Executable=${path}`; + if (!text.startsWith(prefix)) continue; + const separator = /^\r?\n/u.exec(text.slice(prefix.length))?.[0]; + if (separator === undefined) continue; + newline = separator; + rest = text.slice(prefix.length + separator.length); + break; + } + if (rest === text && text.startsWith("Executable=")) { const identifierLine = text.indexOf("\nIdentifier="); rest = identifierLine < 0 ? text : text.slice(identifierLine + 1); } @@ -79,8 +84,17 @@ const splitEchoedValues = ( // Later fields come from the signature itself, so the last `Format=` line // is the one codesign printed after the identifier. const format = rest.lastIndexOf("\nFormat="); - const lineEnd = rest.indexOf("\n"); - const end = format >= 0 ? format : lineEnd >= 0 ? lineEnd : rest.length; + // Without an exact path, use the producer-owned Format record's terminator. + // Looking inside Identifier instead would confuse literal CRLF payload with + // record framing, or strip a literal trailing CR from an LF-delimited value. + if (newline === undefined && format >= 0) + newline = /\r?\n/u.exec(rest.slice(format + 1))?.[0]; + const boundary = format >= 0 ? format : rest.indexOf("\n"); + const crlf = newline === undefined || newline === "\r\n"; + const end = + boundary < 0 + ? rest.length + : boundary - (crlf && rest[boundary - 1] === "\r" ? 1 : 0); return { identifier: rest.slice("Identifier=".length, end), fields: rest.slice(end), diff --git a/src/native/parsers/lipo.test.ts b/src/native/parsers/lipo.test.ts index 43f08d8b8..96f2afbbc 100644 --- a/src/native/parsers/lipo.test.ts +++ b/src/native/parsers/lipo.test.ts @@ -59,6 +59,7 @@ architecture arm64e cpu_type_code: null, cpu_subtype: "CPU_SUBTYPE_FUTURE", cpu_subtype_code: null, + cpu_subtype_base: null, }, ]); }); @@ -85,8 +86,29 @@ architecture arm64e { cpu_subtype: "CPU_SUBTYPE_X86_ALL", cpu_subtype_code: null, + cpu_subtype_base: 3, capabilities: null, }, ]); }); + + it.each([ + { capabilities: "PTR_AUTH_VERSION USERSPACE 1", code: 0x81000002 }, + { capabilities: "", code: null }, + ])( + "retains an arm64e base subtype with capabilities '$capabilities'", + ({ capabilities, code }) => { + expect( + parseLipoArchitectures( + `architecture arm64e.v1\n cputype CPU_TYPE_ARM64\n cpusubtype CPU_SUBTYPE_ARM64E\n capabilities ${capabilities}\n`, + ), + ).toMatchObject([ + { + cpu_type_code: 0x0100000c, + cpu_subtype_code: code, + cpu_subtype_base: 2, + }, + ]); + }, + ); }); diff --git a/src/native/parsers/lipo.ts b/src/native/parsers/lipo.ts index 4f56d8b6b..cc65cca41 100644 --- a/src/native/parsers/lipo.ts +++ b/src/native/parsers/lipo.ts @@ -1,4 +1,5 @@ import { z } from "zod"; +import { machoCpuSubtypeBase } from "../../domain/apple/machoCpuIdentity.js"; const architectureSchema = z.object({ name: z.string().min(1), @@ -6,6 +7,7 @@ const architectureSchema = z.object({ cpu_subtype: z.string().nullable(), cpu_type_code: z.number().int().nonnegative().nullable(), cpu_subtype_code: z.number().int().nonnegative().nullable(), + cpu_subtype_base: z.number().int().nonnegative().nullable(), capabilities: z.string().nullable(), file_offset: z.number().int().min(0).nullable(), size: z.number().int().min(0).nullable(), @@ -30,6 +32,7 @@ export const parseLipoArchitectures = (output: string): LipoArchitecture[] => { cpu_subtype: null, cpu_type_code: null, cpu_subtype_code: null, + cpu_subtype_base: null, capabilities: null, file_offset: null, size: null, @@ -54,6 +57,7 @@ export const parseLipoArchitectures = (output: string): LipoArchitecture[] => { current.cpusubtype, current.capabilities, ), + cpu_subtype_base: cpuSubtypeBase(current.cpusubtype), capabilities: current.capabilities ?? null, file_offset: integer(current.offset), size: integer(current.size), @@ -158,10 +162,10 @@ const cpuSubtypeCode = ( }; /** The subtype bits a lipo record names, without its capability byte. */ -export const lipoSubtypeBits = (value: string | null): number | null => { - if (value === null) return null; +const cpuSubtypeBase = (value: string | undefined): number | null => { + if (value === undefined) return null; const subtype = unsigned32(value) ?? CPU_SUBTYPES[value]; - return subtype === undefined ? null : subtype & 0x00ffffff; + return subtype === undefined ? null : machoCpuSubtypeBase(subtype); }; /** lipo names the LIB64 capability and prints other capability bits in hex. */ diff --git a/src/native/pe/PeResourcesProvider.ts b/src/native/pe/PeResourcesProvider.ts index 4326cb3b7..4f31256d9 100644 --- a/src/native/pe/PeResourcesProvider.ts +++ b/src/native/pe/PeResourcesProvider.ts @@ -1,5 +1,7 @@ import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; +import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; +import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; import type { PeResourcesPort } from "../../application/binaryDiagnostics/PeResourcesPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { ArtifactOperationError } from "../../domain/artifactOperationError.js"; @@ -12,19 +14,29 @@ import { } from "../../domain/analysisErrorCore.js"; import type { InspectPeResourcesInput } from "../../domain/native/peResources.js"; import { err, ok } from "../../domain/result.js"; +import { ProviderCleanupError } from "../../domain/providerCleanupError.js"; import { PE_RESOURCES_PROVIDER } from "../../application/InvestigationProviders.js"; import { parsePeResources } from "./PeResourceParser.js"; /** Portable parser over one bounded, identity-checked regular file. */ export class PeResourcesProvider implements PeResourcesPort { readonly identity = PE_RESOURCES_PROVIDER; + readonly #resources = new ArtifactResourceScope(); + + close(): Promise { + return this.#resources.close(); + } async inspect(input: InspectPeResourcesInput, options?: ExecutionOptions) { try { - const snapshot = await readStableArtifact( - input.path, - input.max_file_bytes, - options?.signal, + const snapshot = await this.#resources.run(() => + readStableArtifact( + input.path, + input.max_file_bytes, + options?.signal, + undefined, + this.#resources, + ), ); return ok( await parsePeResources( @@ -44,12 +56,21 @@ export class PeResourcesProvider implements PeResourcesPort { } } -const peResourcesFailure = ( +const peResourcesFailurePrimary = ( cause: unknown, input: InspectPeResourcesInput, signal: AbortSignal | undefined, ) => { const operation = "inspect_pe_resources"; + if (cause instanceof ArtifactReaderFailure && cause.reason === "integrity") + return new AnalysisArtifactChangedError( + operation, + input.path, + cause.message, + { cause }, + ); + if (cause instanceof ArtifactReaderFailure && cause.reason === "cancelled") + return new AnalysisCancelledError(operation, { cause }); if (signal?.aborted) return new AnalysisCancelledError(operation, { cause }); if (cause instanceof ArtifactReaderFailure) { @@ -64,13 +85,6 @@ const peResourcesFailure = ( }, { cause }, ); - if (cause.reason === "integrity") - return new AnalysisArtifactChangedError( - operation, - input.path, - cause.message, - { cause }, - ); if (cause.reason === "path" || cause.reason === "format") return new AnalysisInputError(operation, { cause }, [ { @@ -79,8 +93,6 @@ const peResourcesFailure = ( message: cause.message, }, ]); - if (cause.reason === "cancelled") - return new AnalysisCancelledError(operation, { cause }); } if (cause instanceof Error && "code" in cause) { @@ -106,3 +118,24 @@ const peResourcesFailure = ( { cause }, ); }; + +const peResourcesFailure = ( + cause: unknown, + input: InspectPeResourcesInput, + signal: AbortSignal | undefined, +) => { + const primary = peResourcesFailurePrimary(cause, input, signal); + if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) + return primary; + const cleanup = new ProviderCleanupError( + PE_RESOURCES_PROVIDER.id, + cause.cleanup.resources, + { reason: cause.cleanup.reason }, + { operation: "inspect_pe_resources", cause }, + ); + return analysisErrorWithCleanupFailure( + primary, + cleanup, + "inspect_pe_resources", + ); +}; diff --git a/src/native/pwndbg/PwndbgCoreContext.ts b/src/native/pwndbg/PwndbgCoreContext.ts index 0ef29cd9b..db8386d26 100644 --- a/src/native/pwndbg/PwndbgCoreContext.ts +++ b/src/native/pwndbg/PwndbgCoreContext.ts @@ -17,6 +17,7 @@ import { type RecordedCrash, } from "../../domain/native/recordedCrash.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; +import type { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; import { capturedPwntoolsOutput, @@ -46,6 +47,7 @@ const replySchema = z.discriminatedUnion("ok", [ export const inspectPwndbgCore = async ({ environment, rootPath, + resources, diagnostics, options, runCommand, @@ -53,6 +55,7 @@ export const inspectPwndbgCore = async ({ }: { readonly environment: Readonly; readonly rootPath: string; + readonly resources: ArtifactResourceScope; readonly diagnostics: AnalysisCapturedOutput; readonly options: ExecutionOptions | undefined; readonly runCommand: PwntoolsCommand; @@ -178,11 +181,14 @@ export const inspectPwndbgCore = async ({ replyPath, PWNTOOLS_LIMITS.outputBytes, options?.signal, + undefined, + resources, ); reply = replySchema.parse(JSON.parse(raw.bytes.toString("utf8"))); } catch (cause: unknown) { if (options?.signal?.aborted) throw new AnalysisCancelledError(OPERATION, { + cause, capturedOutput: recordedCrashStageOutput(diagnostics, output), }); throw new AnalysisOutputError( @@ -226,22 +232,22 @@ export const inspectPwndbgCore = async ({ return { ...reply.value, diagnostics: output }; } catch (cause: unknown) { if (cause instanceof AnalysisError && cause.cleanupIncomplete) throw cause; - if ( + const primary = options?.signal?.aborted && (cause === options.signal.reason || (cause instanceof Error && cause.name === "AbortError")) - ) - throw new AnalysisCancelledError(OPERATION, { - capturedOutput: recordedCrashStageOutput(diagnostics, output), - }); - throw pwntoolsDecoderFailure( - cause, - "debugger", - gdb, - environment.REA_PWNTOOLS_PYTHON ?? "", - await readPwntoolsFailureEvidence(cause, stage), - failureContext, - ); + ? new AnalysisCancelledError(OPERATION, { + capturedOutput: recordedCrashStageOutput(diagnostics, output), + }) + : pwntoolsDecoderFailure( + cause, + "debugger", + gdb, + environment.REA_PWNTOOLS_PYTHON ?? "", + await readPwntoolsFailureEvidence(cause, stage, resources), + failureContext, + ); + throw primary; } }; diff --git a/src/native/pwntools/PwntoolsDecoder.ts b/src/native/pwntools/PwntoolsDecoder.ts index 3a28edbfa..169f25601 100644 --- a/src/native/pwntools/PwntoolsDecoder.ts +++ b/src/native/pwntools/PwntoolsDecoder.ts @@ -16,6 +16,8 @@ import type { AnalysisPartialObservation, } from "../../domain/analysisErrorBase.js"; import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; +import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; +import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; import { AnalysisCancelledError, @@ -78,6 +80,7 @@ export interface PwntoolsDecoderProfile< readonly payload: Payload; readonly snapshot: { readonly bytes: Buffer; readonly sha256: string }; readonly rootPath: string; + readonly resources: ArtifactResourceScope; readonly diagnostics: AnalysisCapturedOutput; readonly options: ExecutionOptions | undefined; readonly runCommand: PwntoolsCommand; @@ -96,6 +99,7 @@ export class PwntoolsDecoder< symbol, "admitted" | "cancelled" >(); + readonly #resources = new ArtifactResourceScope(); #closing = false; #closePromise: Promise | undefined; #pendingCleanup: @@ -244,6 +248,8 @@ export class PwntoolsDecoder< input.path, PWNTOOLS_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); phase = "decoder"; root = await this.createRuntime(); @@ -298,11 +304,16 @@ export class PwntoolsDecoder< replyPath, PWNTOOLS_LIMITS.outputBytes, options?.signal, + undefined, + this.#resources, ); reply = replySchema.parse(JSON.parse(file.bytes.toString("utf8"))); } catch (cause: unknown) { if (options?.signal?.aborted) - throw new AnalysisCancelledError(OPERATION, { capturedOutput }); + throw new AnalysisCancelledError(OPERATION, { + cause, + capturedOutput, + }); throw new AnalysisOutputError( OPERATION, `Owned pwntools decoder reply failed for ${input.path}: ${cause instanceof z.ZodError ? cause.issues[0]?.message + " at " + (cause.issues[0]?.path.map(String).join(".") ?? "root") : cause instanceof Error ? cause.message : String(cause)}`, @@ -369,6 +380,7 @@ export class PwntoolsDecoder< payload: reply.value, snapshot, rootPath: root.path, + resources: this.#resources, diagnostics: capturedOutput, options, runCommand: (spawn, classifyFailure) => @@ -385,12 +397,18 @@ export class PwntoolsDecoder< } return err(cause); } - const evidence = await readPwntoolsFailureEvidence(cause, root?.path); - result = err( + const evidence = await readPwntoolsFailureEvidence( + cause, + root?.path, + this.#resources, + ); + const primary = options?.signal?.aborted && - (cause === options.signal.reason || - (cause instanceof Error && cause.name === "AbortError")) - ? new AnalysisCancelledError(OPERATION) + (cause === options.signal.reason || + (cause instanceof Error && cause.name === "AbortError") || + (cause instanceof ArtifactReaderFailure && + cause.cleanup !== undefined)) + ? new AnalysisCancelledError(OPERATION, { cause }) : pwntoolsDecoderFailure( cause, phase, @@ -398,8 +416,8 @@ export class PwntoolsDecoder< executablePath, evidence, context, - ), - ); + ); + result = err(primary); } if (this.#pendingCleanup !== undefined) { this.#pendingCleanup.failure = result.ok ? undefined : result.error; @@ -483,7 +501,39 @@ export class PwntoolsDecoder< this.#closing = true; this.#closePromise ??= this.#tail .then(async () => { - const failure = await this.#retire(); + let failure: AnalysisError | undefined; + try { + failure = await this.#retire(); + } catch (cause: unknown) { + failure = new ProviderCleanupError( + this.identity.id, + [this.#pendingCleanup?.root?.path ?? "pwntools decoder"], + { reason: cause instanceof Error ? cause.message : String(cause) }, + { operation: this.profile.operation, cause }, + ); + } + try { + await this.#resources.close(); + } catch (cause: unknown) { + const observation = ArtifactReaderFailure.cleanupObservation( + cause, + "pwntools artifact read", + ); + const resourceFailure = new ProviderCleanupError( + this.identity.id, + observation.resources, + { reason: observation.reason }, + { operation: this.profile.operation, cause }, + ); + failure = + failure === undefined + ? resourceFailure + : analysisErrorWithCleanupFailure( + failure, + resourceFailure, + this.profile.operation, + ); + } if (failure !== undefined) throw failure; }) .catch((cause: unknown) => { @@ -502,8 +552,8 @@ export class PwntoolsDecoder< } async #completeCleanup( - retire: () => Promise, - ): Promise { + retire: () => Promise, + ): Promise { const failure = await retire(); return failure !== undefined && this.#closing ? retire() : failure; } @@ -518,6 +568,13 @@ export class PwntoolsDecoder< [ pending.process.launch.ownership?.runId ?? "owned-decoder", ...(pending.root === undefined ? [] : [pending.root.path]), + // The retained group may still be live; name it as OwnedCommand does. + ...(pending.process.launch.ownership === undefined + ? [] + : [ + `pid:${pending.process.launch.ownership.leaderPid}`, + `process-group:${pending.process.launch.ownership.processGroupId}`, + ]), ], { reason: stopped.reason, @@ -541,18 +598,46 @@ export class PwntoolsDecoder< return undefined; } - async #retire(): Promise { - const failure = await this.#retireProcess(); - if (failure !== undefined) return failure; + async #retire(): Promise { + let failure: AnalysisError | undefined; + try { + await this.#resources.retryCleanup(); + } catch (cause: unknown) { + const observation = ArtifactReaderFailure.cleanupObservation( + cause, + "pwntools artifact read", + ); + failure = new ProviderCleanupError( + this.identity.id, + observation.resources, + { reason: observation.reason }, + { + operation: this.profile.operation, + cause, + ...(this.#pendingCleanup?.observation === undefined + ? {} + : { partialObservation: this.#pendingCleanup.observation }), + }, + ); + } + const processFailure = await this.#retireProcess(); + if (processFailure !== undefined) { + return failure === undefined + ? processFailure + : analysisErrorWithCleanupFailure( + failure, + processFailure, + this.profile.operation, + ); + } const pending = this.#pendingCleanup; - if (pending === undefined) return undefined; - if (pending.root !== undefined) { + if (pending?.root !== undefined) { const root = pending.root; try { await root.close(); pending.root = undefined; } catch (cause: unknown) { - return new ProviderCleanupError( + const rootFailure = new ProviderCleanupError( this.identity.id, [root.path], { @@ -573,9 +658,18 @@ export class PwntoolsDecoder< : { partialObservation: pending.observation }), }, ); + failure = + failure === undefined + ? rootFailure + : analysisErrorWithCleanupFailure( + failure, + rootFailure, + this.profile.operation, + ); } } - this.#pendingCleanup = undefined; - return undefined; + if (!this.#resources.hasPending && pending?.root === undefined) + this.#pendingCleanup = undefined; + return failure; } } diff --git a/src/native/pwntools/PwntoolsRecordedCrashProvider.ts b/src/native/pwntools/PwntoolsRecordedCrashProvider.ts index ffc10d13b..24cee7314 100644 --- a/src/native/pwntools/PwntoolsRecordedCrashProvider.ts +++ b/src/native/pwntools/PwntoolsRecordedCrashProvider.ts @@ -48,6 +48,7 @@ export class PwntoolsRecordedCrashProvider payload, snapshot, rootPath, + resources, diagnostics, options, runCommand, @@ -120,6 +121,7 @@ export class PwntoolsRecordedCrashProvider const context = await inspectPwndbgCore({ environment, rootPath, + resources, diagnostics, options, runCommand, diff --git a/src/native/pwntools/PwntoolsResourceLimits.ts b/src/native/pwntools/PwntoolsResourceLimits.ts index dcbe91d5a..3b379779f 100644 --- a/src/native/pwntools/PwntoolsResourceLimits.ts +++ b/src/native/pwntools/PwntoolsResourceLimits.ts @@ -7,6 +7,7 @@ import { } from "./PwntoolsRelease.js"; import { z } from "zod"; import { PWNTOOLS_LIMITS } from "./PwntoolsRelease.js"; +import type { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; /** Actual limits reported by the owned bridge after lowering inherited soft limits. */ export const pwntoolsResourceLimitsSchema = z.strictObject({ @@ -42,6 +43,7 @@ export interface PwntoolsFailureEvidence { export const readPwntoolsFailureEvidence = async ( cause: unknown, rootPath?: string, + resources?: ArtifactResourceScope, ): Promise => { let limitReport: PwntoolsLimitReport | undefined; let marker: PwntoolsFailureEvidence["marker"]; @@ -56,6 +58,9 @@ export const readPwntoolsFailureEvidence = async ( const reported = await readStableArtifact( join(rootPath, "resource.failure"), 1, + undefined, + undefined, + resources, ); const expected = cause.snapshot.exitCode === PWNTOOLS_MEMORY_FAILURE_EXIT ? "M" : "F"; @@ -90,6 +95,9 @@ export const readPwntoolsFailureEvidence = async ( const reported = await readStableArtifact( join(rootPath, "limits.json"), 4096, + undefined, + undefined, + resources, ); limitReport = { limits: pwntoolsResourceLimitsSchema.parse( diff --git a/src/pcap/PcapCommand.ts b/src/pcap/PcapCommand.ts new file mode 100644 index 000000000..0d28a3d75 --- /dev/null +++ b/src/pcap/PcapCommand.ts @@ -0,0 +1,205 @@ +import { randomUUID } from "node:crypto"; +import { AnalysisError } from "../domain/analysisErrorBase.js"; +import { + AnalysisCancelledError, + AnalysisProtocolError, + AnalysisResourceConstraintError, + AnalysisTimeoutError, + AnalysisUnsupportedTargetError, +} from "../domain/analysisErrorCore.js"; +import { + OwnedCommandFailure, + runOwnedCommand, +} from "../process/OwnedCommand.js"; +import type { ProviderProcessSupervisor } from "../process/ProviderProcess.js"; +import { prepareProcessOwnershipInspection } from "../process/ProcessOwnershipObservation.js"; +import { + isWindowsBatchFile, + windowsBatchCommand, + WindowsBatchCommandError, +} from "../process/WindowsBatchCommand.js"; +import { pcapToolUnavailable } from "./PcapConfiguration.js"; + +export interface PcapCommandLimits { + readonly timeoutMs: number; + readonly maxOutputBytes: number; +} + +/** Owned process execution shared by version probes and capture reads. */ +export const runPcapCommand = async (options: { + readonly operation: string; + readonly command: string; + readonly arguments: readonly string[]; + readonly limits: PcapCommandLimits; + readonly environment: Readonly>; + readonly signal: AbortSignal | undefined; + readonly inputPath?: string; + readonly nativeBound?: { + readonly limiter?: { command: string; arguments: readonly string[] }; + readonly memoryLimitBytes?: number; + }; + readonly retain: ( + owner: ProviderProcessSupervisor, + resources: readonly string[], + ) => void; +}): Promise<{ stdout: string; stderr: string }> => { + const { operation, command, limits, signal } = options; + if (signal?.aborted) + throw new AnalysisCancelledError(operation, { cause: signal.reason }); + const hostEnvironment = { + ...process.env, + ...options.environment, + LC_ALL: "C", + LANG: "C", + }; + try { + const batch = process.platform === "win32" && isWindowsBatchFile(command); + const invocation = batch + ? windowsBatchCommand({ + environment: hostEnvironment, + batchPath: command, + arguments: options.arguments, + }) + : { command, arguments: options.arguments }; + const boundedInvocation = + options.nativeBound?.limiter === undefined + ? invocation + : { + command: options.nativeBound.limiter.command, + arguments: [ + ...options.nativeBound.limiter.arguments, + invocation.command, + ...invocation.arguments, + ], + }; + // Native ownership preparation has its own bounded compiler lifecycle; + // do not spend the tool's execution deadline rebuilding a cold SDK cache. + await prepareProcessOwnershipInspection(signal); + const output = await runOwnedCommand( + { + ...boundedInvocation, + runId: randomUUID(), + hostEnvironment, + windowsVerbatimArguments: batch, + expectedCommand: null, + ...(options.nativeBound?.memoryLimitBytes === undefined + ? {} + : { memoryLimitBytes: options.nativeBound.memoryLimitBytes }), + }, + { timeoutMs: limits.timeoutMs, diagnosticBytes: limits.maxOutputBytes }, + signal === undefined ? {} : { signal }, + ); + return { stdout: output.stdout.text, stderr: output.stderr.text }; + } catch (cause) { + if (cause instanceof AnalysisError) throw cause; + if ( + cause instanceof OwnedCommandFailure && + cause.cleanupOwner !== undefined + ) + options.retain(cause.cleanupOwner, cause.resources); + const details = { + cause, + ...(cause instanceof OwnedCommandFailure && cause.snapshot !== null + ? { + capturedOutput: { + stdout: "", + stderr: cause.snapshot.stderr.text, + truncated: + cause.snapshot.stdout.observedBytes > 0 || + (cause.snapshot.diagnosticTruncated ?? false), + exit_code: cause.snapshot.exitCode ?? null, + signal: cause.snapshot.signal ?? null, + }, + } + : {}), + ...(cause instanceof OwnedCommandFailure && cause.cleanupFailure !== null + ? { + cleanup: { + reason: cause.cleanupFailure, + resources: cause.resources, + }, + } + : {}), + }; + if ( + signal?.aborted || + (cause instanceof OwnedCommandFailure && cause.reason === "cancelled") + ) + throw new AnalysisCancelledError(operation, details); + if ( + cause instanceof OwnedCommandFailure && + cause.snapshot?.memoryLimitReached === true + ) + throw new AnalysisResourceConstraintError( + operation, + "memory", + "The owned Windows tool tree reached its enforced committed-memory limit.", + { + process_memory_limit_bytes: + options.nativeBound?.memoryLimitBytes ?? null, + }, + details, + ); + if ( + cause instanceof OwnedCommandFailure && + (cause.snapshot?.signal === "SIGXCPU" || + cause.snapshot?.signal === "SIGXFSZ") + ) + throw new AnalysisResourceConstraintError( + operation, + cause.snapshot.signal === "SIGXCPU" ? "cpu" : "file-size", + `Producer terminated with ${cause.snapshot.signal}; its exact cause is not independently established.`, + null, + details, + ); + if (cause instanceof OwnedCommandFailure && cause.reason === "timeout") + throw new AnalysisTimeoutError(operation, limits.timeoutMs, details); + if (cause instanceof OwnedCommandFailure && cause.reason === "output-limit") + throw new AnalysisResourceConstraintError( + operation, + "memory", + "Tool output exceeded its complete-output budget", + { max_output_bytes: limits.maxOutputBytes }, + details, + ); + if ( + cause instanceof WindowsBatchCommandError || + (cause instanceof Error && + "code" in cause && + (cause.code === "ENOENT" || cause.code === "EACCES")) + ) + throw pcapToolUnavailable( + operation, + `Cannot run selected tool ${command}: ${cause.message}`, + details, + ); + const diagnostic = + cause instanceof OwnedCommandFailure + ? cause.snapshot?.stderr.text.trim() || cause.message + : cause instanceof Error + ? cause.message + : String(cause); + if (options.inputPath === undefined) + throw pcapToolUnavailable( + operation, + `The selected tool ${command} cannot report its version: ${diagnostic}`, + details, + ); + if ( + options.inputPath !== undefined && + /not a capture file|file.*isn't a capture file|file format.*not supported/iu.test( + diagnostic, + ) + ) + throw new AnalysisUnsupportedTargetError( + operation, + options.inputPath, + diagnostic, + details, + ); + throw new AnalysisProtocolError( + `Packet capture tool ${command} failed: ${diagnostic}`, + details, + ); + } +}; diff --git a/src/pcap/PcapConfiguration.test.ts b/src/pcap/PcapConfiguration.test.ts new file mode 100644 index 000000000..edbd223b2 --- /dev/null +++ b/src/pcap/PcapConfiguration.test.ts @@ -0,0 +1,170 @@ +import { describe, expect, it } from "vitest"; + +import { + CAPINFOS_COMMAND_ENV, + TSHARK_COMMAND_ENV, + resolvePcapTools, +} from "./PcapConfiguration.js"; +import { parseCapinfosOutput, parseTsharkJsonOutput } from "./PcapOutput.js"; + +describe("resolvePcapTools", () => { + it("prefers absolute environment paths for both tools", () => { + expect( + resolvePcapTools({ + [TSHARK_COMMAND_ENV]: "/usr/bin/tshark", + [CAPINFOS_COMMAND_ENV]: "/usr/bin/capinfos", + }), + ).toEqual({ + tshark: { command: "/usr/bin/tshark", source: "environment" }, + capinfos: { command: "/usr/bin/capinfos", source: "environment" }, + }); + }); + + it("falls back to PATH resolution without the environment keys", () => { + expect(resolvePcapTools({})).toEqual({ + tshark: { command: "tshark", source: "path" }, + capinfos: { command: "capinfos", source: "path" }, + }); + }); + + it("rejects a relative tshark path explicitly", () => { + expect(() => + resolvePcapTools({ [TSHARK_COMMAND_ENV]: "bin/tshark" }), + ).toThrow(/must be an absolute path/u); + }); + + it("rejects a relative capinfos path explicitly", () => { + expect(() => + resolvePcapTools({ [CAPINFOS_COMMAND_ENV]: "capinfos" }), + ).toThrow(/must be an absolute path/u); + }); +}); + +const REAL_CAPINFOS = [ + "File name: /work/rich-capture.pcap", + "File type: Wireshark/tcpdump/... - pcap", + "File encapsulation: Linux cooked-mode capture v2", + "Packet size limit: file hdr: 262144 bytes", + "Number of packets: 50", + "File size: 23279 bytes", + "Capture duration: 0.373473 seconds", + "Earliest packet time: 2026-10-11 14:13:40.608505", + "Latest packet time: 2026-10-11 14:13:40.981978", + "SHA256: c94f94742b3288b9a979711509ed5eab3028576301f8938319de3c22a6f5c40b", +].join("\n"); + +describe("parseCapinfosOutput", () => { + it("projects metadata from real capinfos output", () => { + expect(parseCapinfosOutput(REAL_CAPINFOS)).toEqual({ + fileType: "Wireshark/tcpdump/... - pcap", + encapsulation: "Linux cooked-mode capture v2", + packetCount: 50, + captureStart: "2026-10-11 14:13:40.608505", + captureEnd: "2026-10-11 14:13:40.981978", + captureDurationSeconds: 0.373473, + snapshotLength: 262144, + sha256: + "c94f94742b3288b9a979711509ed5eab3028576301f8938319de3c22a6f5c40b", + }); + }); + + it("rejects empty metadata rather than reporting complete unknown facts", () => { + expect(() => parseCapinfosOutput("")).toThrow(/machine-readable/u); + }); +}); + +const REAL_TSHARK_JSON = JSON.stringify([ + { + _source: { + layers: { + "frame.number": ["1"], + "frame.protocols": ["sll:ethertype:ip:udp:dns"], + "ip.src": ["192.168.1.1"], + "ip.dst": ["8.8.8.8"], + "dns.qry.name": ["example.com"], + "dns.flags.response": ["1"], + "dns.a": ["93.184.216.34"], + }, + }, + }, + { + _source: { + layers: { + "frame.number": ["2"], + "frame.protocols": ["sll:ethertype:ip:tcp:tls"], + "ip.src": ["192.168.1.1"], + "ip.dst": ["93.184.216.34"], + "tls.handshake.extensions_server_name": ["example.com"], + }, + }, + }, + { + _source: { + layers: { + "frame.number": ["3"], + "frame.protocols": ["sll:ethertype:ip:tcp:http"], + "ip.src": ["192.168.1.1"], + "ip.dst": ["93.184.216.34"], + "http.request.full_uri": ["http://example.com/page"], + }, + }, + }, +]); + +describe("parseTsharkJsonOutput", () => { + it("projects endpoints, DNS, TLS SNI, protocols, and HTTP URIs", async () => { + const result = await parseTsharkJsonOutput(REAL_TSHARK_JSON); + expect(result.endpoints).toEqual( + expect.arrayContaining([ + { address: "192.168.1.1", port: null, packet_count: 3 }, + { address: "8.8.8.8", port: null, packet_count: 1 }, + { address: "93.184.216.34", port: null, packet_count: 2 }, + ]), + ); + expect(result.dnsQueries).toEqual([ + { + query: "example.com", + response_addresses: ["93.184.216.34"], + response_address_count: 1, + }, + ]); + expect(result.tlsSniValues).toEqual(["example.com"]); + expect(result.httpRequestUris).toEqual(["http://example.com/page"]); + expect(result.protocolDistribution).toEqual( + expect.arrayContaining([ + { protocol: "sll:ethertype:ip:udp:dns", packet_count: 1 }, + { protocol: "sll:ethertype:ip:tcp:tls", packet_count: 1 }, + { protocol: "sll:ethertype:ip:tcp:http", packet_count: 1 }, + ]), + ); + }); + + it("retains every endpoint within the aggregate resource budget", async () => { + const packets = Array.from({ length: 10 }, (_, index) => ({ + _source: { + layers: { + "frame.number": [String(index + 1)], + "frame.protocols": ["ip:tcp"], + "ip.src": [`10.0.0.${index}`], + "ip.dst": ["10.0.1.1"], + }, + }, + })); + const result = await parseTsharkJsonOutput(JSON.stringify(packets)); + expect(result.endpoints).toHaveLength(11); + expect(result.endpointCount).toBe(11); // 10 src + 1 dst + }); + + it.each([ + "", + "not json", + "{}", + "null", + "[null]", + '[{"_source":{"layers":{"ip.src":[3]}}}]', + ])("rejects malformed producer output %s", async (text) => { + await expect(parseTsharkJsonOutput(text)).rejects.toMatchObject({ + _tag: "AnalysisProtocolError", + }); + }); +}); diff --git a/src/pcap/PcapConfiguration.ts b/src/pcap/PcapConfiguration.ts new file mode 100644 index 000000000..b2a6212d1 --- /dev/null +++ b/src/pcap/PcapConfiguration.ts @@ -0,0 +1,172 @@ +import { isAbsolute } from "node:path"; + +import type { ProviderAvailability } from "../application/AnalysisProvider.js"; +import type { ProviderRejectionCode } from "../contracts/providerSelection.js"; +import type { AnalysisErrorOptions } from "../domain/analysisErrorBase.js"; +import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js"; +import type { JsonValue } from "../domain/jsonValue.js"; + +/** Environment keys selecting the caller's tshark and capinfos binaries. */ +export const TSHARK_COMMAND_ENV = "REA_TSHARK_COMMAND"; +export const CAPINFOS_COMMAND_ENV = "REA_CAPINFOS_COMMAND"; + +const TOOL_REMEDIATION = `Supply Wireshark 4.x tshark and capinfos on PATH or through absolute ${TSHARK_COMMAND_ENV} and ${CAPINFOS_COMMAND_ENV}; REA does not install them.`; + +/** + * Host-tool refusals concern the caller's Wireshark installation, not the + * target, so they carry their own guidance instead of the generic advice to + * choose another target. + */ +export const pcapToolUnavailable = ( + operation: string, + reason: string, + options?: AnalysisErrorOptions, +): AnalysisCapabilityUnavailableError => + new AnalysisCapabilityUnavailableError("pcap", operation, reason, { + ...options, + userMessage: `${/[.!?]$/u.test(reason) ? reason : `${reason}.`} ${TOOL_REMEDIATION}`, + }); + +/** How each tool was selected for this provider instance. */ +export interface PcapToolSelection { + readonly tshark: { command: string; source: "environment" | "path" }; + readonly capinfos: { command: string; source: "environment" | "path" }; +} + +/** + * Resolve the caller-supplied tshark and capinfos binaries. Each accepts an + * absolute environment path or falls back to PATH resolution, mirroring the + * mitmdump pattern. REA never installs the Wireshark suite. + */ +export const resolvePcapTools = ( + environment: Readonly>, +): PcapToolSelection => { + const tsharkEnv = environment[TSHARK_COMMAND_ENV]; + const capinfosEnv = environment[CAPINFOS_COMMAND_ENV]; + if ( + tsharkEnv !== undefined && + tsharkEnv.trim() !== "" && + !isAbsolute(tsharkEnv) + ) + throw new PcapConfigurationFailure( + "tshark_not_absolute", + `${TSHARK_COMMAND_ENV} must be an absolute path to the tshark binary`, + { configured: tsharkEnv }, + ); + if ( + capinfosEnv !== undefined && + capinfosEnv.trim() !== "" && + !isAbsolute(capinfosEnv) + ) + throw new PcapConfigurationFailure( + "capinfos_not_absolute", + `${CAPINFOS_COMMAND_ENV} must be an absolute path to the capinfos binary`, + { configured: capinfosEnv }, + ); + return { + tshark: { + command: + tsharkEnv === undefined || tsharkEnv.trim() === "" + ? "tshark" + : tsharkEnv, + source: + tsharkEnv === undefined || tsharkEnv.trim() === "" + ? "path" + : "environment", + }, + capinfos: { + command: + capinfosEnv === undefined || capinfosEnv.trim() === "" + ? "capinfos" + : capinfosEnv, + source: + capinfosEnv === undefined || capinfosEnv.trim() === "" + ? "path" + : "environment", + }, + }; +}; + +export type PcapConfigurationFailureCode = + | "tshark_not_absolute" + | "capinfos_not_absolute" + | "tshark_missing" + | "capinfos_missing" + | "tshark_version_unresolved" + | "capinfos_version_unresolved" + | "tshark_version_unsupported" + | "capinfos_version_unsupported"; + +export class PcapConfigurationFailure extends Error { + constructor( + readonly code: PcapConfigurationFailureCode, + message: string, + readonly diagnostics: Readonly> = {}, + options?: ErrorOptions, + ) { + super(message, options); + } +} + +/** Recognize the selected Wireshark tool's version banner. */ +const parseVersion = ( + stdout: string, + tool: "tshark" | "capinfos", +): string | null => { + const line = stdout + .split(/\r?\n/u) + .map((entry) => entry.trim()) + .find((entry) => entry !== ""); + const parsed = + line === undefined + ? null + : new RegExp(`^${tool} \\(Wireshark\\) (\\d+)\\.\\d+\\.\\d+`, "iu").exec( + line, + ); + if (parsed === null || line === undefined) return null; + if (parsed[1] !== "4") + throw new PcapConfigurationFailure( + `${tool}_version_unsupported`, + "Packet summary inspection currently requires Wireshark 4.x tools; select an installation with the admitted output profile.", + { version: line }, + ); + return line; +}; + +export interface PcapClientIdentity { + readonly tsharkVersion: string | null; + readonly capinfosVersion: string | null; +} + +/** Probe both tools without reading any capture file. */ +export const inspectPcapClient = async ( + selection: PcapToolSelection, + probe: (command: string) => Promise, +): Promise => ({ + tsharkVersion: parseVersion(await probe(selection.tshark.command), "tshark"), + capinfosVersion: parseVersion( + await probe(selection.capinfos.command), + "capinfos", + ), +}); + +/** Availability in the shape shared by every provider. */ +const rejectionCodeOf = ( + code: PcapConfigurationFailureCode, +): ProviderRejectionCode => + code.includes("missing") + ? "executable_missing" + : code.includes("unsupported") + ? "unsupported_version" + : code.includes("not_absolute") + ? "not_configured" + : "version_unresolved"; + +export const pcapConfigurationAvailability = ( + cause: PcapConfigurationFailure, +): ProviderAvailability => ({ + status: "unavailable", + code: rejectionCodeOf(cause.code), + reason: cause.message, + diagnostics: { ...cause.diagnostics }, +}); diff --git a/src/pcap/PcapNativeBound.ts b/src/pcap/PcapNativeBound.ts new file mode 100644 index 000000000..dc98bfca0 --- /dev/null +++ b/src/pcap/PcapNativeBound.ts @@ -0,0 +1,78 @@ +import { access, realpath } from "node:fs/promises"; +import { constants } from "node:fs"; +import { isAbsolute } from "node:path"; +import { AnalysisError } from "../domain/analysisErrorBase.js"; +import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js"; +import type { ArtifactAnalysisResources } from "../process/ArtifactAnalysisResources.js"; +import type { runPcapCommand } from "./PcapCommand.js"; + +const PRLIMIT_COMMAND_ENV = "REA_TSHARK_PRLIMIT_COMMAND"; + +/** Own native capture admission and the exact enforced resource profile. */ +export const preparePcapNativeBound = async ( + environment: Readonly>, + resources: ArtifactAnalysisResources, +): Promise<{ + nativeBound: NonNullable[0]["nativeBound"]>; + limitations: readonly string[]; +}> => { + if (process.platform === "win32") { + return { + nativeBound: { memoryLimitBytes: 1024 ** 3 }, + limitations: [ + "Each owned Windows tool tree has a 1 GiB Job Object committed-memory limit; this is not a machine-wide quota.", + ], + }; + } + if (process.platform !== "linux") { + const reason = + "Packet summaries require an enforceable native memory bound: Linux with util-linux prlimit, or Windows with owned Job Objects. This host's capture boundary remains unsupported."; + throw new AnalysisCapabilityUnavailableError( + "pcap", + "inspect_pcap_capture", + reason, + { userMessage: reason }, + ); + } + const configured = environment[PRLIMIT_COMMAND_ENV] ?? "/usr/bin/prlimit"; + try { + if (!isAbsolute(configured)) + throw new Error(`${PRLIMIT_COMMAND_ENV} must be absolute.`); + const limiter = await realpath(configured); + await access(limiter, constants.X_OK); + const limits = await resources.readLimits({ + address_space_bytes: 1024 ** 3, + file_bytes: 64 * 1024 ** 2, + cpu_seconds: 300, + }); + const nativeBound = { + limiter: { + command: limiter, + arguments: [ + `--as=${limits.address_space_bytes}:${limits.address_space_bytes}`, + `--fsize=${limits.file_bytes}:${limits.file_bytes}`, + `--cpu=${limits.cpu_seconds}:${limits.cpu_seconds}`, + "--core=0:0", + "--", + ], + }, + }; + const limitations = [ + `Linux prlimit preserves stricter inherited ceilings: ${limits.address_space_bytes} bytes of per-process address space, ${limits.file_bytes} bytes per file and ${limits.cpu_seconds} CPU seconds; core dumps are disabled. These are not aggregate machine quotas.`, + ]; + return { nativeBound, limitations }; + } catch (cause) { + if (cause instanceof AnalysisError) throw cause; + const reason = + "Cannot establish the selected Linux resource limiter before processing capture bytes."; + throw new AnalysisCapabilityUnavailableError( + "pcap", + "inspect_pcap_capture", + reason, + { + cause, + userMessage: `${reason} (${cause instanceof Error ? cause.message : String(cause)}) Check that ${PRLIMIT_COMMAND_ENV} (default /usr/bin/prlimit) names an absolute, executable util-linux prlimit.`, + }, + ); + } +}; diff --git a/src/pcap/PcapOutput.test.ts b/src/pcap/PcapOutput.test.ts new file mode 100644 index 000000000..c0e158438 --- /dev/null +++ b/src/pcap/PcapOutput.test.ts @@ -0,0 +1,167 @@ +import { expect, it } from "vitest"; +import { parseCapinfosOutput, parseTsharkJsonOutput } from "./PcapOutput.js"; + +const capture = (layers: ReadonlyArray>) => + JSON.stringify( + layers.map((fields, index) => ({ + _source: { + layers: { + "frame.number": [String(index + 1)], + "frame.protocols": ["ip:udp:dns"], + ...fields, + }, + }, + })), + ); + +it("binds interleaved DNS answers to the question in their response packet", async () => { + const result = await parseTsharkJsonOutput( + capture([ + { "dns.qry.name": ["alpha.example"], "dns.flags.response": ["False"] }, + { "dns.qry.name": ["beta.example"], "dns.flags.response": ["False"] }, + { + "dns.qry.name": ["alpha.example"], + "dns.flags.response": ["True"], + "dns.a": ["192.0.2.10"], + }, + { + "dns.qry.name": ["beta.example"], + "dns.flags.response": ["True"], + "dns.a": ["192.0.2.20"], + }, + ]), + ); + expect(result.dnsQueries).toEqual([ + { + query: "alpha.example", + response_addresses: ["192.0.2.10"], + response_address_count: 1, + }, + { + query: "beta.example", + response_addresses: ["192.0.2.20"], + response_address_count: 1, + }, + ]); + expect(result.partial).toBe(false); +}); + +it("retains unassignable DNS addresses without inventing a query relationship", async () => { + const result = await parseTsharkJsonOutput( + capture([ + { + "dns.qry.name": ["alpha.example", "beta.example"], + "dns.flags.response": ["True"], + "dns.a": ["192.0.2.9"], + }, + { "dns.flags.response": ["True"], "dns.aaaa": ["2001:db8::9"] }, + ]), + ); + expect( + result.dnsQueries.every((query) => query.response_addresses.length === 0), + ).toBe(true); + expect(result.unattributedDnsAddresses).toEqual(["192.0.2.9", "2001:db8::9"]); + expect(result.unattributedDnsPackets).toBe(2); + expect(result.partial).toBe(true); +}); + +it("counts IPv6 endpoints once per packet and preserves every examined fact", async () => { + const packets = Array.from({ length: 51 }, (_, index) => ({ + "ipv6.src": ["2001:db8::1"], + "ipv6.dst": ["2001:db8::1"], + "tls.handshake.extensions_server_name": [`host${String(index)}.example`], + "frame.protocols": [`ipv6:protocol${String(index)}`], + })); + const result = await parseTsharkJsonOutput(capture(packets)); + expect(result.endpoints).toEqual([ + { address: "2001:db8::1", port: null, packet_count: 51 }, + ]); + expect(result.tlsSniCount).toBe(51); + expect(result.tlsSniValues).toHaveLength(51); + expect(result.protocolCount).toBe(51); + expect(result.protocolDistribution).toHaveLength(51); + expect(result.partial).toBe(false); +}); + +it("orders equal-count endpoints and protocols by code point, not host locale", async () => { + // Locale collation puts "fe80::1" first and, under da-DK, "aarp" after "zz". + const result = await parseTsharkJsonOutput( + capture([ + { "ipv6.src": ["fe80::1"], "frame.protocols": ["eth:llc:zz"] }, + { "ipv6.src": ["fe80:1::1"], "frame.protocols": ["eth:llc:aarp"] }, + ]), + ); + expect(result.endpoints.map(({ address }) => address)).toEqual([ + "fe80:1::1", + "fe80::1", + ]); + expect(result.protocolDistribution.map(({ protocol }) => protocol)).toEqual([ + "eth:llc:aarp", + "eth:llc:zz", + ]); +}); + +it("preserves all DNS addresses and their exact examined count", async () => { + const result = await parseTsharkJsonOutput( + capture( + Array.from({ length: 101 }, (_, index) => ({ + "dns.qry.name": ["rotating.example"], + "dns.flags.response": ["True"], + "dns.a": [`192.0.2.${String(index)}`], + })), + ), + ); + expect(result.dnsQueries[0]?.response_addresses).toHaveLength(101); + expect(result.dnsQueries[0]?.response_address_count).toBe(101); + expect(result.partial).toBe(false); +}); + +it("accepts exact machine packet counts and rejects scaled human counts", () => { + const prefix = + "File type: pcap\nFile encapsulation: Ethernet\nNumber of packets: "; + expect(parseCapinfosOutput(`${prefix}20010`).packetCount).toBe(20010); + expect(() => parseCapinfosOutput(`${prefix}20 k`)).toThrow( + /machine-readable/u, + ); +}); + +it("excludes transport credentials without normalizing observed URL bytes", async () => { + const result = await parseTsharkJsonOutput( + capture([ + { + "http.request.full_uri": [ + "http://user:password@Example.com/a/../b?token=local-evidence#keep", + ], + }, + { + "http.request.full_uri": [ + "http://other:secret@Example.com/a/../b?token=local-evidence#keep", + ], + }, + ]), + ); + expect(result.httpRequestUris).toEqual([ + "http://Example.com/a/../b?token=local-evidence#keep", + ]); + expect(result.httpRequestUriCount).toBe(2); + expect(result.httpUriRedactionCount).toBe(2); + expect(result.partial).toBe(true); +}); + +it("refuses dense JSON before its expanded graph exceeds the decoding budget", async () => { + await expect( + parseTsharkJsonOutput(`[${"{},".repeat(600_000)}{}]`), + ).rejects.toMatchObject({ + _tag: "AnalysisResourceConstraintError", + }); +}); + +it("permits cancellation while validating and aggregating producer output", async () => { + const controller = new AbortController(); + const result = parseTsharkJsonOutput( + capture([{ "ip.src": ["192.0.2.1"] }]), + controller.signal, + ); + controller.abort(new Error("stopped")); + await expect(result).rejects.toThrow("stopped"); +}); diff --git a/src/pcap/PcapOutput.ts b/src/pcap/PcapOutput.ts new file mode 100644 index 000000000..b14d7ba3c --- /dev/null +++ b/src/pcap/PcapOutput.ts @@ -0,0 +1,316 @@ +import { setImmediate as yieldToEventLoop } from "node:timers/promises"; +import { + AnalysisProtocolError, + AnalysisResourceConstraintError, +} from "../domain/analysisErrorCore.js"; +import { parseRecordedTransportUrl } from "../domain/recordedTransportUrl.js"; +import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js"; + +const OPERATION = "inspect_pcap_capture"; +/** Bounds JSON decoding plus its expanded object graph before JSON.parse. */ +export const TSHARK_JSON_MAX_BYTES = 8 * 1024 * 1024; +const MAX_RETAINED_BYTES = 16 * 1024 * 1024; +const MAX_DECODED_BYTES = 128 * 1024 * 1024; + +const protocolFailure = (reason: string): never => { + throw new AnalysisProtocolError(`Invalid packet-capture output: ${reason}`); +}; + +export interface CapinfosMetadata { + readonly fileType: string; + readonly encapsulation: string; + readonly packetCount: number; + readonly captureStart: string | null; + readonly captureEnd: string | null; + readonly captureDurationSeconds: number | null; + readonly snapshotLength: number | null; + readonly sha256: string | null; +} + +/** capinfos -M with a C locale provides exact numbers instead of "20 k". */ +export const parseCapinfosOutput = (stdout: string): CapinfosMetadata => { + const lines = new Map(); + for (const line of stdout.split(/\r?\n/u)) { + const at = line.indexOf(":"); + if (at >= 0 && !/^\s/u.test(line)) + lines.set(line.slice(0, at), line.slice(at + 1).trim()); + } + const fileType = lines.get("File type"); + const encapsulation = lines.get("File encapsulation"); + const countText = lines.get("Number of packets"); + if ( + !fileType || + !encapsulation || + countText === undefined || + !/^\d+$/u.test(countText) + ) + return protocolFailure( + "capinfos did not provide machine-readable type, encapsulation and packet count", + ); + const packetCount = Number(countText); + if (!Number.isSafeInteger(packetCount)) + return protocolFailure("packet count is not representable"); + const durationText = lines.get("Capture duration"); + const duration = + durationText === undefined + ? null + : /^(\d+(?:\.\d+)?)(?:\s+seconds?)?$/u.exec(durationText); + const snapshot = /^file hdr:\s*(\d+) bytes$/u.exec( + lines.get("Packet size limit") ?? "", + ); + const snapshotLength = snapshot === null ? null : Number(snapshot[1]); + const sha256 = lines.get("SHA256") ?? null; + if (sha256 !== null && !/^[0-9a-f]{64}$/u.test(sha256)) + return protocolFailure("capinfos SHA256 is malformed"); + return { + fileType, + encapsulation, + packetCount, + captureStart: lines.get("Earliest packet time") ?? null, + captureEnd: lines.get("Latest packet time") ?? null, + captureDurationSeconds: duration === null ? null : Number(duration[1]), + snapshotLength: + snapshotLength !== null && + Number.isSafeInteger(snapshotLength) && + snapshotLength > 0 + ? snapshotLength + : null, + sha256, + }; +}; + +export interface TsharkFields { + readonly endpoints: { address: string; port: null; packet_count: number }[]; + readonly endpointCount: number; + readonly dnsQueries: { + query: string; + response_addresses: string[]; + response_address_count: number; + }[]; + readonly dnsQueryCount: number; + readonly tlsSniValues: string[]; + readonly tlsSniCount: number; + readonly protocolDistribution: { protocol: string; packet_count: number }[]; + readonly protocolCount: number; + readonly httpRequestUris: string[]; + readonly httpRequestUriCount: number; + readonly httpUriRedactionCount: number; + readonly unattributedDnsAddresses: string[]; + readonly unattributedDnsAddressCount: number; + readonly unattributedDnsPackets: number; + readonly packetCount: number; + readonly partial: boolean; +} + +const object = (value: unknown): value is Record => + typeof value === "object" && value !== null && !Array.isArray(value); + +/** Validate the fixed JSON field representation before retaining aggregate facts. */ +export const parseTsharkJsonOutput = async ( + stdout: string, + signal?: AbortSignal, +): Promise => { + signal?.throwIfAborted(); + if (Buffer.byteLength(stdout) > TSHARK_JSON_MAX_BYTES) + throw new AnalysisResourceConstraintError( + OPERATION, + "memory", + "tshark JSON exceeds the bounded decoding budget", + { max_json_bytes: TSHARK_JSON_MAX_BYTES }, + ); + // The selected-field protocol has five container levels. Reject deeper + // graphs before materializing them; quoted brackets are string data. + let depth = 0, + quoted = false, + escaped = false; + let decodedBytes = stdout.length * 2; + for (let index = 0; index < stdout.length; index += 1) { + if (index % 65536 === 0) { + await yieldToEventLoop(); + signal?.throwIfAborted(); + } + const char = stdout[index]; + if (quoted) { + if (escaped) escaped = false; + else if (char === "\\") escaped = true; + else if (char === '"') quoted = false; + } else if (char === '"') { + quoted = true; + decodedBytes += 64; + } else if (char === "{" || char === "[") { + decodedBytes += 128; + if (++depth > 5) protocolFailure("unexpected JSON nesting"); + } else if (char === "}" || char === "]") depth -= 1; + else if (char === ":" || char === ",") decodedBytes += 128; + if (decodedBytes > MAX_DECODED_BYTES) + throw new AnalysisResourceConstraintError( + OPERATION, + "memory", + "tshark JSON expansion exceeds the decoding budget", + { max_decoded_bytes: MAX_DECODED_BYTES }, + ); + } + let packets: unknown; + try { + packets = JSON.parse(stdout) as unknown; + } catch (cause) { + throw new AnalysisProtocolError("tshark emitted malformed JSON", { cause }); + } + if (!Array.isArray(packets)) + return protocolFailure("tshark packet root must be an array"); + const endpoints = new Map(); + const dns = new Map>(); + const sni = new Set(); + const protocols = new Map(); + const uris = new Set(); + const observedUris = new Set(); + let uriRedactions = 0; + const unattributed = new Set(); + let unattributedPackets = 0; + let retainedBytes = 0; + const charge = (value: string): void => { + retainedBytes += 192 + 2 * Buffer.byteLength(value); + if (retainedBytes > MAX_RETAINED_BYTES) + throw new AnalysisResourceConstraintError( + OPERATION, + "memory", + "Packet inventory exceeds the retained-fact budget", + { max_retained_bytes: MAX_RETAINED_BYTES }, + ); + }; + const add = (set: Set, value: string): void => { + if (!set.has(value)) { + charge(value); + set.add(value); + } + }; + for (let index = 0; index < packets.length; index += 1) { + if (index % 256 === 0) { + await yieldToEventLoop(); + signal?.throwIfAborted(); + } + const packet: unknown = packets[index]; + if ( + !object(packet) || + !object(packet._source) || + !object(packet._source.layers) + ) + return protocolFailure( + `packet ${String(index + 1)} lacks _source.layers`, + ); + const layers = packet._source.layers; + for (const [key, value] of Object.entries(layers)) + if ( + !Array.isArray(value) || + !value.every((item) => typeof item === "string") + ) + return protocolFailure( + `packet ${String(index + 1)} field ${key} must be an array of strings`, + ); + const field = (name: string): readonly string[] => + (layers[name] as string[] | undefined) ?? []; + const frame = field("frame.number"); + if ( + frame.length !== 1 || + !/^\d+$/u.test(frame[0]!) || + Number(frame[0]) !== index + 1 + ) + return protocolFailure( + "frame inventory is missing, duplicated or out of order", + ); + if ( + field("frame.protocols").length !== 1 || + field("frame.protocols")[0] === "" + ) + return protocolFailure( + "packet protocol inventory is missing or ambiguous", + ); + // Count one occurrence per packet even for loopback or nested IP layers. + for (const address of new Set([ + ...field("ip.src"), + ...field("ip.dst"), + ...field("ipv6.src"), + ...field("ipv6.dst"), + ])) { + if (address === "") continue; + if (!endpoints.has(address)) charge(address); + endpoints.set(address, (endpoints.get(address) ?? 0) + 1); + } + const questions = new Set( + field("dns.qry.name").filter((value) => value !== ""), + ); + for (const question of questions) + if (!dns.has(question)) { + charge(question); + dns.set(question, new Set()); + } + const addresses = [...field("dns.a"), ...field("dns.aaaa")].filter( + (value) => value !== "", + ); + const response = field("dns.flags.response"); + if (addresses.length > 0) { + if ( + questions.size === 1 && + response.length > 0 && + response.every((value) => value === "True" || value === "1") + ) { + const values = dns.get(questions.values().next().value!)!; + for (const address of addresses) add(values, address); + } else { + unattributedPackets += 1; + for (const address of addresses) add(unattributed, address); + } + } + for (const value of field("tls.handshake.extensions_server_name")) + if (value !== "") add(sni, value); + for (const value of new Set(field("frame.protocols"))) { + if (value === "") continue; + if (!protocols.has(value)) charge(value); + protocols.set(value, (protocols.get(value) ?? 0) + 1); + } + for (const value of field("http.request.full_uri")) { + if (value === "" || observedUris.has(value)) continue; + add(observedUris, value); + const { credentials } = parseRecordedTransportUrl(value); + if (credentials !== null) uriRedactions += 1; + if (credentials === "ambiguous") continue; + add( + uris, + credentials === null + ? value + : value.slice(0, credentials.start) + value.slice(credentials.end), + ); + } + } + signal?.throwIfAborted(); + return { + endpoints: [...endpoints] + .sort((a, b) => b[1] - a[1] || compareUnicodeCodePoints(a[0], b[0])) + .map(([address, packet_count]) => ({ + address, + port: null, + packet_count, + })), + endpointCount: endpoints.size, + dnsQueries: [...dns].map(([query, addresses]) => ({ + query, + response_addresses: [...addresses], + response_address_count: addresses.size, + })), + dnsQueryCount: dns.size, + tlsSniValues: [...sni], + tlsSniCount: sni.size, + protocolDistribution: [...protocols] + .sort((a, b) => b[1] - a[1] || compareUnicodeCodePoints(a[0], b[0])) + .map(([protocol, packet_count]) => ({ protocol, packet_count })), + protocolCount: protocols.size, + httpRequestUris: [...uris], + httpRequestUriCount: observedUris.size, + httpUriRedactionCount: uriRedactions, + unattributedDnsAddresses: [...unattributed], + unattributedDnsAddressCount: unattributed.size, + unattributedDnsPackets: unattributedPackets, + packetCount: packets.length, + partial: observedUris.size > uris.size || unattributedPackets > 0, + }; +}; diff --git a/src/pcap/PcapProvider.ts b/src/pcap/PcapProvider.ts new file mode 100644 index 000000000..be2c12ed2 --- /dev/null +++ b/src/pcap/PcapProvider.ts @@ -0,0 +1,491 @@ +import type { + ExecutionOptions, + ProviderAvailability, +} from "../application/AnalysisProvider.js"; +import { + createAnalysisExecution, + type AnalysisExecution, +} from "../application/AnalysisProvider.js"; +import { + pcapResultSchemas, + type PcapRequest, + type PcapOperation, +} from "../domain/pcap/pcapAnalysis.js"; +import { + AnalysisCancelledError, + AnalysisCapabilityUnavailableError, + AnalysisProtocolError, +} from "../domain/analysisErrorCore.js"; +import { AnalysisError } from "../domain/analysisErrorBase.js"; +import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; +import { err, ok, type Result } from "../domain/result.js"; +import type { ProviderProcessSupervisor } from "../process/ProviderProcess.js"; +import { + PcapConfigurationFailure, + inspectPcapClient, + resolvePcapTools, + pcapConfigurationAvailability, + pcapToolUnavailable, + type PcapToolSelection, +} from "./PcapConfiguration.js"; +import { + parseCapinfosOutput, + parseTsharkJsonOutput, + TSHARK_JSON_MAX_BYTES, +} from "./PcapOutput.js"; +import { runPcapCommand, type PcapCommandLimits } from "./PcapCommand.js"; +import { ProviderCleanupError } from "../domain/providerCleanupError.js"; +import { createPcapEvidence } from "../domain/pcap/pcapEvidence.js"; +import { preparePcapNativeBound } from "./PcapNativeBound.js"; +import { PcapSnapshot } from "./PcapSnapshot.js"; +import { readStableArtifact } from "../artifacts/readStableArtifact.js"; +import { ArtifactAnalysisResources } from "../process/ArtifactAnalysisResources.js"; +import { readLinuxResourceLimits } from "../process/LinuxResourceLimits.js"; + +export const PCAP_PROVIDER_IDENTITY = { + id: "pcap", + name: "Packet capture analysis", + version: null, +} as const; +const FIELDS = [ + "frame.number", + "frame.protocols", + "ip.src", + "ip.dst", + "ipv6.src", + "ipv6.dst", + "dns.flags.response", + "dns.qry.name", + "dns.a", + "dns.aaaa", + "tls.handshake.extensions_server_name", + "http.request.full_uri", +]; + +export interface PcapProviderOptions { + readonly environment?: Readonly>; +} + +/** Inspect saved captures through bounded, owned tool processes and one stable input copy. */ +export class PcapProvider { + readonly #resources = new ArtifactAnalysisResources( + "pcap", + "inspect_pcap_capture", + readStableArtifact, + readLinuxResourceLimits, + { + message: "A packet summary is already active; retry after it completes.", + details: { max_concurrent_inspections: 1 }, + }, + ); + private readonly environment: Readonly>; + private readonly snapshots = new Set(); + private readonly commands = new Map< + ProviderProcessSupervisor, + { snapshot: PcapSnapshot | undefined; resources: readonly string[] } + >(); + + constructor(options: PcapProviderOptions = {}) { + this.environment = options.environment ?? process.env; + } + + private run( + operation: PcapOperation, + command: string, + args: readonly string[], + limits: PcapCommandLimits, + signal: AbortSignal | undefined, + snapshot?: PcapSnapshot, + inputPath?: string, + ) { + return runPcapCommand({ + operation, + command, + arguments: args, + limits, + signal, + environment: + snapshot === undefined + ? this.environment + : { + ...this.environment, + WIRESHARK_CONFIG_DIR: snapshot.configurationPath, + }, + ...(inputPath === undefined ? {} : { inputPath }), + ...(inputPath === undefined || this.nativeBound === undefined + ? {} + : { nativeBound: this.nativeBound }), + retain: (owner, resources) => { + this.commands.set(owner, { snapshot, resources }); + }, + }); + } + + private nativeBound: Parameters[0]["nativeBound"]; + private nativeLimitations: readonly string[] = []; + + private async prepareCaptureBound(): Promise { + const prepared = await preparePcapNativeBound( + this.environment, + this.#resources, + ); + this.nativeBound = prepared.nativeBound; + this.nativeLimitations = prepared.limitations; + } + + private async client(operation: PcapOperation, signal?: AbortSignal) { + const selection = resolvePcapTools(this.environment); + const identity = await inspectPcapClient( + selection, + async (command) => + ( + await this.run( + operation, + command, + ["--version"], + { timeoutMs: 20_000, maxOutputBytes: 64 * 1024 }, + signal, + ) + ).stdout, + ); + for (const [name, version] of [ + ["tshark", identity.tsharkVersion], + ["capinfos", identity.capinfosVersion], + ] as const) { + if (version === null) + throw new PcapConfigurationFailure( + `${name}_version_unresolved`, + `The selected ${name} command did not report a version. Set REA_${name.toUpperCase()}_COMMAND to its absolute executable path.`, + ); + } + return { + selection, + client: { + tshark_command: selection.tshark.command, + tshark_source: selection.tshark.source, + tshark_version: identity.tsharkVersion, + capinfos_command: selection.capinfos.command, + capinfos_source: selection.capinfos.source, + capinfos_version: identity.capinfosVersion, + }, + }; + } + + async inspectAvailability( + signal?: AbortSignal, + ): Promise { + const result = await this.#resources.run( + async () => ok(await this.inspectAvailabilityAdmitted(signal)), + signal, + ); + if (!result.ok) throw result.error; + return result.value; + } + + private async inspectAvailabilityAdmitted( + signal?: AbortSignal, + ): Promise { + try { + const { client } = await this.client("inspect_pcap_client", signal); + if (process.platform !== "linux" && process.platform !== "win32") + return { + status: "unavailable", + code: "unsupported_host", + reason: + "No enforceable native memory boundary is available for capture summaries on this host.", + diagnostics: client, + }; + await this.prepareCaptureBound(); + return { + status: "available", + code: null, + reason: null, + diagnostics: client, + }; + } catch (cause) { + if (signal?.aborted || cause instanceof AnalysisCancelledError) + throw new AnalysisCancelledError("inspect_pcap_client", { cause }); + if (cause instanceof PcapConfigurationFailure) + return pcapConfigurationAvailability(cause); + return { + status: "unavailable", + code: + cause instanceof AnalysisCapabilityUnavailableError + ? "executable_missing" + : "version_unresolved", + reason: cause instanceof Error ? cause.message : String(cause), + diagnostics: {}, + }; + } + } + + private async discard( + snapshot: PcapSnapshot, + ): Promise { + try { + if ( + [...this.commands.values()].some( + (command) => command.snapshot === snapshot, + ) + ) + throw new Error( + "An unreleased command still owns the capture snapshot", + ); + await snapshot.close(); + this.snapshots.delete(snapshot); + return undefined; + } catch (cause) { + return new ProviderCleanupError( + "pcap", + [snapshot.path], + { reason: String(cause) }, + { operation: "inspect_pcap_capture", cause }, + ); + } + } + + async close(): Promise { + const failures: unknown[] = []; + try { + await this.#resources.close(); + } catch (cause) { + failures.push(cause); + } + for (const owner of this.commands.keys()) { + try { + const result = await owner.stop(); + if (result.status === "incomplete") failures.push(result.reason); + else if (result.status === "not-owned") + failures.push("Command ownership remains unresolved"); + else this.commands.delete(owner); + } catch (cause) { + failures.push(cause); + } + } + for (const snapshot of this.snapshots) { + const failure = await this.discard(snapshot); + if (failure !== undefined) failures.push(failure); + } + if (failures.length > 0) + throw new ProviderCleanupError( + "pcap", + [...this.snapshots] + .map((snapshot) => snapshot.path) + .concat( + [...this.commands.values()].flatMap((command) => command.resources), + ), + { reason: "Owned process or snapshot cleanup failed" }, + { operation: "pcap.close", cause: new AggregateError(failures) }, + ); + } + + async execute( + request: PcapRequest, + options?: ExecutionOptions, + ): Promise> { + return this.#resources.run( + () => this.executeAdmitted(request, options), + options?.signal, + ); + } + + private async executeAdmitted( + request: PcapRequest, + options?: ExecutionOptions, + ): Promise> { + const signal = options?.signal; + let snapshot: PcapSnapshot | undefined; + let result: Result; + try { + signal?.throwIfAborted(); + const { selection, client } = await this.client( + request.operation, + signal, + ); + const provider = { + ...PCAP_PROVIDER_IDENTITY, + version: client.tshark_version, + }; + if (request.operation === "inspect_pcap_client") + result = ok( + createAnalysisExecution( + pcapResultSchemas.inspect_pcap_client.parse({ client }), + provider, + ), + ); + else { + await this.prepareCaptureBound(); + snapshot = await PcapSnapshot.create(); + this.snapshots.add(snapshot); + const identity = await snapshot.capture(request.input.path, signal); + const captured = await this.inspectCapture( + selection, + snapshot, + request.input.path, + identity, + signal, + ); + const data = pcapResultSchemas.inspect_pcap_capture.parse({ + client, + ...captured.result, + }); + result = ok( + createAnalysisExecution(data, provider, { + subject: { + path: request.input.path, + format: "file", + sha256: identity.sha256, + }, + limitations: captured.limitations, + }), + ); + } + } catch (cause) { + result = err( + cause instanceof AnalysisError + ? cause + : signal?.aborted + ? new AnalysisCancelledError(request.operation, { cause }) + : cause instanceof PcapConfigurationFailure + ? pcapToolUnavailable(request.operation, cause.message, { + cause, + }) + : new AnalysisProtocolError( + `Packet-capture analysis failed: ${cause instanceof Error ? cause.message : String(cause)}`, + { cause }, + ), + ); + } + if (signal?.aborted && result.ok) + result = err( + new AnalysisCancelledError(request.operation, { + cause: signal.reason, + partialObservation: createPcapEvidence(request, result.value), + }), + ); + if (snapshot !== undefined) { + const cleanup = await this.discard(snapshot); + if (signal?.aborted && result.ok) + result = err( + new AnalysisCancelledError(request.operation, { + cause: signal.reason, + partialObservation: createPcapEvidence(request, result.value), + }), + ); + if (cleanup !== undefined) + result = result.ok + ? err( + cleanup.retainPartialObservation( + createPcapEvidence(request, result.value), + ), + ) + : err( + analysisErrorWithCleanupFailure( + result.error, + cleanup, + request.operation, + ), + ); + } + return result; + } + + private async inspectCapture( + selection: PcapToolSelection, + snapshot: PcapSnapshot, + path: string, + identity: { bytes: number; sha256: string }, + signal: AbortSignal | undefined, + ) { + const info = await this.run( + "inspect_pcap_capture", + selection.capinfos.command, + ["-M", "--", snapshot.path], + { timeoutMs: 60_000, maxOutputBytes: 64 * 1024 }, + signal, + snapshot, + path, + ); + const metadata = parseCapinfosOutput(info.stdout); + if (metadata.sha256 !== null && metadata.sha256 !== identity.sha256) + throw new AnalysisProtocolError( + "capinfos SHA256 disagrees with the owned capture snapshot", + ); + const dissected = await this.run( + "inspect_pcap_capture", + selection.tshark.command, + [ + "-n", + "-r", + snapshot.path, + "-T", + "json", + "--no-duplicate-keys", + `--temp-dir=${snapshot.configurationPath}`, + ...FIELDS.flatMap((field) => ["-e", field]), + ], + { timeoutMs: 300_000, maxOutputBytes: TSHARK_JSON_MAX_BYTES }, + signal, + snapshot, + path, + ); + const fields = await parseTsharkJsonOutput(dissected.stdout, signal); + await snapshot.verify(identity, path, signal); + if (fields.packetCount !== metadata.packetCount) + throw new AnalysisProtocolError( + `capinfos counted ${String(metadata.packetCount)} packets but tshark returned ${String(fields.packetCount)}`, + ); + return { + result: { + target: { path, ...identity }, + file_type: metadata.fileType, + encapsulation: metadata.encapsulation, + packet_count: metadata.packetCount, + capture_start: metadata.captureStart, + capture_end: metadata.captureEnd, + capture_duration_seconds: metadata.captureDurationSeconds, + diagnostics: { + capinfos_stderr: info.stderr, + tshark_stderr: dissected.stderr, + }, + snapshot_length: metadata.snapshotLength, + endpoints: fields.endpoints, + endpoint_count: fields.endpointCount, + dns_queries: fields.dnsQueries, + dns_query_count: fields.dnsQueryCount, + tls_sni_values: fields.tlsSniValues, + tls_sni_count: fields.tlsSniCount, + protocol_distribution: fields.protocolDistribution, + protocol_count: fields.protocolCount, + http_request_uris: fields.httpRequestUris, + http_request_uri_count: fields.httpRequestUriCount, + http_uri_redaction_count: fields.httpUriRedactionCount, + unattributed_dns_addresses: fields.unattributedDnsAddresses, + unattributed_dns_address_count: fields.unattributedDnsAddressCount, + unattributed_dns_packet_count: fields.unattributedDnsPackets, + coverage: fields.partial ? "partial" : "complete", + }, + limitations: [ + ...this.nativeLimitations, + "Both tools read one owned snapshot; target identity comes from its admitted source descriptor", + "DNS address values are associated only with a single question in the same response packet; values may include additional DNS records, not only final resolution answers", + "Only bytes present in the saved capture are examined; encryption and capture truncation can hide higher-level fields", + ...(fields.partial + ? [ + "One or more projected categories were capped, credential-bearing URIs were omitted or coalesced, or DNS address attribution remains unresolved; counts retain the examined totals", + ] + : []), + ...(fields.httpUriRedactionCount > 0 + ? [ + "HTTP transport credentials were excluded; ambiguous credential spans cause the URI to be omitted", + ] + : []), + ...(fields.unattributedDnsPackets > 0 + ? [ + `DNS address attribution was unresolved in ${String(fields.unattributedDnsPackets)} packet(s); unattributed addresses are retained separately`, + ] + : []), + ], + }; + } +} diff --git a/src/pcap/PcapSnapshot.ts b/src/pcap/PcapSnapshot.ts new file mode 100644 index 000000000..2e9082ccd --- /dev/null +++ b/src/pcap/PcapSnapshot.ts @@ -0,0 +1,269 @@ +import { createHash } from "node:crypto"; +import { chmod, open, stat, mkdir } from "node:fs/promises"; +import { join } from "node:path"; +import { AnalysisError } from "../domain/analysisErrorBase.js"; +import { + AnalysisAccessDeniedError, + AnalysisArtifactChangedError, + AnalysisCancelledError, + AnalysisCapabilityUnavailableError, + AnalysisInputError, + AnalysisResourceConstraintError, +} from "../domain/analysisErrorCore.js"; +import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js"; +import { + openRegularFile, + RegularFileAdmissionFailure, + sameRegularFileState, +} from "../filesystem/RegularFile.js"; +import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRootUnavailableError } from "../process/PrivateRuntimeRootUnavailableError.js"; + +const OPERATION = "inspect_pcap_capture"; +const MAX_CAPTURE_BYTES = 2 * 1024 ** 3; + +/** An owned capture copy and every descriptor needed to release it safely. */ +export class PcapSnapshot { + private readonly handles = new Set(); + readonly path: string; + readonly configurationPath: string; + private constructor(private readonly root: PrivateRuntimeRoot) { + this.path = join(root.path, "capture.pcap"); + this.configurationPath = join(root.path, "configuration"); + } + + static async create(): Promise { + try { + return new PcapSnapshot( + await PrivateRuntimeRoot.create({ prefix: "rea-pcap-" }), + ); + } catch (cause) { + if (cause instanceof PrivateRuntimeRootUnavailableError) + throw new AnalysisCapabilityUnavailableError( + "pcap", + OPERATION, + cause.message, + { cause, retryable: cause.retryable }, + ); + throw new AnalysisResourceConstraintError( + OPERATION, + "file-size", + "Cannot allocate the owned capture workspace", + null, + { cause }, + ); + } + } + + private own(handle: OwnedFileHandle): OwnedFileHandle { + this.handles.add(handle); + return handle; + } + private async release(handle: OwnedFileHandle): Promise { + await handle.close(); + this.handles.delete(handle); + } + + async capture( + path: string, + signal?: AbortSignal, + ): Promise<{ bytes: number; sha256: string }> { + const sourceRead = async (read: () => Promise): Promise => { + try { + return await read(); + } catch (cause) { + if (signal?.aborted) + throw new AnalysisCancelledError(OPERATION, { cause }); + if (cause instanceof AnalysisError) throw cause; + if ( + cause instanceof Error && + "code" in cause && + (cause.code === "EACCES" || cause.code === "EPERM") + ) + throw new AnalysisAccessDeniedError(OPERATION, path, cause.code, { + cause, + }); + throw new AnalysisInputError(OPERATION, { cause }, [ + { + path: ["path"], + reason: "invalid_value", + message: `Cannot read selected capture ${path}: ${cause instanceof Error ? cause.message : String(cause)}`, + }, + ]); + } + }; + try { + signal?.throwIfAborted(); + await mkdir(this.configurationPath, { mode: 0o700 }); + const source = await sourceRead(async () => { + try { + return this.own( + new OwnedFileHandle( + await openRegularFile(path, { symlinks: "follow", signal }), + ), + ); + } catch (cause) { + if (cause instanceof RegularFileAdmissionFailure) { + this.own(cause.owner); + throw cause.cause; + } + throw cause; + } + }); + const before = await sourceRead(() => + source.handle.stat({ bigint: true }), + ); + if (before.size > BigInt(MAX_CAPTURE_BYTES)) + throw new AnalysisResourceConstraintError( + OPERATION, + "file-size", + "Capture exceeds the owned-snapshot disk budget", + { max_capture_bytes: MAX_CAPTURE_BYTES }, + ); + const destination = this.own( + new OwnedFileHandle(await open(this.path, "wx", 0o600)), + ); + const buffer = Buffer.alloc(64 * 1024); + const hash = createHash("sha256"); + let copied = 0; + while (copied <= Number(before.size)) { + signal?.throwIfAborted(); + const { bytesRead } = await sourceRead(() => + source.handle.read( + buffer, + 0, + Math.min(buffer.length, Number(before.size) - copied + 1), + copied, + ), + ); + signal?.throwIfAborted(); + if (bytesRead === 0) break; + copied += bytesRead; + if (BigInt(copied) > before.size) + throw new AnalysisArtifactChangedError( + OPERATION, + path, + "Capture grew during acquisition", + ); + const chunk = buffer.subarray(0, bytesRead); + await destination.handle.writeFile(chunk); + hash.update(chunk); + } + const after = await sourceRead(() => + source.handle.stat({ bigint: true }), + ); + const selected = await stat(path, { bigint: true }).catch( + (cause: unknown) => { + if ( + cause instanceof Error && + "code" in cause && + (cause.code === "EACCES" || cause.code === "EPERM") + ) + throw new AnalysisAccessDeniedError(OPERATION, path, cause.code, { + cause, + }); + throw new AnalysisArtifactChangedError( + OPERATION, + path, + "Selected path became unavailable during acquisition", + { cause }, + ); + }, + ); + if ( + BigInt(copied) !== before.size || + !sameRegularFileState(before, after) || + !sameRegularFileState(before, selected) + ) + throw new AnalysisArtifactChangedError( + OPERATION, + path, + "Capture identity or contents changed during acquisition", + ); + await this.release(source); + await this.release(destination); + await chmod(this.path, 0o400); + signal?.throwIfAborted(); + return { bytes: copied, sha256: hash.digest("hex") }; + } catch (cause) { + if (signal?.aborted) + throw new AnalysisCancelledError(OPERATION, { cause }); + if (cause instanceof AnalysisError) throw cause; + throw new AnalysisResourceConstraintError( + OPERATION, + "file-size", + "Owned capture snapshot I/O failed", + null, + { cause }, + ); + } + } + + /** Recheck byte identity after both tools; a read-only mode alone is not proof. */ + async verify( + expected: { bytes: number; sha256: string }, + selectedPath: string, + signal?: AbortSignal, + ): Promise { + try { + const file = this.own( + new OwnedFileHandle( + await openRegularFile(this.path, { symlinks: "reject", signal }), + ), + ); + const before = await file.handle.stat({ bigint: true }); + const buffer = Buffer.alloc(64 * 1024); + const hash = createHash("sha256"); + let bytes = 0; + while (bytes <= expected.bytes) { + signal?.throwIfAborted(); + const read = await file.handle.read( + buffer, + 0, + Math.min(buffer.length, expected.bytes - bytes + 1), + bytes, + ); + if (read.bytesRead === 0) break; + bytes += read.bytesRead; + hash.update(buffer.subarray(0, read.bytesRead)); + } + const after = await file.handle.stat({ bigint: true }); + const selected = await stat(this.path, { bigint: true }); + if ( + bytes !== expected.bytes || + hash.digest("hex") !== expected.sha256 || + !sameRegularFileState(before, after) || + !sameRegularFileState(before, selected) + ) + throw new AnalysisArtifactChangedError( + OPERATION, + selectedPath, + "Owned packet snapshot changed during tool analysis.", + ); + await this.release(file); + } catch (cause) { + if (signal?.aborted) + throw new AnalysisCancelledError(OPERATION, { cause }); + if (cause instanceof RegularFileAdmissionFailure) this.own(cause.owner); + if (cause instanceof AnalysisError) throw cause; + throw new AnalysisArtifactChangedError( + OPERATION, + selectedPath, + "Cannot establish the owned packet snapshot's post-analysis identity.", + { cause }, + ); + } + } + + async close(): Promise { + const results = await Promise.allSettled( + [...this.handles].map((handle) => this.release(handle)), + ); + const failures = results.flatMap((result) => + result.status === "rejected" ? [result.reason as unknown] : [], + ); + if (failures.length > 0) + throw new AggregateError(failures, "Capture descriptor cleanup failed"); + await this.root.close(); + } +} diff --git a/src/process/ArtifactAnalysisResources.ts b/src/process/ArtifactAnalysisResources.ts index 5eb90b8e2..b0083e05b 100644 --- a/src/process/ArtifactAnalysisResources.ts +++ b/src/process/ArtifactAnalysisResources.ts @@ -36,7 +36,10 @@ export class ArtifactAnalysisResources { readonly #artifacts = new ArtifactResourceScope(); readonly #pending = new Map< ArtifactAnalysisRuntime, - ProviderProcessSupervisor | undefined + { + readonly owner: ProviderProcessSupervisor | undefined; + readonly operation: string; + } >(); #tail: Promise = Promise.resolve(); #busy = false; @@ -56,14 +59,15 @@ export class ArtifactAnalysisResources { run( work: () => Promise>, signal?: AbortSignal, + operation = this.operation, ): Promise> { if (this.#closed || signal?.aborted) - return Promise.resolve(err(new AnalysisCancelledError(this.operation))); + return Promise.resolve(err(new AnalysisCancelledError(operation))); if (this.#busy) return Promise.resolve( err( new AnalysisResourceConstraintError( - this.operation, + operation, "capacity", this.capacity.message, this.capacity.details, @@ -73,7 +77,7 @@ export class ArtifactAnalysisResources { this.#busy = true; const running = this.#tail .then(() => this.#artifacts.run(work)) - .catch((cause: unknown) => err(this.#artifactFailure(cause))) + .catch((cause: unknown) => err(this.#artifactFailure(cause, operation))) .finally(() => { this.#busy = false; }); @@ -101,8 +105,9 @@ export class ArtifactAnalysisResources { retain( root: ArtifactAnalysisRuntime, owner?: ProviderProcessSupervisor, + operation = this.operation, ): void { - this.#pending.set(root, owner); + this.#pending.set(root, { owner, operation }); } get pendingPaths(): readonly string[] { @@ -110,12 +115,13 @@ export class ArtifactAnalysisResources { } async release(): Promise { - for (const [root, owner] of this.#pending) { + for (const [root, retained] of this.#pending) { try { + const { owner } = retained; if (owner !== undefined) { const stopped = await owner.stop(); if (stopped.status === "incomplete") throw new Error(stopped.reason); - this.#pending.set(root, undefined); + this.#pending.set(root, { ...retained, owner: undefined }); } await root.close(); this.#pending.delete(root); @@ -124,7 +130,7 @@ export class ArtifactAnalysisResources { this.providerId, [root.path], { reason: String(cause) }, - { operation: this.operation, cause }, + { operation: retained.operation, cause }, ); } } @@ -134,6 +140,7 @@ export class ArtifactAnalysisResources { observation: NonNullable, cause: unknown, capturedOutput?: AnalysisCapturedOutput, + operation = this.operation, ): ProviderCleanupError { return new ProviderCleanupError( this.providerId, @@ -144,7 +151,7 @@ export class ArtifactAnalysisResources { ? {} : { captured_output: { ...capturedOutput } }), }, - { operation: this.operation, cause }, + { operation, cause }, ); } @@ -155,6 +162,7 @@ export class ArtifactAnalysisResources { readonly output_bytes: number; }, effectiveLimits: LinuxResourceLimits | undefined, + operation = this.operation, ): AnalysisError { const capturedOutput = cause.snapshot === null @@ -171,16 +179,16 @@ export class ArtifactAnalysisResources { ...(capturedOutput === undefined ? {} : { capturedOutput }), }; if (cause.reason === "cancelled") - return new AnalysisCancelledError(this.operation, detail); + return new AnalysisCancelledError(operation, detail); if (cause.reason === "timeout") return new AnalysisTimeoutError( - this.operation, + operation, limits.command_timeout_ms, detail, ); if (cause.reason === "output-limit") return new AnalysisResourceConstraintError( - this.operation, + operation, "memory", cause.message, { output_bytes: limits.output_bytes }, @@ -192,18 +200,19 @@ export class ArtifactAnalysisResources { cause.snapshot?.signal === "SIGXCPU") ) return new AnalysisResourceConstraintError( - this.operation, + operation, cause.snapshot.signal === "SIGXFSZ" ? "file-size" : "cpu", `Producer terminated with ${cause.snapshot.signal}; the signal's exact cause is not independently established.`, effectiveLimits === undefined ? null : { ...effectiveLimits }, detail, ); - return new AnalysisOutputError(this.operation, cause.message, detail); + return new AnalysisOutputError(operation, cause.message, detail); } async finish( result: Result, observation: (value: T) => AnalysisPartialObservation, + operation = this.operation, ): Promise> { try { await this.release(); @@ -223,7 +232,7 @@ export class ArtifactAnalysisResources { : projectAnalysisError(result.error), }, { - operation: this.operation, + operation, cause, ...(partialObservation === undefined ? {} : { partialObservation }), }, @@ -260,11 +269,11 @@ export class ArtifactAnalysisResources { if (descriptorFailure !== undefined) throw descriptorFailure; } - #artifactFailure(cause: unknown): AnalysisError { + #artifactFailure(cause: unknown, operation = this.operation): AnalysisError { if (cause instanceof AnalysisError) return cause; if (cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined) - return this.cleanupFailure(cause.cleanup, cause); - return new ProviderAdapterError(this.providerId, this.operation, { + return this.cleanupFailure(cause.cleanup, cause, undefined, operation); + return new ProviderAdapterError(this.providerId, operation, { cause, diagnostics: { stage: "artifact-resources", reason: String(cause) }, }); diff --git a/src/process/DarwinProcessRunTokenReader.ts b/src/process/DarwinProcessRunTokenReader.ts index 5aafcd787..335e72fbe 100644 --- a/src/process/DarwinProcessRunTokenReader.ts +++ b/src/process/DarwinProcessRunTokenReader.ts @@ -74,7 +74,9 @@ const sourceFiles = [ export const SWIFTC_INTERRUPT = "SIGINT"; /** Deadline for the one-shot helper compilation. */ -const COMPILER_TIMEOUT_MS = 60_000; +// A fresh Swift SDK cache took 88 seconds on the supported Intel macOS VM. +// Keep compilation bounded independently of short provider version probes. +const COMPILER_TIMEOUT_MS = 120_000; /** Bound on compiler diagnostics embedded in the inspection failure text. */ const STDERR_EXCERPT_LIMIT = 512; @@ -253,7 +255,7 @@ export type DarwinProcessReaderCompiler = export const createDarwinProcessRunTokenReader = ( options: { readonly compiler?: DarwinProcessReaderCompiler; - /** Deadline for the helper compilation; the default keeps verification fast. */ + /** Deadline for helper compilation, independent of provider execution. */ readonly compileTimeoutMs?: number; /** * Caller-owned directory holding the compiler's module cache. Unset keeps diff --git a/src/process/PrivateRuntimeRoot.ts b/src/process/PrivateRuntimeRoot.ts index 7002e2f65..c319df0de 100644 --- a/src/process/PrivateRuntimeRoot.ts +++ b/src/process/PrivateRuntimeRoot.ts @@ -3,6 +3,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { WindowsPrivateRuntime } from "../windows/WindowsPrivateRuntime.js"; +import { PrivateRuntimeRootUnavailableError } from "./PrivateRuntimeRootUnavailableError.js"; import { windowsNativeCapabilities, @@ -34,16 +35,6 @@ export const privateRuntimeRootCapability = ( ? windowsNativeCapabilities(platform).private_runtime_dacl : { available: true, reason: null, proof: "posix-mkdtemp-owner-only" }; -/** Expected failure when a runtime root's privacy boundary is unavailable. */ -export class PrivateRuntimeRootUnavailableError extends Error { - readonly code = "private-runtime-root-authority-unavailable"; - - constructor(message: string) { - super(message); - this.name = "PrivateRuntimeRootUnavailableError"; - } -} - /** * Owns a private temporary runtime root and removes it idempotently. * @@ -66,7 +57,9 @@ export class PrivateRuntimeRoot { const platform = options.platform ?? process.platform; const capability = privateRuntimeRootCapability(platform); if (!capability.available) - throw new PrivateRuntimeRootUnavailableError(capability.reason); + throw new PrivateRuntimeRootUnavailableError(capability.reason, { + retryable: capability.retryable === true, + }); if (platform === "win32") { const runtime = WindowsPrivateRuntime.create( options.parent ?? tmpdir(), diff --git a/src/process/PrivateRuntimeRootUnavailableError.ts b/src/process/PrivateRuntimeRootUnavailableError.ts new file mode 100644 index 000000000..27e7ae49d --- /dev/null +++ b/src/process/PrivateRuntimeRootUnavailableError.ts @@ -0,0 +1,14 @@ +/** Expected failure when a runtime root's privacy boundary is unavailable. */ +export class PrivateRuntimeRootUnavailableError extends Error { + readonly code = "private-runtime-root-authority-unavailable"; + readonly retryable: boolean; + + constructor( + message: string, + options?: ErrorOptions & { readonly retryable?: boolean }, + ) { + super(message, options); + this.name = "PrivateRuntimeRootUnavailableError"; + this.retryable = options?.retryable ?? false; + } +} diff --git a/src/process/ProviderDeadline.test.ts b/src/process/ProviderDeadline.test.ts new file mode 100644 index 000000000..b43ce6654 --- /dev/null +++ b/src/process/ProviderDeadline.test.ts @@ -0,0 +1,35 @@ +import { afterEach, expect, it, vi } from "vitest"; +import { ProviderStartupDeadline } from "./ProviderDeadline.js"; + +afterEach(() => { + vi.restoreAllMocks(); +}); + +it("keeps remaining time and cancellation classification stable across wall-clock jumps", () => { + const dateNow = vi.spyOn(Date, "now").mockReturnValue(10_000); + const caller = new AbortController(); + const deadline = new ProviderStartupDeadline(10_000, caller.signal); + try { + dateNow.mockReturnValue(9_000_000_000_000); + const remaining = deadline.remainingMs(); + expect(remaining).toBeGreaterThan(0); + expect(remaining).toBeLessThanOrEqual(10_000); + expect(Number.isInteger(remaining)).toBe(true); + expect(deadline.interruption).toBeUndefined(); + caller.abort(new Error("caller stopped startup")); + expect(deadline.interruption).toBe("cancelled"); + } finally { + deadline.dispose(); + } +}); + +it("aborts a bounded wait when its real monotonic deadline expires", async () => { + const deadline = new ProviderStartupDeadline(40); + try { + await expect(deadline.wait(500)).resolves.toBe("aborted"); + expect(deadline.interruption).toBe("timeout"); + expect(deadline.remainingMs()).toBe(0); + } finally { + deadline.dispose(); + } +}); diff --git a/src/process/ProviderDeadline.ts b/src/process/ProviderDeadline.ts index 3081f469f..33cb3a8d0 100644 --- a/src/process/ProviderDeadline.ts +++ b/src/process/ProviderDeadline.ts @@ -42,11 +42,11 @@ export class ProviderStartupDeadline { ) { if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) throw new RangeError("Provider startup timeout must be positive"); - this.#deadlineAt = Date.now() + timeoutMs; + this.#deadlineAt = performance.now() + timeoutMs; this.#externalSignal = signal; this.#onExternalAbort = () => { if (this.#controller.signal.aborted) return; - if (Date.now() >= this.#deadlineAt) { + if (performance.now() >= this.#deadlineAt) { this.#interruption = "timeout"; this.#abort( new DOMException("Provider startup deadline elapsed", "TimeoutError"), @@ -79,13 +79,13 @@ export class ProviderStartupDeadline { get interruption(): "cancelled" | "timeout" | undefined { return ( this.#interruption ?? - (Date.now() >= this.#deadlineAt ? "timeout" : undefined) + (performance.now() >= this.#deadlineAt ? "timeout" : undefined) ); } /** Milliseconds still available to the next startup phase. */ remainingMs(): number { - return Math.max(0, this.#deadlineAt - Date.now()); + return Math.max(0, Math.ceil(this.#deadlineAt - performance.now())); } /** Wait for at most one polling interval under the shared deadline signal. */ diff --git a/src/process/WindowsAuthority.ts b/src/process/WindowsAuthority.ts index ccd041312..b25a22863 100644 --- a/src/process/WindowsAuthority.ts +++ b/src/process/WindowsAuthority.ts @@ -11,6 +11,7 @@ export type WindowsNativeCapability = readonly available: false; readonly reason: string; readonly proof: "not-proven" | "not-applicable"; + readonly retryable?: true; }; /** Security controls required before REA may claim Windows isolation. */ @@ -52,6 +53,7 @@ export const windowsNativeCapabilities = ( available: false, reason: loaded.reason, proof: "not-proven", + ...(loaded.retryable === true ? { retryable: true as const } : {}), } as const); return { job_object_process_ownership: capability, diff --git a/src/process/capture/ProcessCaptureClock.ts b/src/process/capture/ProcessCaptureClock.ts new file mode 100644 index 000000000..1fe9fda0a --- /dev/null +++ b/src/process/capture/ProcessCaptureClock.ts @@ -0,0 +1,3 @@ +/** Keep wall-clock timestamps separate from capture-relative elapsed time. */ +export const monotonicProcessCaptureClock = (): number => + Math.floor(performance.now()); diff --git a/src/process/capture/ProcessCaptureJournal.ts b/src/process/capture/ProcessCaptureJournal.ts index b8a0874d9..07c1f0351 100644 --- a/src/process/capture/ProcessCaptureJournal.ts +++ b/src/process/capture/ProcessCaptureJournal.ts @@ -13,6 +13,7 @@ import type { ProcessCaptureEventJournalEntry, RecordProcessCaptureEvent, } from "../../domain/process/processCapture.js"; +import { monotonicProcessCaptureClock } from "./ProcessCaptureClock.js"; /** Mutable observation-order ledger whose writer is shared by capture producers. */ export interface ProcessCaptureJournal { readonly entries: readonly ProcessCaptureEventJournalEntry[]; @@ -55,7 +56,10 @@ export const scheduleScenarioInteractions = ( const timer = scheduleProcessDelay(event.at_ms, () => { options.dispatchedEventIndexes.add(eventIndex); const terminal = getTerminal(); - const dispatchedAt = Math.max(0, Date.now() - started); + const dispatchedAt = Math.max( + 0, + monotonicProcessCaptureClock() - started, + ); let outcome: InteractionEvent["outcome"] = "dispatched"; if (terminal === undefined) outcome = "target_exited"; else { diff --git a/src/process/capture/ProcessCaptureLifecycle.test.ts b/src/process/capture/ProcessCaptureLifecycle.test.ts index 765635ccc..abad38ac2 100644 --- a/src/process/capture/ProcessCaptureLifecycle.test.ts +++ b/src/process/capture/ProcessCaptureLifecycle.test.ts @@ -5,6 +5,7 @@ import { parseProcessScenario } from "../../domain/process/processScenario.js"; import type { ProcessCaptureFinalization } from "../../domain/process/processCapture.js"; import { awaitTerminalExit } from "./ProcessCaptureLifecycle.js"; import type { ProcessTimer } from "./ProcessTimer.js"; +import { monotonicProcessCaptureClock } from "./ProcessCaptureClock.js"; type Delivery = ProcessCaptureFinalization["signals"][number]["delivery"]; @@ -79,8 +80,8 @@ const start = ( idle_timeout_ms: 10_000, ...scenario, }), - started: Date.now(), - lastOutput: () => Date.now(), + started: monotonicProcessCaptureClock(), + lastOutput: monotonicProcessCaptureClock, signal, signalTarget: fake.signalTarget, recordFinalization: (snapshot) => { diff --git a/src/process/capture/ProcessCaptureLifecycle.ts b/src/process/capture/ProcessCaptureLifecycle.ts index 2d2fcec00..ab9271dda 100644 --- a/src/process/capture/ProcessCaptureLifecycle.ts +++ b/src/process/capture/ProcessCaptureLifecycle.ts @@ -48,6 +48,7 @@ import { type ProcessCaptureTruncationDetails, } from "../../domain/process/processCaptureCoverage.js"; import { scheduleProcessInterval, type ProcessTimer } from "./ProcessTimer.js"; +import { monotonicProcessCaptureClock } from "./ProcessCaptureClock.js"; import type { FilesystemCheckpoint, @@ -266,10 +267,10 @@ export const settleProcessCaptureJournal = async ( quietMs = 25, maxWaitMs = 500, ): Promise => { - const deadline = Date.now() + maxWaitMs; + const deadline = monotonicProcessCaptureClock() + maxWaitMs; let observed = journal.length; - let lastChangeAt = Date.now(); - while (Date.now() < deadline) { + let lastChangeAt = monotonicProcessCaptureClock(); + while (monotonicProcessCaptureClock() < deadline) { await new Promise((resolve) => setTimeout(resolve, 4)); // A stalled event loop can leave timer and poll callbacks that were already // due queued behind this wake-up. Drain them before judging silence so a @@ -277,8 +278,8 @@ export const settleProcessCaptureJournal = async ( await setImmediate(); if (journal.length !== observed) { observed = journal.length; - lastChangeAt = Date.now(); - } else if (Date.now() - lastChangeAt >= quietMs) return; + lastChangeAt = monotonicProcessCaptureClock(); + } else if (monotonicProcessCaptureClock() - lastChangeAt >= quietMs) return; } }; @@ -337,6 +338,12 @@ export const buildCaptureResult = ( truncation_details: options.truncationDetails, limitations: [ "The executable digest is a prelaunch file sample; matching path metadata immediately after spawn does not prove an atomic operating-system image binding.", + ...(Date.parse(options.manifest.completed_at) < + Date.parse(options.manifest.started_at) + ? [ + "Wall-clock completion time precedes start time; elapsed capture timing is recorded separately and remains monotonic.", + ] + : []), "Process trees are sampled and may omit short-lived descendants.", ...(options.samplingPartial ? ["Process-tree sampling ended with an incomplete observation."] @@ -660,7 +667,7 @@ export const observeSettlement = async ( recordEvent("lifecycle", 1); return { state: "unverifiable", elapsed_ms: 0 }; } - const started = Date.now(); + const started = monotonicProcessCaptureClock(); let consecutiveEmpty = 0; let sawLive = false; let deadlineReached = false; @@ -678,19 +685,25 @@ export const observeSettlement = async ( [...observations.values()].some(({ state }) => state === "unverifiable") ) { recordEvent("lifecycle", 1); - return { state: "unverifiable", elapsed_ms: Date.now() - started }; + return { + state: "unverifiable", + elapsed_ms: monotonicProcessCaptureClock() - started, + }; } if ([...observations.values()].every(({ state }) => state === "empty")) { consecutiveEmpty += 1; if (consecutiveEmpty >= 2) { recordEvent("lifecycle", 1); - return { state: "quiesced", elapsed_ms: Date.now() - started }; + return { + state: "quiesced", + elapsed_ms: monotonicProcessCaptureClock() - started, + }; } } else { consecutiveEmpty = 0; sawLive = true; } - deadlineReached = Date.now() - started >= settleMs; + deadlineReached = monotonicProcessCaptureClock() - started >= settleMs; if (deadlineReached) break; await delay(50, undefined, { signal }); } @@ -698,8 +711,14 @@ export const observeSettlement = async ( // A lone empty observation proves neither liveness nor quiescence; only an // observed live member justifies alive_at_deadline. return sawLive - ? { state: "alive_at_deadline", elapsed_ms: Date.now() - started } - : { state: "unverifiable", elapsed_ms: Date.now() - started }; + ? { + state: "alive_at_deadline", + elapsed_ms: monotonicProcessCaptureClock() - started, + } + : { + state: "unverifiable", + elapsed_ms: monotonicProcessCaptureClock() - started, + }; }; /** Name why an attempt is unverified; a blank message never reaches the capture schema. */ @@ -786,7 +805,10 @@ export const awaitTerminalExit = async ({ if (finalizationStartedAt === undefined) return; const record: (typeof finalizationSignals)[number] = { signal: finalizationSignal, - sent_at_ms: Math.round(performance.now() - finalizationStartedAt), + sent_at_ms: Math.max( + 0, + monotonicProcessCaptureClock() - finalizationStartedAt, + ), delivery: "unverified" as FinalizationDelivery, reason: "delivery had not settled when the record was published", }; @@ -856,7 +878,7 @@ export const awaitTerminalExit = async ({ terminal.kill("SIGKILL"); return; } - finalizationStartedAt = performance.now(); + finalizationStartedAt = monotonicProcessCaptureClock(); attempt("SIGTERM"); }; terminal.onExit((exit) => { @@ -867,7 +889,7 @@ export const awaitTerminalExit = async ({ const finalizationElapsedMs = finalizationStartedAt === undefined ? undefined - : Math.round(performance.now() - finalizationStartedAt); + : Math.max(0, monotonicProcessCaptureClock() - finalizationStartedAt); recordEvent("lifecycle", 0); for (const [eventIndex, event] of scenario.events.entries()) { if (dispatchedEventIndexes.has(eventIndex)) continue; @@ -875,7 +897,10 @@ export const awaitTerminalExit = async ({ interactions.push({ sequence, scheduled_at_ms: event.at_ms, - dispatched_at_ms: Math.max(0, Date.now() - started), + dispatched_at_ms: Math.max( + 0, + monotonicProcessCaptureClock() - started, + ), type: event.type, data: event.type === "input" @@ -935,14 +960,20 @@ export const awaitTerminalExit = async ({ forceKill(); } else if (finalizationStartedAt !== undefined) { if ( - performance.now() - finalizationStartedAt >= + monotonicProcessCaptureClock() - finalizationStartedAt >= scenario.finalization_ms ) forceKill(); - } else if (Date.now() - started >= scenario.timeout_ms) { + } else if ( + monotonicProcessCaptureClock() - started >= + scenario.timeout_ms + ) { reason = "timeout"; terminateAtDeadline(); - } else if (Date.now() - lastOutput() >= scenario.idle_timeout_ms) { + } else if ( + monotonicProcessCaptureClock() - lastOutput() >= + scenario.idle_timeout_ms + ) { reason = "idle_timeout"; terminateAtDeadline(); } @@ -971,10 +1002,11 @@ const PROCESS_CLEANUP_VERIFICATION_INTERVAL_MS = 25; const verifyTokenOwnedProcessesUntilSettled = async ( verify: () => Promise, ): Promise => { - const deadline = Date.now() + PROCESS_CLEANUP_VERIFICATION_GRACE_MS; + const deadline = + monotonicProcessCaptureClock() + PROCESS_CLEANUP_VERIFICATION_GRACE_MS; let result = await verify(); while (!result.cleaned) { - const remaining = deadline - Date.now(); + const remaining = deadline - monotonicProcessCaptureClock(); if (remaining <= 0) return result; await new Promise((resolve) => setTimeout( @@ -1288,7 +1320,7 @@ export const captureTerminalFrames = (options: { } outputBytes += bytes; const atMs = normalizeProcessElapsedTime( - Date.now() - options.started, + monotonicProcessCaptureClock() - options.started, options.scenario.normalization.time_bucket_ms, ); const normalized = normalizeProcessText( diff --git a/src/process/capture/ProcessCaptureProgress.ts b/src/process/capture/ProcessCaptureProgress.ts index 83d5a51f5..205334db7 100644 --- a/src/process/capture/ProcessCaptureProgress.ts +++ b/src/process/capture/ProcessCaptureProgress.ts @@ -1,4 +1,5 @@ import type { ProcessCaptureCleanupReport } from "../../domain/process/processCapture.js"; +import { monotonicProcessCaptureClock } from "./ProcessCaptureClock.js"; /** * Progress port accepted by process capture. @@ -61,7 +62,7 @@ const formatProgressMessage = ( /** Serialize observed capture status through one rate-limited reporter. */ export const createProcessCaptureProgressTracker = ( progress: ProcessCaptureProgress | undefined, - now: () => number = Date.now, + now: () => number = monotonicProcessCaptureClock, ) => { const started = now(); let completed = 0; diff --git a/src/process/capture/ProcessHarness.ts b/src/process/capture/ProcessHarness.ts index 1033e68cd..847e512f8 100644 --- a/src/process/capture/ProcessHarness.ts +++ b/src/process/capture/ProcessHarness.ts @@ -70,6 +70,7 @@ import { observeProcessStartIdentity, signalProcessWithStartIdentity, } from "../ProcessOwnershipObservation.js"; +import { monotonicProcessCaptureClock } from "./ProcessCaptureClock.js"; interface StartedCaptureRuntime { readonly renderer: TerminalRenderer; @@ -268,7 +269,7 @@ const startCaptureRuntime = async ( options.signal, ); const startedAt = new Date(); - const started = Date.now(); + const started = monotonicProcessCaptureClock(); let lastOutput = started; renderer = createTerminalRenderer( scenario, @@ -296,7 +297,7 @@ const startCaptureRuntime = async ( ...options, terminal, started, - onOutput: () => (lastOutput = Date.now()), + onOutput: () => (lastOutput = monotonicProcessCaptureClock()), renderer, }); scheduleScenarioInteractions({ @@ -541,7 +542,7 @@ const completeCapture = async (options: { }, { name: "after_settlement", - at_ms: Math.max(0, Date.now() - runtime.started), + at_ms: Math.max(0, monotonicProcessCaptureClock() - runtime.started), files: after.files, effects: classifyFilesystemEffects(options.before, after), truncated: after.truncated, diff --git a/src/process/capture/ProcessNormalization.test.ts b/src/process/capture/ProcessNormalization.test.ts index 9c9ba1951..e5ef61062 100644 --- a/src/process/capture/ProcessNormalization.test.ts +++ b/src/process/capture/ProcessNormalization.test.ts @@ -266,3 +266,47 @@ it("normalizes representative process identities and preserves null, zero, and u "/program child 42020 parent 41010 group 43030 session 44040 listen: selected", ); }); + +it("normalizes nested paths once using the most specific selected identity", () => { + const declared = parseProcessScenario({ + executable: "/workspace/project/bin/program", + working_directory: "/workspace/project", + filesystem_observation_paths: [ + "/workspace/project/data", + "/workspace/project/data/cache", + ], + normalization: { paths: true, pids: false, ports: false, patterns: [] }, + }); + expect( + normalizeProcessText( + "/workspace/project/bin/program /workspace/project/data/cache/item /workspace/project/data/result /workspace/project/log /workspace/tmp", + declared, + "/workspace", + rootPid, + ), + ).toBe( + " /item /result /log /tmp", + ); +}); + +it("treats path metacharacters literally while preferring nested observed roots", () => { + const declared = parseProcessScenario({ + executable: "/selected/[tool]+", + working_directory: "/selected", + filesystem_observation_paths: [ + "/selected/(data)", + "/selected/(data)/cache", + ], + normalization: { paths: true, pids: false, ports: false, patterns: [] }, + }); + expect( + normalizeProcessText( + "/selected/[tool]+ /selected/(data)/cache/item /selected/(data)/file /selected/log /selected/toolll", + declared, + "/tmp", + rootPid, + ), + ).toBe( + " /item /file /log /toolll", + ); +}); diff --git a/src/process/capture/ProcessNormalization.ts b/src/process/capture/ProcessNormalization.ts index 9364ec95b..74db31b1c 100644 --- a/src/process/capture/ProcessNormalization.ts +++ b/src/process/capture/ProcessNormalization.ts @@ -17,19 +17,8 @@ export const normalizeProcessText = ( pid: number, ): string => { let normalized = value; - if (scenario.normalization.paths) { - normalized = normalized.replaceAll(temporaryRoot, ""); - normalized = normalized.replaceAll( - scenario.working_directory, - "", - ); - normalized = normalized.replaceAll(scenario.executable, ""); - for (const [index, root] of scenario.filesystem_observation_paths.entries()) - normalized = normalized.replaceAll( - root, - ``, - ); - } + if (scenario.normalization.paths) + normalized = normalizePathTokens(normalized, scenario, temporaryRoot); if (scenario.normalization.ports) normalized = normalizePortTokens(normalized); if (scenario.normalization.pids) @@ -44,6 +33,39 @@ export const normalizeProcessText = ( return normalized; }; +/** Match original paths once, preferring the most specific selected identity. */ +const normalizePathTokens = ( + value: string, + scenario: ProcessScenario, + temporaryRoot: string, +): string => { + const aliases = new Map(); + const selected: readonly (readonly [string, string])[] = [ + [temporaryRoot, ""], + [scenario.working_directory, ""], + [scenario.executable, ""], + ...scenario.filesystem_observation_paths.map( + (root, index): readonly [string, string] => [ + root, + ``, + ], + ), + ]; + for (const [path, alias] of selected) + if (path !== "" && !aliases.has(path)) aliases.set(path, alias); + const paths = [...aliases.keys()].sort( + (left, right) => right.length - left.length, + ); + if (paths.length === 0) return value; + const pattern = paths + .map((path) => path.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")) + .join("|"); + return value.replace( + new RegExp(pattern, "gu"), + (path) => aliases.get(path) ?? path, + ); +}; + // A port may end a sentence, but a period followed by a letter, digit, or // underscore in any script continues a decimal, version, or host name and is // not a port boundary. diff --git a/src/process/capture/ProcessSampling.ts b/src/process/capture/ProcessSampling.ts index 69e7dd343..59b67f577 100644 --- a/src/process/capture/ProcessSampling.ts +++ b/src/process/capture/ProcessSampling.ts @@ -6,6 +6,7 @@ import type { } from "../../domain/process/processCapture.js"; import { execFileOutput } from "../ExecFileOutput.js"; import { readProcessRunId } from "../ProcessOwnership.js"; +import { monotonicProcessCaptureClock } from "./ProcessCaptureClock.js"; const PROC_READ_CONCURRENCY = 64; interface ProcessRow { @@ -491,7 +492,7 @@ export const startProcessSampler = (options: { } return sampleProcesses({ rootPid, - elapsedMs: Date.now() - started, + elapsedMs: monotonicProcessCaptureClock() - started, limit: limit + 1, identities, signal: controller.signal, diff --git a/src/server/createServer.ts b/src/server/createServer.ts index 12ad6418b..c73071bea 100644 --- a/src/server/createServer.ts +++ b/src/server/createServer.ts @@ -9,6 +9,7 @@ import { wasmArtifactModule } from "../composition/wasm.js"; import { registerWasmTools } from "./registerWasmTools.js"; import { snapshotEnvironment } from "../process/snapshotEnvironment.js"; import { createPeResourcesService } from "../composition/binaryDiagnostics.js"; +import type { PeResourcesService } from "../application/binaryDiagnostics/PeResourcesService.js"; import { registerPeResourcesTool } from "./registerPeResourcesTool.js"; import type { EvmInterfaceService } from "../application/evm/EvmInterfaceService.js"; import { evmInterfaceModule } from "../composition/evm.js"; @@ -54,6 +55,7 @@ import { silentLogger } from "../logger.js"; import type { Logger } from "pino"; import { registerApplicationTools } from "./registerApplicationTools.js"; import { registerArtifactTools } from "./registerArtifactTools.js"; +import { registerNativeTools } from "./registerNativeTools.js"; import { registerBrowserScenarioTool } from "./registerBrowserScenarioTool.js"; import { registerBrowserTools } from "./registerBrowserTools.js"; import { registerWebScriptTool } from "./registerWebScriptTool.js"; @@ -84,6 +86,7 @@ import type { FirmwareAnalysisPort } from "../application/firmware/FirmwareAnaly import { createFirmwareAnalysisProvider } from "../composition/firmware.js"; import { registerAndroidTools } from "./registerAndroidTools.js"; import { registerApktoolTools } from "./registerApktoolTools.js"; +import { registerPcapTools } from "./registerPcapTools.js"; import { registerFlutterTools } from "./registerFlutterTools.js"; import { registerJebTools } from "./registerJebTools.js"; import { registerAdbTools } from "./registerAdbTools.js"; @@ -91,11 +94,14 @@ import { AndroidAnalysisService } from "../application/android/AndroidAnalysisSe import { JebAnalysisService } from "../application/jeb/JebAnalysisService.js"; import type { AndroidAnalysisPort } from "../application/android/AndroidAnalysisPort.js"; import type { ApktoolResourceAnalysisPort } from "../application/apktool/ApktoolResourceAnalysisPort.js"; +import type { PcapAnalysisPort } from "../application/pcap/PcapAnalysisPort.js"; +import { PcapAnalysisService } from "../application/pcap/PcapAnalysisService.js"; import { ApktoolResourceAnalysisService } from "../application/apktool/ApktoolResourceAnalysisService.js"; import type { FlutterBuildAnalysisPort } from "../application/flutter/FlutterBuildAnalysisPort.js"; import { FlutterBuildAnalysisService } from "../application/flutter/FlutterBuildAnalysisService.js"; import { createAndroidAnalysisProvider } from "../composition/android.js"; import { createApktoolResourceAnalysisProvider } from "../composition/apktool.js"; +import { createPcapAnalysisProvider } from "../composition/pcap.js"; import { createFlutterBuildAnalysisProvider } from "../composition/flutter.js"; import type { JebAnalysisPort } from "../application/jeb/JebAnalysisPort.js"; import { createJebAnalysisProvider } from "../composition/jeb.js"; @@ -103,8 +109,6 @@ import type { AdbDeviceAnalysisPort } from "../application/adb/AdbDeviceAnalysis import { AdbDeviceAnalysisService } from "../application/adb/AdbDeviceAnalysisService.js"; import { createAdbDeviceAnalysisProvider } from "../composition/adb.js"; import { registerManagedWorkflowTools } from "./registerManagedWorkflowTools.js"; -import { NATIVE_TOOL_CONTRACTS } from "../contracts/native/nativeToolContracts.js"; -import { registerEvidenceTools } from "./registerEvidenceTools.js"; import { registerOfficialTools } from "./registerOfficialTools.js"; import { registerGuidedPrompts } from "./registerPrompts.js"; import { registerSessionTools } from "./registerSessionTools.js"; @@ -146,6 +150,7 @@ export interface CreateServerOptions { readonly webNetworkCapture?: WebNetworkCaptureService; readonly androidAnalysis?: AndroidAnalysisPort; readonly apktoolAnalysis?: ApktoolResourceAnalysisPort; + readonly pcapAnalysis?: PcapAnalysisPort; readonly flutterAnalysis?: FlutterBuildAnalysisPort; readonly jebAnalysis?: JebAnalysisPort; readonly adbDeviceAnalysis?: AdbDeviceAnalysisPort; @@ -276,6 +281,10 @@ export const createServer = ( options.webSourceLocation ?? createWebSourceLocationService(environment); const webModuleTrace = options.webModuleTrace ?? createWebModuleTraceService(environment); + const goBinary = options.goBinary ?? createGoBinaryService(); + const peResources = createPeResourcesService(); + const webNetworkCapture = + options.webNetworkCapture ?? createWebNetworkCaptureService(environment); const javascriptRecovery = options.javascriptRecovery ?? createJavaScriptRecoveryProvider(environment); const artifactResources = new ArtifactResourceScope(); @@ -303,6 +312,7 @@ export const createServer = ( ); const android = options.androidAnalysis ?? createAndroidAnalysisProvider(environment); + const pcap = options.pcapAnalysis ?? createPcapAnalysisProvider(environment); const flutter = options.flutterAnalysis ?? createFlutterBuildAnalysisProvider(); const fridaInstrumentation = @@ -333,12 +343,16 @@ export const createServer = ( jeb.close(), adbDevice.close(), flutter.close(), + pcap.close(), evmInterface.close(), sqliteDatabase.close(), binaryLayout.close(), recordedCrash.close(), webSourceLocation.close(), webModuleTrace.close(), + goBinary.close(), + peResources.close(), + webNetworkCapture.close(), javascriptRecovery.close?.() ?? Promise.resolve(), artifactResources.close(), firmwareAnalysis.close(), @@ -382,6 +396,9 @@ export const createServer = ( recordEvidenceWithUnknown, withAdmittedAnalysis: analysisAdmission, artifactResources, + goBinary, + peResources, + webNetworkCapture, }; registerBinaryAnalysisTools(toolContext); registerFridaTools( @@ -438,12 +455,21 @@ export const createServer = ( recordEvidence, analysisAdmission, ); + registerPcapTools( + server, + new PcapAnalysisService(pcap), + toolLogger, + recordEvidence, + analysisAdmission, + evidenceById, + ); registerFlutterTools( server, new FlutterBuildAnalysisService(flutter), toolLogger, recordEvidence, analysisAdmission, + evidenceById, ); registerApktoolTools( server, @@ -502,6 +528,9 @@ const registerConfiguredAnalysisTools = ( evidenceById, recordEvidence, withAdmittedAnalysis, + goBinary, + peResources, + webNetworkCapture, }: ServerToolContext, android: AndroidAnalysisPort, wasmArtifact: Pick, @@ -515,6 +544,7 @@ const registerConfiguredAnalysisTools = ( toolLogger, recordEvidence, withAdmittedAnalysis, + evidenceById, ); registerJebTools( server, @@ -540,14 +570,14 @@ const registerConfiguredAnalysisTools = ( ); registerPeResourcesTool( server, - createPeResourcesService(), + peResources, toolLogger, recordEvidence, withAdmittedAnalysis, ); registerGoTools( server, - options.goBinary ?? createGoBinaryService(), + goBinary, toolLogger, recordEvidence, withAdmittedAnalysis, @@ -612,10 +642,11 @@ const registerConfiguredAnalysisTools = ( ); registerWebNetworkCaptureTool( server, - options.webNetworkCapture ?? createWebNetworkCaptureService(environment), + webNetworkCapture, toolLogger, recordEvidence, withAdmittedAnalysis, + evidenceById, ); registerJavaScriptRecoveryTool( server, @@ -656,6 +687,9 @@ const createSessionRecorders = ( }); interface ServerToolContext extends ReturnType { + readonly goBinary: GoBinaryService; + readonly peResources: PeResourcesService; + readonly webNetworkCapture: WebNetworkCaptureService; readonly artifactResources: ArtifactResourceScope; readonly server: EvidenceMcpServer; readonly session: BinarySessionPort | undefined; @@ -707,7 +741,7 @@ const registerBinaryAnalysisTools = ({ recordEvidence, withAdmittedAnalysis, }; - registerEvidenceTools(server, NATIVE_TOOL_CONTRACTS, evidenceOptions); + registerNativeTools(server, { ...evidenceOptions, evidenceById }); registerArtifactTools(server, { ...evidenceOptions, evidenceById }); registerManagedTools(server, { ...evidenceOptions, evidenceById }); if (session !== undefined) diff --git a/src/server/registerAnalysisViewTool.ts b/src/server/registerAnalysisViewTool.ts index ebd204edd..d427c0cb4 100644 --- a/src/server/registerAnalysisViewTool.ts +++ b/src/server/registerAnalysisViewTool.ts @@ -7,7 +7,10 @@ import { toolContract } from "../contracts/toolContracts.js"; import type { Logger } from "pino"; import { createEvidenceToolHandler } from "./contractToolHandler.js"; import type { WithAdmittedAnalysis } from "./analysisAdmission.js"; -import { toolRegistrationOptions } from "./toolRegistrationOptions.js"; +import { + toolRegistrationOptions, + applicationValidatedInputSchema, +} from "./toolRegistrationOptions.js"; /** Bind selected-view projection to its named contract and session Evidence owner. */ export const registerAnalysisViewTool = ( @@ -18,6 +21,7 @@ export const registerAnalysisViewTool = ( withAdmittedAnalysis?: WithAdmittedAnalysis, ): void => { const contract = toolContract("inspect_analysis_view"); + const registration = toolRegistrationOptions(contract); const handler = createEvidenceToolHandler( server, (input) => Promise.resolve(inspectAnalysisView(input, evidenceById)), @@ -27,7 +31,10 @@ export const registerAnalysisViewTool = ( ); server.registerTool( contract.name, - toolRegistrationOptions(contract), + { + ...registration, + inputSchema: applicationValidatedInputSchema(registration.inputSchema), + }, handler(contract), ); }; diff --git a/src/server/registerAndroidTools.ts b/src/server/registerAndroidTools.ts index 722bd6695..a8c29a187 100644 --- a/src/server/registerAndroidTools.ts +++ b/src/server/registerAndroidTools.ts @@ -1,6 +1,8 @@ import type { EvidenceMcpServer } from "./EvidenceMcpServer.js"; import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js"; import { AndroidAnalysisService } from "../application/android/AndroidAnalysisService.js"; +import { inspectAndroidPackage } from "../application/android/AndroidPackageInspection.js"; +import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; import { summarizeRetainedAndroidSearch } from "../application/android/AndroidSearchEvidenceSummary.js"; import { toolContract } from "../contracts/toolContracts.js"; import type { Logger } from "pino"; @@ -18,6 +20,7 @@ export const registerAndroidTools = ( logger: Logger, recordEvidence?: EvidenceWriter["recordEvidence"], withAdmittedAnalysis?: WithAdmittedAnalysis, + evidenceById?: EvidenceLookup, ): void => { const handler = createContractToolHandler( server, @@ -44,10 +47,26 @@ export const registerAndroidTools = ( withAdmittedAnalysis, ); const packageContract = toolContract("inspect_android_package"); + const packageService: ContractToolService<"inspect_android_package"> = { + execute: (_operation, input, options) => + inspectAndroidPackage( + service, + input, + { recordEvidence, evidenceById }, + options, + ), + }; + const packageHandler = createContractToolHandler( + server, + packageService, + logger, + recordEvidence, + withAdmittedAnalysis, + ); server.registerTool( packageContract.name, toolRegistrationOptions(packageContract), - handler(packageContract), + packageHandler(packageContract), ); const searchContract = toolContract("search_android_classes"); server.registerTool( diff --git a/src/server/registerArtifactTools.ts b/src/server/registerArtifactTools.ts index cf95fea41..1217664e6 100644 --- a/src/server/registerArtifactTools.ts +++ b/src/server/registerArtifactTools.ts @@ -6,7 +6,10 @@ import { artifactInspectionInputSchema, } from "../contracts/artifactToolContracts.js"; import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; -import { summarizeRetainedAnalysis } from "../application/analysisView/AnalysisViewService.js"; +import { + requireAnalysisViewRetention, + summarizeRetainedAnalysis, +} from "../application/analysisView/AnalysisViewService.js"; import { createArtifactExtractionDestination } from "../application/artifacts/ArtifactExtractionDestination.js"; import { ok } from "../domain/result.js"; import type { BinaryTarget } from "../domain/binaryTargetTypes.js"; @@ -25,6 +28,10 @@ export const registerArtifactTools = ( readonly withAdmittedAnalysis: import("./analysisAdmission.js").WithAdmittedAnalysis; }, ): void => { + const retention = { + recordEvidence: options.recordEvidence, + evidenceById: options.evidenceById, + }; registerEvidenceTools(server, ARTIFACT_TOOL_CONTRACTS, { ...options, parametersForExecution: (operation, parameters) => { @@ -37,12 +44,13 @@ export const registerArtifactTools = ( ? { ...parameters, output_root: createArtifactExtractionDestination() } : parameters; }, + preflight: (operation, parameters) => + operation === "inspect_artifact" && parameters.detail === "summary" + ? requireAnalysisViewRetention(operation, retention) + : ok(null), projectEvidence: (operation, parameters, evidence) => operation === "inspect_artifact" && parameters.detail === "summary" - ? summarizeRetainedAnalysis(evidence, { - recordEvidence: options.recordEvidence, - evidenceById: options.evidenceById, - }) + ? summarizeRetainedAnalysis(evidence, retention) : ok(evidence), sourceEvidence: (operation, result) => operation === "inspect_artifact" diff --git a/src/server/registerCaptureTools.ts b/src/server/registerCaptureTools.ts index c097f89be..296faba5c 100644 --- a/src/server/registerCaptureTools.ts +++ b/src/server/registerCaptureTools.ts @@ -28,4 +28,17 @@ export const registerCaptureTools = ( toolRegistrationOptions(contract), handler(contract), ); + const discovery = toolContract("inspect_packet_fields"); + const discover = createEvidenceToolHandler( + server, + (input, options) => service.inspectFields(input, options), + logger, + recordEvidence, + withAdmittedAnalysis, + ); + server.registerTool( + discovery.name, + toolRegistrationOptions(discovery), + discover(discovery), + ); }; diff --git a/src/server/registerEvidenceTools.ts b/src/server/registerEvidenceTools.ts index a8efac6de..b3b2358d1 100644 --- a/src/server/registerEvidenceTools.ts +++ b/src/server/registerEvidenceTools.ts @@ -33,6 +33,16 @@ interface EvidenceToolRegistration { operation: Exclude, parameters: Readonly>, ) => Readonly>; + /** Exclude adapter-only selections, such as delivery detail, from Evidence identity. */ + readonly parametersForEvidence?: ( + operation: Exclude, + parameters: Readonly>, + ) => Readonly>; + /** Refuse an unsatisfiable delivery selection before any analysis runs. */ + readonly preflight?: ( + operation: Exclude, + parameters: Readonly>, + ) => Result; readonly projectEvidence?: ( operation: Exclude, parameters: Readonly>, @@ -51,6 +61,12 @@ export const registerEvidenceTools = ( contract.name, toolRegistrationOptions(contract), async (input, context) => { + const ready = options.preflight?.( + contract.name, + jsonObjectSchema.parse(input), + ); + if (ready !== undefined && !ready.ok) + return server.delivery.toCallToolResult(ready, contract); const admitted = await options.withAdmittedAnalysis( contract.name, context.mcpReq.signal, @@ -95,7 +111,9 @@ export const registerEvidenceTools = ( execution.value.provider, { operation: contract.name, - parameters, + parameters: + options.parametersForEvidence?.(contract.name, parameters) ?? + parameters, result: execution.value.result, ...(execution.value.analysisProfile === undefined ? {} diff --git a/src/server/registerFlutterTools.ts b/src/server/registerFlutterTools.ts index 5b601c5f7..cd57e12a9 100644 --- a/src/server/registerFlutterTools.ts +++ b/src/server/registerFlutterTools.ts @@ -1,10 +1,15 @@ import type { EvidenceMcpServer } from "./EvidenceMcpServer.js"; import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js"; import { FlutterBuildAnalysisService } from "../application/flutter/FlutterBuildAnalysisService.js"; +import { inspectDartAot } from "../application/flutter/DartAotInspection.js"; +import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; import { toolContract } from "../contracts/toolContracts.js"; import type { WithAdmittedAnalysis } from "./analysisAdmission.js"; import type { Logger } from "pino"; -import { createContractToolHandler } from "./contractToolHandler.js"; +import { + createContractToolHandler, + type ContractToolService, +} from "./contractToolHandler.js"; import { toolRegistrationOptions } from "./toolRegistrationOptions.js"; /** Bind Flutter handlers to their exact named contracts through admission. */ @@ -14,6 +19,7 @@ export const registerFlutterTools = ( logger: Logger, recordEvidence?: EvidenceWriter["recordEvidence"], withAdmittedAnalysis?: WithAdmittedAnalysis, + evidenceById?: EvidenceLookup, ): void => { const handler = createContractToolHandler( server, @@ -22,14 +28,23 @@ export const registerFlutterTools = ( recordEvidence, withAdmittedAnalysis, ); - for (const contract of [ - toolContract("identify_flutter_build"), - toolContract("inspect_dart_aot"), - ] as const) { - server.registerTool( - contract.name, - toolRegistrationOptions(contract), - handler(contract), - ); - } + const identify = toolContract("identify_flutter_build"); + server.registerTool( + identify.name, + toolRegistrationOptions(identify), + handler(identify), + ); + const aotService: ContractToolService<"inspect_dart_aot"> = { + execute: (_operation, input, options) => + inspectDartAot(service, input, { recordEvidence, evidenceById }, options), + }; + const aotHandler = createContractToolHandler( + server, + aotService, + logger, + recordEvidence, + withAdmittedAnalysis, + ); + const aot = toolContract("inspect_dart_aot"); + server.registerTool(aot.name, toolRegistrationOptions(aot), aotHandler(aot)); }; diff --git a/src/server/registerInvestigationTools.ts b/src/server/registerInvestigationTools.ts index d5a2a4706..02e1c52d0 100644 --- a/src/server/registerInvestigationTools.ts +++ b/src/server/registerInvestigationTools.ts @@ -21,7 +21,10 @@ import { RECONSTRUCTION_PROVIDER, STATIC_RUNTIME_PROVIDER, } from "../application/InvestigationProviders.js"; -import { toolRegistrationOptions } from "./toolRegistrationOptions.js"; +import { + applicationValidatedInputSchema, + toolRegistrationOptions, +} from "./toolRegistrationOptions.js"; import { verifyReconstruction } from "../domain/reconstructionVerification.js"; /** Register Evidence-composed differential investigation workflows. */ @@ -52,30 +55,29 @@ const registerChangedBehavior = ( session: BinarySessionPort, contract: ReturnType>, ): void => { + const registration = toolRegistrationOptions(contract); server.registerTool( contract.name, - toolRegistrationOptions(contract), + { + ...registration, + inputSchema: applicationValidatedInputSchema(registration.inputSchema), + }, async (input, context) => { - const closure = evidenceClosure( - session, - comparisonClosure(input.comparisons), - ); - if (!closure.ok) - return server.delivery.toCallToolResult(closure, contract); - const links = closure.value; const computed = await runDerivedOperation(context, contract.name, () => - findChangedBehavior(input.comparisons), + findChangedBehavior(input), ); if (!computed.ok) return server.delivery.toCallToolResult(computed, contract); - const result = computed.value; + const { result, comparisonEvidenceIds } = computed.value; + const closure = evidenceClosure(session, result.evidence_links); + if (!closure.ok) + return server.delivery.toCallToolResult(closure, contract); + const links = closure.value; const evidence = createEvidence(undefined, CHANGED_BEHAVIOR_PROVIDER, { predicateType: "rea.changed-behavior", operation: contract.name, parameters: { - comparison_evidence_ids: input.comparisons.map( - ({ evidence_id: id }) => id, - ), + comparison_evidence_ids: [...comparisonEvidenceIds], }, result: jsonValueSchema.parse(result), confidence: "derived", diff --git a/src/server/registerNativeTools.ts b/src/server/registerNativeTools.ts new file mode 100644 index 000000000..036389d16 --- /dev/null +++ b/src/server/registerNativeTools.ts @@ -0,0 +1,54 @@ +import type { EvidenceMcpServer } from "./EvidenceMcpServer.js"; +import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js"; + +import { NATIVE_TOOL_CONTRACTS } from "../contracts/native/nativeToolContracts.js"; +import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; +import { + requireAnalysisViewRetention, + summarizeRetainedAnalysis, +} from "../application/analysisView/AnalysisViewService.js"; +import type { JsonValue } from "../domain/jsonValue.js"; +import { ok } from "../domain/result.js"; +import type { BinaryTarget } from "../domain/binaryTargetTypes.js"; +import type { Logger } from "pino"; +import { registerEvidenceTools } from "./registerEvidenceTools.js"; + +/** Delivery detail selects a response shape; it never reaches the tools or Evidence identity. */ +const withoutDelivery = ( + operation: string, + parameters: Readonly>, +): Readonly> => { + if (operation !== "inspect_macho") return parameters; + const { detail: _detail, ...selected } = parameters; + return selected; +}; + +/** Register macOS native contracts; Mach-O inspection can deliver a retained summary. */ +export const registerNativeTools = ( + server: EvidenceMcpServer, + options: { + readonly logger: Logger; + readonly activeTarget: (() => BinaryTarget | undefined) | undefined; + readonly recordEvidence: EvidenceWriter["recordEvidence"] | undefined; + readonly evidenceById?: EvidenceLookup | undefined; + readonly withAdmittedAnalysis: import("./analysisAdmission.js").WithAdmittedAnalysis; + }, +): void => { + const retention = { + recordEvidence: options.recordEvidence, + evidenceById: options.evidenceById, + }; + registerEvidenceTools(server, NATIVE_TOOL_CONTRACTS, { + ...options, + parametersForExecution: withoutDelivery, + parametersForEvidence: withoutDelivery, + preflight: (operation, parameters) => + operation === "inspect_macho" && parameters.detail === "summary" + ? requireAnalysisViewRetention(operation, retention) + : ok(null), + projectEvidence: (operation, parameters, evidence) => + operation === "inspect_macho" && parameters.detail === "summary" + ? summarizeRetainedAnalysis(evidence, retention) + : ok(evidence), + }); +}; diff --git a/src/server/registerPcapTools.ts b/src/server/registerPcapTools.ts new file mode 100644 index 000000000..b2ebd239a --- /dev/null +++ b/src/server/registerPcapTools.ts @@ -0,0 +1,83 @@ +import type { EvidenceMcpServer } from "./EvidenceMcpServer.js"; +import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js"; +import { PcapAnalysisService } from "../application/pcap/PcapAnalysisService.js"; +import { toolContract } from "../contracts/toolContracts.js"; +import type { WithAdmittedAnalysis } from "./analysisAdmission.js"; +import type { Logger } from "pino"; +import { + createContractToolHandler, + createEvidenceToolHandler, +} from "./contractToolHandler.js"; +import { + toolRegistrationOptions, + applicationValidatedInputSchema, +} from "./toolRegistrationOptions.js"; +import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; +import { + requireAnalysisViewRetention, + summarizeRetainedAnalysis, +} from "../application/analysisView/AnalysisViewService.js"; +import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; +import { err } from "../domain/result.js"; + +/** Bind pcap handlers to their exact named contracts through admission. */ +export const registerPcapTools = ( + server: EvidenceMcpServer, + service: PcapAnalysisService, + logger: Logger, + recordEvidence?: EvidenceWriter["recordEvidence"], + withAdmittedAnalysis?: WithAdmittedAnalysis, + evidenceById?: EvidenceLookup, +): void => { + const handler = createContractToolHandler( + server, + service, + logger, + recordEvidence, + withAdmittedAnalysis, + ); + const clientContract = toolContract("inspect_pcap_client"); + server.registerTool( + clientContract.name, + toolRegistrationOptions(clientContract), + handler(clientContract), + ); + const contract = toolContract("inspect_pcap_capture"); + const registration = toolRegistrationOptions(contract); + const capture = createEvidenceToolHandler( + server, + async (rawInput, options) => { + const parsed = contract.inputSchema.safeParse(rawInput); + if (!parsed.success) + return err( + analysisInputErrorFromIssues( + contract.name, + parsed.error.issues, + rawInput, + { cause: parsed.error }, + ), + ); + const { detail, ...input } = parsed.data; + const retention = { recordEvidence, evidenceById }; + if (detail === "summary") { + const ready = requireAnalysisViewRetention(contract.name, retention); + if (!ready.ok) return ready; + } + const result = await service.execute(contract.name, input, options); + return detail === "summary" && result.ok + ? summarizeRetainedAnalysis(result.value, retention) + : result; + }, + logger, + recordEvidence, + withAdmittedAnalysis, + ); + server.registerTool( + contract.name, + { + ...registration, + inputSchema: applicationValidatedInputSchema(registration.inputSchema), + }, + capture(contract), + ); +}; diff --git a/src/server/registerSessionRecordTools.ts b/src/server/registerSessionRecordTools.ts index a41d60cac..68daab23b 100644 --- a/src/server/registerSessionRecordTools.ts +++ b/src/server/registerSessionRecordTools.ts @@ -12,6 +12,8 @@ import { err, ok } from "../domain/result.js"; import { AnalysisCancelledError } from "../domain/analysisErrorCore.js"; import { inspectEvidenceBundle } from "../application/investigation/InspectEvidenceBundle.js"; import { toolRegistrationOptions } from "./toolRegistrationOptions.js"; +import { withAdmittedAnalysis } from "./analysisAdmission.js"; +import { runAdmittedToolOperation } from "./admittedToolOperation.js"; interface EvidenceToolRegistration { readonly server: EvidenceMcpServer; @@ -92,40 +94,54 @@ const registerImportEvidenceTool = ({ resources, importContract, }: EvidenceToolRegistration): void => { + const admission = withAdmittedAnalysis({ kind: "session", session }); server.registerTool( importContract.name, toolRegistrationOptions(importContract), - async (input, context) => { - const path = input.path; - const signal = context.mcpReq.signal; - const loaded = await readImmutableEvidenceBundle(path, signal, resources); - if (!loaded.ok) - return server.delivery.toCallToolResult(loaded, importContract); - const retainedUnknownRevisions = new Set( - bundleForSerialization(session).unknowns.map((unknown) => - unknownRevisionKey(unknown), - ), - ); - if (signal.aborted) - return server.delivery.toCallToolResult( - err(new AnalysisCancelledError("import_evidence_bundle")), - importContract, - ); - const imported = session.importEvidenceBundle(loaded.value); - return imported.ok - ? server.delivery.toCallToolResult( - ok({ - imported: imported.value, - unknowns_added: loaded.value.unknowns.filter( - (unknown) => - !retainedUnknownRevisions.has(unknownRevisionKey(unknown)), - ).length, - total: bundleForSerialization(session).records.length, - }), - importContract, - ) - : server.delivery.toCallToolResult(imported, importContract); - }, + async (input, context) => + runAdmittedToolOperation( + server, + admission, + importContract.name, + context.mcpReq.signal, + async () => { + const path = input.path; + const signal = context.mcpReq.signal; + const loaded = await readImmutableEvidenceBundle( + path, + signal, + resources, + ); + if (!loaded.ok) + return server.delivery.toCallToolResult(loaded, importContract); + const retainedUnknownRevisions = new Set( + bundleForSerialization(session).unknowns.map((unknown) => + unknownRevisionKey(unknown), + ), + ); + if (signal.aborted) + return server.delivery.toCallToolResult( + err(new AnalysisCancelledError("import_evidence_bundle")), + importContract, + ); + const imported = session.importEvidenceBundle(loaded.value); + return imported.ok + ? server.delivery.toCallToolResult( + ok({ + imported: imported.value, + unknowns_added: loaded.value.unknowns.filter( + (unknown) => + !retainedUnknownRevisions.has( + unknownRevisionKey(unknown), + ), + ).length, + total: bundleForSerialization(session).records.length, + }), + importContract, + ) + : server.delivery.toCallToolResult(imported, importContract); + }, + ), ); }; diff --git a/src/server/registerSignalTools.ts b/src/server/registerSignalTools.ts index 87a67361f..f833ffbd5 100644 --- a/src/server/registerSignalTools.ts +++ b/src/server/registerSignalTools.ts @@ -28,4 +28,17 @@ export const registerSignalTools = ( toolRegistrationOptions(contract), handler(contract), ); + const discovery = toolContract("inspect_signal_decoders"); + const discover = createEvidenceToolHandler( + server, + (input, options) => service.inspectDecoders(input, options), + logger, + recordEvidence, + withAdmittedAnalysis, + ); + server.registerTool( + discovery.name, + toolRegistrationOptions(discovery), + discover(discovery), + ); }; diff --git a/src/server/registerWebNetworkCaptureTool.ts b/src/server/registerWebNetworkCaptureTool.ts index 9f0c9dec8..3e9759504 100644 --- a/src/server/registerWebNetworkCaptureTool.ts +++ b/src/server/registerWebNetworkCaptureTool.ts @@ -1,12 +1,23 @@ import type { EvidenceMcpServer } from "./EvidenceMcpServer.js"; -import type { StandardSchemaWithJSON } from "@modelcontextprotocol/server"; +import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; +import { + requireAnalysisViewRetention, + summarizeRetainedAnalysis, +} from "../application/analysisView/AnalysisViewService.js"; +import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js"; +import { redactExplicitFailure } from "../domain/explicitSensitiveFailure.js"; +import { captureSensitiveValues } from "../domain/webNetworkCapture.js"; +import { err } from "../domain/result.js"; import type { WebNetworkCaptureService } from "../application/WebNetworkCaptureService.js"; import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js"; import { toolContract } from "../contracts/toolContracts.js"; import type { Logger } from "pino"; import type { WithAdmittedAnalysis } from "./analysisAdmission.js"; import { createEvidenceToolHandler } from "./contractToolHandler.js"; -import { toolRegistrationOptions } from "./toolRegistrationOptions.js"; +import { + toolRegistrationOptions, + applicationValidatedInputSchema, +} from "./toolRegistrationOptions.js"; /** Bind historical inspection to its named contract and caller-owned Evidence writer. */ export const registerWebNetworkCaptureTool = ( @@ -15,22 +26,41 @@ export const registerWebNetworkCaptureTool = ( logger: Logger, recordEvidence?: EvidenceWriter["recordEvidence"], withAdmittedAnalysis?: WithAdmittedAnalysis, + evidenceById?: EvidenceLookup, ): void => { const contract = toolContract("inspect_web_network_capture"); const registration = toolRegistrationOptions(contract); // Keep the exact advertised contract; the shared service validates raw input // before effects so caller-declared sensitivity also covers invalid arguments. // SDK pre-validation otherwise emits unprojected issue paths as plain text. - const inputSchema: StandardSchemaWithJSON = { - "~standard": { - ...registration.inputSchema["~standard"], - vendor: "rea-application", - validate: (value: unknown) => ({ value }), - }, - }; + const inputSchema = applicationValidatedInputSchema(registration.inputSchema); const handler = createEvidenceToolHandler( server, - (input, options) => service.inspect(input, options), + async (rawInput, options) => { + const parsed = contract.inputSchema.safeParse(rawInput); + if (!parsed.success) + return err( + redactExplicitFailure( + analysisInputErrorFromIssues( + contract.name, + parsed.error.issues, + rawInput, + { cause: parsed.error }, + ), + captureSensitiveValues(rawInput), + ), + ); + const { detail, ...input } = parsed.data; + const retention = { recordEvidence, evidenceById }; + if (detail === "summary") { + const ready = requireAnalysisViewRetention(contract.name, retention); + if (!ready.ok) return ready; + } + const inspected = await service.inspect(input, options); + return detail === "summary" && inspected.ok + ? summarizeRetainedAnalysis(inspected.value, retention) + : inspected; + }, logger, recordEvidence, withAdmittedAnalysis, diff --git a/src/server/toolRegistrationOptions.ts b/src/server/toolRegistrationOptions.ts index 4615971d4..c943be3f2 100644 --- a/src/server/toolRegistrationOptions.ts +++ b/src/server/toolRegistrationOptions.ts @@ -1,9 +1,21 @@ import type { ToolContract } from "../contracts/toolContractTypes.js"; +import type { StandardSchemaWithJSON } from "@modelcontextprotocol/server"; import { toolInputSchemaWithMetadata, toolOutputSchemaWithMetadata, } from "../contracts/toolSchemaMetadata.js"; +/** Preserve advertised contracts while the application owns structured input failures. */ +export const applicationValidatedInputSchema = ( + schema: StandardSchemaWithJSON, +): StandardSchemaWithJSON => ({ + "~standard": { + ...schema["~standard"], + vendor: "rea-application", + validate: (value: unknown) => ({ value }), + }, +}); + /** Project the canonical Zod contracts directly into SDK registration. */ export const toolRegistrationOptions = ( contract: Contract, diff --git a/src/signals/SigrokRecordingProvider.ts b/src/signals/SigrokRecordingProvider.ts index b0eb5c4ba..2e903d4c6 100644 --- a/src/signals/SigrokRecordingProvider.ts +++ b/src/signals/SigrokRecordingProvider.ts @@ -1,3 +1,11 @@ +import { + type InspectSignalDecodersInput, + signalDecodersSchema, +} from "../domain/signals/signalDecoders.js"; +import { + DecoderDiscoveryBudgetError, + parseDecoderDiscovery, +} from "./parseDecoderDiscovery.js"; import { readLinuxResourceLimits, type LinuxResourceLimits, @@ -81,7 +89,7 @@ export class SigrokRecordingProvider implements SignalRecordingPort { readLimits, { message: - "A signal decoding operation is already active; retry after it completes.", + "A sigrok operation is already active; retry after it completes.", details: { max_concurrent_decodes: 1 }, }, ); @@ -91,17 +99,28 @@ export class SigrokRecordingProvider implements SignalRecordingPort { options?: ExecutionOptions, ): Promise> { return this.#resources.run( - () => this.#decode(input, options), + () => this.#executeRequest(input, options), options?.signal, ); } + inspectDecoders( + input: InspectSignalDecodersInput, + options?: ExecutionOptions, + ): Promise> { + return this.#resources.run( + () => this.#executeRequest(input, options), + options?.signal, + "inspect_signal_decoders", + ); + } close(): Promise { return this.#resources.close(); } - async #decode( - input: DecodeSignalRecordingInput, + async #executeRequest( + input: DecodeSignalRecordingInput | InspectSignalDecodersInput, options?: ExecutionOptions, ): Promise> { + const operation = "path" in input ? OPERATION : "inspect_signal_decoders"; let phase: | "configuration" | "artifact" @@ -109,12 +128,12 @@ export class SigrokRecordingProvider implements SignalRecordingPort { | "producer" | "integrity" = "configuration"; let capturedOutput: AnalysisCapturedOutput | undefined; - let resourcePath = input.path; + let resourcePath = "path" in input ? input.path : "sigrok decoder catalog"; let effectiveLimits: LinuxResourceLimits | undefined; let root: ArtifactAnalysisRuntime | undefined; let result: Result; try { - if (options?.signal?.aborted) throw new AnalysisCancelledError(OPERATION); + if (options?.signal?.aborted) throw new AnalysisCancelledError(operation); await this.#resources.release(); if (this.platform !== "linux") throw new Error( @@ -154,7 +173,7 @@ export class SigrokRecordingProvider implements SignalRecordingPort { ]; phase = "workspace"; root = await this.createRuntime(); - this.#resources.retain(root, undefined); + this.#resources.retain(root, undefined, operation); const snapshotPath = join(root.path, "recording"); const execute = async (args: readonly string[]) => { const output = await runOwnedCommand( @@ -197,24 +216,24 @@ export class SigrokRecordingProvider implements SignalRecordingPort { ); if (currentLimiter.sha256 !== limiterIdentity.sha256) throw new AnalysisArtifactChangedError( - OPERATION, + operation, limiter, "Configured resource limiter changed during analysis.", { capturedOutput }, ); if (current.sha256 !== tool.sha256) throw new AnalysisArtifactChangedError( - OPERATION, + operation, command, "Configured decoder executable changed during analysis.", { capturedOutput }, ); phase = previousPhase; - resourcePath = input.path; + resourcePath = "path" in input ? input.path : command; if (output.exitCode !== 0) throw new ProviderAdapterError( SIGROK_PROVIDER_IDENTITY.id, - OPERATION, + operation, { diagnostics: { exit_code: output.exitCode ?? null, @@ -234,65 +253,15 @@ export class SigrokRecordingProvider implements SignalRecordingPort { throw new Error( "Expected sigrok-cli 0.7.2 with libsigrokdecode; inspect the selected installation.", ); - phase = "artifact"; - const selected = await this.#resources.read( - input.path, - LIMITS.input_bytes, - options?.signal, - ); - phase = "workspace"; - await writeFile(snapshotPath, selected.bytes, { - flag: "wx", - mode: 0o400, - }); - phase = "producer"; - const args = [ - "--dont-scan", - "--input-file=recording", - `--protocol-decoders=${input.decoders}`, - "--protocol-decoder-samplenum", - ...(input.input_format === null - ? [] - : [`--input-format=${input.input_format}`]), - ...(input.annotations === null - ? [] - : [`--protocol-decoder-annotations=${input.annotations}`]), - ]; - const output = await execute(args); - phase = "integrity"; - resourcePath = snapshotPath; - if ( - (await this.#resources.read(snapshotPath, LIMITS.input_bytes)) - .sha256 !== selected.sha256 - ) - throw new AnalysisArtifactChangedError( - OPERATION, - snapshotPath, - "Decoder changed the private recording copy.", - capturedOutput === undefined ? {} : { capturedOutput }, - ); - phase = "producer"; - resourcePath = input.path; - const report = signalRecordingSchema.parse({ - artifact: { - path: input.path, - sha256: selected.sha256, - bytes: selected.bytes.length, - }, - selection: input, - ...windowAnnotationText( - output.stdout.text, - input.line_offset, - input.line_limit, - ), - diagnostics: output.stderr.text, + const metadata = (args: readonly string[], diagnostics: string) => ({ + diagnostics, tool: { configured_path: configured, path: command, sha256: tool.sha256, version_banner: version.stdout.text, version_diagnostics: version.stderr.text, - arguments: args, + arguments: [...args], }, resource_limiter: { configured_path: configuredLimiter, @@ -301,31 +270,108 @@ export class SigrokRecordingProvider implements SignalRecordingPort { arguments: limitArguments, }, limits: { ...LIMITS, ...effectiveLimits }, - hardware_acquisition: "not-performed", + hardware_acquisition: "not-performed" as const, }); - result = ok( - createAnalysisExecution(report, SIGROK_PROVIDER_IDENTITY, { - subject: { + if (!("path" in input)) { + phase = "producer"; + const args = + input.decoder === null + ? ["--dont-scan", "--list-supported"] + : ["--dont-scan", `--protocol-decoders=${input.decoder}`, "--show"]; + const output = await execute(args); + const report = signalDecodersSchema.parse({ + selection: input, + ...parseDecoderDiscovery(output.stdout.text, input), + ...metadata(args, output.stderr.text), + }); + result = ok( + createAnalysisExecution(report, SIGROK_PROVIDER_IDENTITY, { + subject: { path: command, sha256: tool.sha256, format: "file" }, + limitations: [ + "Catalog and help are observed from the selected sigrok installation. Help lines preserve producer descriptions, not a separately validated parameter schema.", + "Each request probes the installation again; pages do not share a frozen catalog. Decoder modules and libraries are trusted and not fully fingerprinted.", + "Hardware discovery, recording reads and acquisition are not requested. Linux per-process limits and bounded output apply; this is not an OS sandbox.", + ], + }), + ); + } else { + phase = "artifact"; + const selected = await this.#resources.read( + input.path, + LIMITS.input_bytes, + options?.signal, + ); + phase = "workspace"; + await writeFile(snapshotPath, selected.bytes, { + flag: "wx", + mode: 0o400, + }); + phase = "producer"; + const args = [ + "--dont-scan", + "--input-file=recording", + `--protocol-decoders=${input.decoders}`, + "--protocol-decoder-samplenum", + ...(input.input_format === null + ? [] + : [`--input-format=${input.input_format}`]), + ...(input.annotations === null + ? [] + : [`--protocol-decoder-annotations=${input.annotations}`]), + ]; + const output = await execute(args); + phase = "integrity"; + resourcePath = snapshotPath; + if ( + (await this.#resources.read(snapshotPath, LIMITS.input_bytes)) + .sha256 !== selected.sha256 + ) + throw new AnalysisArtifactChangedError( + operation, + snapshotPath, + "Decoder changed the private recording copy.", + capturedOutput === undefined ? {} : { capturedOutput }, + ); + phase = "producer"; + resourcePath = "path" in input ? input.path : command; + const report = signalRecordingSchema.parse({ + artifact: { path: input.path, sha256: selected.sha256, - format: "file", + bytes: selected.bytes.length, }, - locations: [{ kind: "artifact-path", path: input.path }], - limitations: [ - "Annotations are the selected decoder's interpretation of the recorded samples and caller-selected settings, not independently verified protocol semantics. Empty output does not establish absence of traffic.", - "Sample-number ranges and display text are preserved verbatim, not converted to timestamps or parsed as a lossless byte stream. All producer stderr is retained, including warnings on exit zero.", - "Only a private copy of the selected file is decoded. Hardware discovery/acquisition and target execution are not requested. Caller-supplied tools, plugins and decoder modules are trusted; this is not an OS sandbox.", - "Linux prlimit enforces soft and hard ceilings before execution, preserving stricter inherited limits: at most 1 GiB address space per process, 64 MiB per file, 30 CPU seconds and no core dumps. Effective limits are reported. Resident input is capped at 32 MiB, each command at 30 wall-clock seconds and combined output at 4 MiB. Output overflow fails. These are per-process/per-file limits, not aggregate memory or filesystem quotas; caller-supplied tools and the limiter are trusted.", - ], - }), - ); + selection: input, + ...windowAnnotationText( + output.stdout.text, + input.line_offset, + input.line_limit, + ), + ...metadata(args, output.stderr.text), + }); + result = ok( + createAnalysisExecution(report, SIGROK_PROVIDER_IDENTITY, { + subject: { + path: input.path, + sha256: selected.sha256, + format: "file", + }, + locations: [{ kind: "artifact-path", path: input.path }], + limitations: [ + "Annotations are the selected decoder's interpretation of the recorded samples and caller-selected settings, not independently verified protocol semantics. Empty output does not establish absence of traffic.", + "Sample-number ranges and display text are preserved verbatim, not converted to timestamps or parsed as a lossless byte stream. All producer stderr is retained, including warnings on exit zero.", + "Only a private copy of the selected file is decoded. Hardware discovery/acquisition and target execution are not requested. Caller-supplied tools, plugins and decoder modules are trusted; this is not an OS sandbox.", + "Linux prlimit enforces soft and hard ceilings before execution, preserving stricter inherited limits: at most 1 GiB address space per process, 64 MiB per file, 30 CPU seconds and no core dumps. Effective limits are reported. Resident input is capped at 32 MiB, each command at 30 wall-clock seconds and combined output at 4 MiB. Output overflow fails. These are per-process/per-file limits, not aggregate memory or filesystem quotas; caller-supplied tools and the limiter are trusted.", + ], + }), + ); + } } catch (cause) { if ( root !== undefined && cause instanceof OwnedCommandFailure && cause.cleanupOwner !== undefined ) - this.#resources.retain(root, cause.cleanupOwner); + this.#resources.retain(root, cause.cleanupOwner, operation); result = err( this.#failure( cause, @@ -334,18 +380,22 @@ export class SigrokRecordingProvider implements SignalRecordingPort { root?.path ?? null, effectiveLimits, capturedOutput, + operation, ), ); } - return this.#resources.finish(result, (execution) => - createEvidence(execution.subject ?? undefined, execution.provider, { - operation: OPERATION, - parameters: input, - result: execution.result, - confidence: "observed", - locations: execution.locations, - limitations: execution.limitations, - }), + return this.#resources.finish( + result, + (execution) => + createEvidence(execution.subject ?? undefined, execution.provider, { + operation, + parameters: input, + result: execution.result, + confidence: "observed", + locations: execution.locations, + limitations: execution.limitations, + }), + operation, ); } #failure( @@ -360,6 +410,7 @@ export class SigrokRecordingProvider implements SignalRecordingPort { workspacePath: string | null, effectiveLimits: LinuxResourceLimits | undefined, observedOutput: AnalysisCapturedOutput | undefined, + operation = OPERATION, ): AnalysisError { if (cause instanceof AnalysisError) return cause; if (cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined) @@ -367,15 +418,34 @@ export class SigrokRecordingProvider implements SignalRecordingPort { cause.cleanup, cause, observedOutput, + operation, ); if ( (cause instanceof Error && cause.name === "AbortError") || (cause instanceof ArtifactReaderFailure && cause.reason === "cancelled") ) - return new AnalysisCancelledError(OPERATION, { cause }); + return new AnalysisCancelledError(operation, { cause }); + if (cause instanceof DecoderDiscoveryBudgetError) + return new AnalysisResourceConstraintError( + operation, + "memory", + cause.message, + { line_budget: 65536 }, + { + cause, + ...(observedOutput === undefined + ? {} + : { capturedOutput: observedOutput }), + }, + ); const reason = cause instanceof Error ? cause.message : String(cause); if (cause instanceof OwnedCommandFailure) - return this.#resources.commandFailure(cause, LIMITS, effectiveLimits); + return this.#resources.commandFailure( + cause, + LIMITS, + effectiveLimits, + operation, + ); if (phase === "workspace") { const code = cause instanceof Error && @@ -385,13 +455,13 @@ export class SigrokRecordingProvider implements SignalRecordingPort { : null; if (code === "ENOSPC" || code === "EDQUOT" || code === "EFBIG") return new AnalysisResourceConstraintError( - OPERATION, + operation, "file-size", `Private analysis workspace failed (${code}): ${reason}`, { workspace_path: workspacePath, system_code: code }, { cause }, ); - return new ProviderAdapterError(SIGROK_PROVIDER_IDENTITY.id, OPERATION, { + return new ProviderAdapterError(SIGROK_PROVIDER_IDENTITY.id, operation, { cause, userMessage: `Cannot prepare the private analysis workspace: ${reason}`, diagnostics: { @@ -414,12 +484,12 @@ export class SigrokRecordingProvider implements SignalRecordingPort { ["limit", "integrity", "path"].includes(cause.reason) ) return new AnalysisArtifactChangedError( - OPERATION, + operation, path, `Post-run identity verification failed for ${path}: ${reason}`, detail, ); - return new ProviderAdapterError(SIGROK_PROVIDER_IDENTITY.id, OPERATION, { + return new ProviderAdapterError(SIGROK_PROVIDER_IDENTITY.id, operation, { ...detail, diagnostics: { stage: "integrity", resource_path: path, reason }, }); @@ -427,10 +497,13 @@ export class SigrokRecordingProvider implements SignalRecordingPort { if (phase === "configuration") return new AnalysisCapabilityUnavailableError( SIGROK_PROVIDER_IDENTITY.id, - OPERATION, + operation, reason, { cause, + ...(observedOutput === undefined + ? {} + : { capturedOutput: observedOutput }), userMessage: `${reason} On Linux, configure sigrok-cli 0.7.2 through REA_SIGROK_COMMAND and util-linux prlimit through REA_SIGROK_PRLIMIT_COMMAND (default /usr/bin/prlimit).`, }, ); @@ -440,14 +513,14 @@ export class SigrokRecordingProvider implements SignalRecordingPort { cause.reason === "limit" ) return new AnalysisResourceConstraintError( - OPERATION, + operation, "file-size", reason, { input_bytes: LIMITS.input_bytes }, { cause }, ); if (cause instanceof ArtifactReaderFailure && cause.reason === "integrity") - return new AnalysisArtifactChangedError(OPERATION, path, reason, { + return new AnalysisArtifactChangedError(operation, path, reason, { cause, }); if ( @@ -456,13 +529,18 @@ export class SigrokRecordingProvider implements SignalRecordingPort { "code" in cause && (cause.code === "EACCES" || cause.code === "EPERM") ) - return new AnalysisAccessDeniedError(OPERATION, path, cause.code, { + return new AnalysisAccessDeniedError(operation, path, cause.code, { cause, }); if (phase === "artifact") - return new AnalysisInputError(OPERATION, { cause }, [ + return new AnalysisInputError(operation, { cause }, [ { path: ["path"], reason: "invalid_value", message: reason }, ]); - return new AnalysisOutputError(OPERATION, reason, { cause }); + return new AnalysisOutputError(operation, reason, { + cause, + ...(observedOutput === undefined + ? {} + : { capturedOutput: observedOutput }), + }); } } diff --git a/src/signals/parseDecoderDiscovery.ts b/src/signals/parseDecoderDiscovery.ts new file mode 100644 index 000000000..230abe2b0 --- /dev/null +++ b/src/signals/parseDecoderDiscovery.ts @@ -0,0 +1,79 @@ +import type { InspectSignalDecodersInput } from "../domain/signals/signalDecoders.js"; + +export class DecoderDiscoveryBudgetError extends Error {} + +const copyText = (value: string): string => + Buffer.from(value, "utf16le").toString("utf16le"); + +/** Parse only the 0.7.2 catalog grammar; help remains literal producer text. */ +export const parseDecoderDiscovery = ( + text: string, + input: InspectSignalDecodersInput, +) => { + // Bound record-object expansion before splitting the already byte-bounded output. + // 65,536 records leaves an 8 MiB budget at 128 bytes of bookkeeping per record. + let separators = 0; + for (const character of text) + if (character === "\n" && ++separators >= 65536) + throw new DecoderDiscoveryBudgetError( + "Decoder discovery exceeds the 65,536-line representation budget", + ); + const lines = text.split(/\r?\n/u); + if (lines.at(-1) === "") lines.pop(); + const query = input.query.toLowerCase(); + const decoders: { id: string; name: string }[] = []; + const help: { line_number: number; text: string }[] = []; + if (input.decoder === null) { + const start = lines.indexOf("Supported protocol decoders:"); + if (start < 0) throw new Error("sigrok decoder catalog heading is missing"); + const seen = new Set(); + for (const line of lines.slice(start + 1)) { + if (line === "") continue; + const match = /^ {2}([a-zA-Z0-9_+-]+) +(.+)$/u.exec(line); + if ( + match?.[1] === undefined || + match[2] === undefined || + seen.has(match[1]) + ) + throw new Error("Malformed or duplicate sigrok decoder catalog record"); + seen.add(match[1]); + decoders.push({ id: match[1], name: match[2] }); + } + if (decoders.length === 0) + throw new Error("sigrok returned an empty decoder catalog"); + } else { + if (lines[0] !== `ID: ${input.decoder}`) + throw new Error("Decoder help does not identify the selected decoder"); + lines.forEach((line, i) => help.push({ line_number: i + 1, text: line })); + } + const catalog = input.decoder === null; + const matching = catalog + ? decoders.filter(({ id, name }) => + `${id} ${name}`.toLowerCase().includes(query), + ) + : help.filter(({ text: line }) => line.toLowerCase().includes(query)); + const start = Math.min(input.offset, matching.length); + const count = Math.min( + input.limit ?? matching.length, + matching.length - start, + ); + // Keep retained pages independent of the complete producer-output allocation. + const page = matching + .slice(start, start + count) + .map((record) => + "id" in record + ? { id: copyText(record.id), name: copyText(record.name) } + : { line_number: record.line_number, text: copyText(record.text) }, + ); + return { + decoders: catalog ? page : [], + help_lines: catalog ? [] : page, + output_window: { + unit: catalog ? "decoders" : "help-lines", + examined: catalog ? decoders.length : help.length, + matching: matching.length, + returned: page.length, + has_more: start + count < matching.length, + }, + }; +}; diff --git a/src/wasm/WabtArtifactProvider.test.ts b/src/wasm/WabtArtifactProvider.test.ts index 74d481de3..428cf8cbd 100644 --- a/src/wasm/WabtArtifactProvider.test.ts +++ b/src/wasm/WabtArtifactProvider.test.ts @@ -1,14 +1,40 @@ import { access, chmod, readFile, writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { expect, it } from "vitest"; +import { expect, it, vi } from "vitest"; import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js"; import { WabtArtifactProvider } from "./WabtArtifactProvider.js"; -import { - PrivateRuntimeRoot, - PrivateRuntimeRootUnavailableError, -} from "../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRootUnavailableError } from "../process/PrivateRuntimeRootUnavailableError.js"; import { spawnOwnedProviderProcess } from "../process/ProviderProcess.js"; import { OwnedCommandFailure } from "../process/OwnedCommand.js"; +import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; + +const fileCloseFailure = vi.hoisted(() => ({ + selectedPath: "", + attempts: 0, + failFirst: false, +})); + +vi.mock("node:fs/promises", async (importOriginal) => { + const fs = await importOriginal(); + return { + ...fs, + open: async (...args: Parameters) => { + const handle = await fs.open(...args); + if (String(args[0]) !== fileCloseFailure.selectedPath) return handle; + const close = handle.close.bind(handle); + handle.close = async () => { + fileCloseFailure.attempts += 1; + if (fileCloseFailure.failFirst) { + fileCloseFailure.failFirst = false; + throw new Error("injected WABT input close failure"); + } + return close(); + }; + return handle; + }, + }; +}); const failureTags: Readonly> = { invalid: "AnalysisInputError", @@ -21,6 +47,82 @@ const failureTags: Readonly> = { "wat-warning": "AnalysisOutputError", }; +const assertCleanupRecovery = async (options: { + readonly provider: WabtArtifactProvider; + readonly result: Awaited>; + readonly path: string; + readonly runtimePath: string; + readonly cleanupAttempts: () => number; + readonly runtimeCreations: () => number; +}): Promise => { + expect(options.result).toMatchObject({ + error: { + cleanupIncomplete: true, + cleanupResources: [options.runtimePath], + partialObservation: { normalized_result: { validation: "valid" } }, + }, + }); + await expect(access(options.runtimePath)).resolves.toBeUndefined(); + const blocked = await options.provider.inspect({ + path: options.path, + glue_paths: [], + candidate_paths: [], + }); + expect(blocked).toMatchObject({ + ok: false, + error: { + cleanupIncomplete: true, + cleanupResources: [options.runtimePath], + }, + }); + expect(options.cleanupAttempts()).toBe(2); + expect(options.runtimeCreations()).toBe(1); + await options.provider.close(); + expect(options.cleanupAttempts()).toBe(3); + await expect(access(options.runtimePath)).rejects.toMatchObject({ + code: "ENOENT", + }); +}; + +const assertModeOutcome = ( + mode: string, + result: Awaited>, + path: string, +): void => { + if (mode === "success") + expect(result).toMatchObject({ + ok: true, + value: { + result: { + artifact: { path, bytes: 76 }, + validation: "valid", + runtime_execution: "not-performed", + }, + }, + }); + else + expect(result).toMatchObject({ + ok: false, + error: { _tag: failureTags[mode] }, + }); + if (mode === "invalid") + expect(result).toMatchObject({ + error: { capturedOutput: { stderr: "module.wasm: invalid bytes\n" } }, + }); + if (mode === "malformed-wat" || mode === "wat-warning") + expect(result).toMatchObject({ + error: { + capturedOutput: { + stdout: + mode === "malformed-wat" + ? "unexpected decoder output\n" + : '(module (@custom "test" "payload"))\n', + stderr: mode === "wat-warning" ? "decoder warning\n" : "", + }, + }, + }); +}; + it("returns actionable unavailable without creating a workspace when tools are absent", async () => { const provider = new WabtArtifactProvider({}, undefined, () => { throw new Error("Must not allocate"); @@ -40,40 +142,133 @@ it("returns actionable unavailable without creating a workspace when tools are a }); }); -it("reports an unavailable private runtime root without a misleading WABT remediation", async () => { - const toolRoot = await createTestTempDirectory("rea-wabt-tool-root-"); +it("retries a retained input descriptor before admitting the next WABT operation", async () => { + const root = await createTestTempDirectory("rea-wabt-read-cleanup-"); + const path = join(root, "selected.wasm"); + await writeFile(path, Buffer.alloc(76, 1)); for (const tool of ["wasm-validate", "wasm-objdump", "wasm2wat"]) - await writeFile( - join(toolRoot, tool + (process.platform === "win32" ? ".exe" : "")), - "source-owned executable seam", - { mode: 0o700 }, - ); + await writeFile(join(root, tool), "source-owned executable seam", { + mode: 0o700, + }); + const dump = await readFile( + new URL("../../tests/fixtures/wasm/objdump.txt", import.meta.url), + "utf8", + ); const provider = new WabtArtifactProvider( - { REA_WABT_BIN_DIRECTORY: toolRoot }, - undefined, - () => { - throw new PrivateRuntimeRootUnavailableError( - "REA Windows native controls are unavailable: probe failure", - ); + { REA_WABT_BIN_DIRECTORY: root }, + async (input) => { + const version = input.arguments[0] === "--version"; + const stdout = version + ? "1.0.42\n" + : input.command.includes("wasm-objdump") + ? dump + : input.command.includes("wasm2wat") + ? '(module (@custom "test" "payload"))\n' + : ""; + const launched = await spawnOwnedProviderProcess({ + ...input, + command: process.execPath, + arguments: [ + "-e", + `process.stdout.write(${JSON.stringify(stdout)}); process.exit(0);`, + ], + expectedCommand: null, + }); + return launched; }, ); - expect( - await provider.inspect({ + fileCloseFailure.selectedPath = path; + fileCloseFailure.attempts = 0; + fileCloseFailure.failFirst = true; + try { + const first = await provider.inspect({ + path, + candidate_paths: [], + glue_paths: [], + }); + expect(first).toMatchObject({ + ok: false, + error: { + cleanupIncomplete: true, + cleanupResources: [path], + cause: { message: "injected WABT input close failure" }, + }, + }); + expect(fileCloseFailure.attempts).toBe(1); + + const retried = await provider.inspect({ + path, + candidate_paths: [], + glue_paths: [], + }); + expect(retried.ok).toBe(true); + expect(fileCloseFailure.attempts).toBeGreaterThan(1); + + fileCloseFailure.failFirst = true; + const closeRetry = await provider.inspect({ + path, + candidate_paths: [], + glue_paths: [], + }); + expect(closeRetry).toMatchObject({ + ok: false, + error: { cleanupIncomplete: true, cleanupResources: [path] }, + }); + const beforeClose = fileCloseFailure.attempts; + await provider.close(); + expect(fileCloseFailure.attempts).toBeGreaterThan(beforeClose); + } finally { + fileCloseFailure.selectedPath = ""; + fileCloseFailure.failFirst = false; + await provider.close(); + } +}); + +it.each([false, true])( + "reports an unavailable private runtime root with retryable=%s without a misleading WABT remediation", + async (retryable) => { + const toolRoot = await createTestTempDirectory("rea-wabt-tool-root-"); + for (const tool of ["wasm-validate", "wasm-objdump", "wasm2wat"]) + await writeFile( + join(toolRoot, tool + (process.platform === "win32" ? ".exe" : "")), + "source-owned executable seam", + { mode: 0o700 }, + ); + const provider = new WabtArtifactProvider( + { REA_WABT_BIN_DIRECTORY: toolRoot }, + undefined, + () => { + throw new PrivateRuntimeRootUnavailableError( + "REA Windows native controls are unavailable: probe failure", + { retryable }, + ); + }, + ); + const result = await provider.inspect({ path: "/module.wasm", glue_paths: [], candidate_paths: [], - }), - ).toMatchObject({ - ok: false, - error: { - _tag: "AnalysisCapabilityUnavailableError", - userMessage: undefined, - message: expect.stringContaining( - "REA Windows native controls are unavailable", - ), - }, - }); -}); + }); + expect(result).toMatchObject({ + ok: false, + error: { + _tag: "AnalysisCapabilityUnavailableError", + retryable, + userMessage: undefined, + message: expect.stringContaining( + "REA Windows native controls are unavailable", + ), + }, + }); + if (result.ok) + throw new Error("Unavailable runtime must refuse inspection"); + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "capability_unavailable", + retryable, + category: retryable ? "unavailable" : "unsupported_provider", + }); + }, +); it.each([ "success", "invalid", @@ -100,6 +295,7 @@ it.each([ "utf8", ); let runtimePath = ""; + let runtimeCreations = 0; let acquiredPid: number | undefined; let cleanupAttempts = 0; const controller = new AbortController(); @@ -158,6 +354,7 @@ it.each([ return launched; }, async () => { + runtimeCreations += 1; const root = await PrivateRuntimeRoot.create({ prefix: "rea-wabt-owned-test-", }); @@ -176,53 +373,17 @@ it.each([ { path, glue_paths: [], candidate_paths: [] }, { signal: controller.signal }, ); - if (mode === "success") - expect(result).toMatchObject({ - ok: true, - value: { - result: { - artifact: { path, bytes: 76 }, - validation: "valid", - runtime_execution: "not-performed", - }, - }, - }); - else - expect(result).toMatchObject({ - ok: false, - error: { _tag: failureTags[mode] }, - }); - if (mode === "invalid") - expect(result).toMatchObject({ - error: { capturedOutput: { stderr: "module.wasm: invalid bytes\n" } }, - }); + assertModeOutcome(mode, result, path); if (mode === "cleanup") { - expect(result).toMatchObject({ - error: { - cleanupIncomplete: true, - cleanupResources: [runtimePath], - partialObservation: { normalized_result: { validation: "valid" } }, - }, + await assertCleanupRecovery({ + provider, + result, + path, + runtimePath, + cleanupAttempts: () => cleanupAttempts, + runtimeCreations: () => runtimeCreations, }); - await expect(access(runtimePath)).resolves.toBeUndefined(); - await expect(provider.close()).rejects.toMatchObject({ - cleanupIncomplete: true, - }); - await expect(access(runtimePath)).resolves.toBeUndefined(); - await provider.close(); } - if (mode === "malformed-wat" || mode === "wat-warning") - expect(result).toMatchObject({ - error: { - capturedOutput: { - stdout: - mode === "malformed-wat" - ? "unexpected decoder output\n" - : '(module (@custom "test" "payload"))\n', - stderr: mode === "wat-warning" ? "decoder warning\n" : "", - }, - }, - }); await expect(access(runtimePath)).rejects.toMatchObject({ code: "ENOENT" }); expect(await readFile(path)).toEqual(bytes); if (acquiredPid !== undefined) { diff --git a/src/wasm/WabtArtifactProvider.ts b/src/wasm/WabtArtifactProvider.ts index ffed3871b..c5f0aef53 100644 --- a/src/wasm/WabtArtifactProvider.ts +++ b/src/wasm/WabtArtifactProvider.ts @@ -2,13 +2,15 @@ import { randomUUID, createHash } from "node:crypto"; import { access, realpath, writeFile } from "node:fs/promises"; import { constants } from "node:fs"; import { isAbsolute, join } from "node:path"; -import type { - AnalysisExecution, - ExecutionOptions, -} from "../application/AnalysisProvider.js"; +import type { ExecutionOptions } from "../application/AnalysisProvider.js"; import { createAnalysisExecution } from "../application/AnalysisProvider.js"; -import type { WasmArtifactPort } from "../application/wasm/WasmArtifactPort.js"; +import type { + WasmArtifactExecution, + WasmArtifactPort, +} from "../application/wasm/WasmArtifactPort.js"; import { readStableArtifact } from "../artifacts/readStableArtifact.js"; +import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; +import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; import type { AnalysisError, AnalysisCapturedOutput, @@ -16,6 +18,7 @@ import type { import { AnalysisCancelledError, AnalysisArtifactChangedError, + AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisOutputError, } from "../domain/analysisErrorCore.js"; @@ -41,9 +44,7 @@ const digest = (text: string) => createHash("sha256").update(text).digest("hex"); /** Run caller-supplied WABT against private copies of exactly selected bytes. */ export class WabtArtifactProvider implements WasmArtifactPort { - readonly #pendingRoots = new Set< - Pick - >(); + readonly #resources = new ArtifactResourceScope(); constructor( readonly environment: Readonly = process.env, readonly launcher?: Launcher, @@ -53,37 +54,58 @@ export class WabtArtifactProvider implements WasmArtifactPort { ) {} /** Retry retained cleanup without discarding roots that still cannot be removed. */ async close(): Promise { - const failures: { path: string; reason: string }[] = []; - for (const root of this.#pendingRoots) { - try { - await root.close(); - this.#pendingRoots.delete(root); - } catch (cause: unknown) { - failures.push({ - path: root.path, - reason: cause instanceof Error ? cause.message : String(cause), - }); - } - } - if (failures.length > 0) + try { + await this.#resources.close(); + } catch (cause: unknown) { + const cleanup = + cause instanceof ArtifactReaderFailure ? cause.cleanup : undefined; throw new ProviderCleanupError( WABT_PROVIDER_IDENTITY.id, - failures.map(({ path }) => path), - { failures }, - { operation: OPERATION }, + cleanup?.resources ?? ["artifact-resources"], + { + reason: + cleanup?.reason ?? + (cause instanceof Error ? cause.message : String(cause)), + }, + { operation: OPERATION, cause }, ); + } } async inspect( input: InspectWasmArtifactInput, options?: ExecutionOptions, - ): Promise> { + ): Promise> { + try { + return await this.#resources.run(() => this.#inspect(input, options)); + } catch (cause: unknown) { + if ( + cause instanceof ArtifactReaderFailure && + cause.reason === "unavailable" && + cause.cleanup === undefined + ) + return err(this.#closedError()); + return err(wabtFailure(cause, "artifact", input.path)); + } + } + + #closedError(): AnalysisCapabilityUnavailableError { + return new AnalysisCapabilityUnavailableError( + WABT_PROVIDER_IDENTITY.id, + OPERATION, + "Provider is closing", + ); + } + + async #inspect( + input: InspectWasmArtifactInput, + options?: ExecutionOptions, + ): Promise> { let root: Pick | undefined; let phase: "configuration" | "artifact" | "producer" = "configuration"; - let result: Result; + let result: Result; let capturedOutput: AnalysisCapturedOutput | undefined; try { if (options?.signal?.aborted) throw new AnalysisCancelledError(OPERATION); - await this.close(); const directory = this.environment.REA_WABT_BIN_DIRECTORY ?? ""; if (!isAbsolute(directory)) throw new Error( @@ -108,6 +130,8 @@ export class WabtArtifactProvider implements WasmArtifactPort { path, WABT_LIMITS.toolBytes, options?.signal, + undefined, + this.#resources, ); commands.push({ tool, @@ -130,17 +154,24 @@ export class WabtArtifactProvider implements WasmArtifactPort { snapshotPath, WABT_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); if (bytes.sha256 !== snapshotHash) throw new Error("Private WASM snapshot bytes changed."); } catch (cause: unknown) { + const cleanup = + cause instanceof ArtifactReaderFailure ? cause.cleanup : undefined; if (options?.signal?.aborted) - throw new AnalysisCancelledError(OPERATION); + throw new AnalysisCancelledError(OPERATION, { + cause, + ...(cleanup === undefined ? {} : { cleanup }), + }); throw new AnalysisArtifactChangedError( OPERATION, input.path, "Private WASM snapshot no longer matches selected byte identity.", - { cause }, + { cause, ...(cleanup === undefined ? {} : { cleanup }) }, ); } }; @@ -175,6 +206,8 @@ export class WabtArtifactProvider implements WasmArtifactPort { command.path, WABT_LIMITS.toolBytes, options?.signal, + undefined, + this.#resources, ); if (current.sha256 !== command.sha256) throw new AnalysisOutputError( @@ -200,6 +233,8 @@ export class WabtArtifactProvider implements WasmArtifactPort { input.path, WABT_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); const artifact = { path: input.path, @@ -215,6 +250,8 @@ export class WabtArtifactProvider implements WasmArtifactPort { path, WABT_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); candidates.push({ path, @@ -228,6 +265,8 @@ export class WabtArtifactProvider implements WasmArtifactPort { path, WABT_LIMITS.inputBytes, options?.signal, + undefined, + this.#resources, ); const source = new TextDecoder("utf-8", { fatal: true }).decode( bytes.bytes, @@ -395,10 +434,13 @@ export class WabtArtifactProvider implements WasmArtifactPort { ); } if (root !== undefined) { - try { - await root.close(); - } catch (cause: unknown) { - this.#pendingRoots.add(root); + const cleanup = await this.#resources.release({ + kind: "private-runtime-root", + resource: root.path, + root, + }); + if (cleanup.kind === "failed") { + const cause = cleanup.cause; const partialObservation = result.ok ? createEvidence( result.value.subject ?? undefined, diff --git a/src/wasm/WabtFailures.ts b/src/wasm/WabtFailures.ts index ef5692f1b..7b6875203 100644 --- a/src/wasm/WabtFailures.ts +++ b/src/wasm/WabtFailures.ts @@ -11,7 +11,7 @@ import { } from "../domain/analysisErrorCore.js"; import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import { OwnedCommandFailure } from "../process/OwnedCommand.js"; -import { PrivateRuntimeRootUnavailableError } from "../process/PrivateRuntimeRoot.js"; +import { PrivateRuntimeRootUnavailableError } from "../process/PrivateRuntimeRootUnavailableError.js"; import { WABT_LIMITS, WABT_PROVIDER_IDENTITY } from "./WabtRelease.js"; /** Preserve lifecycle failures and diagnostic bytes instead of returning partial success. */ export const wabtFailure = ( @@ -20,12 +20,19 @@ export const wabtFailure = ( path: string, ): AnalysisError => { if (cause instanceof AnalysisError) return cause; + const artifactCleanup = + cause instanceof ArtifactReaderFailure ? cause.cleanup : undefined; + const cleanupOptions = + artifactCleanup === undefined ? {} : { cleanup: artifactCleanup }; const reason = cause instanceof Error ? cause.message : String(cause); if ( (cause instanceof ArtifactReaderFailure && cause.reason === "cancelled") || (cause instanceof Error && cause.name === "AbortError") ) - return new AnalysisCancelledError("inspect_wasm_artifact", { cause }); + return new AnalysisCancelledError("inspect_wasm_artifact", { + cause, + ...cleanupOptions, + }); if (cause instanceof OwnedCommandFailure) { const capturedOutput = cause.snapshot === null @@ -76,7 +83,7 @@ export const wabtFailure = ( WABT_PROVIDER_IDENTITY.id, "inspect_wasm_artifact", reason, - { cause }, + { cause, retryable: cause.retryable }, ); if (phase === "configuration") return new AnalysisCapabilityUnavailableError( @@ -85,6 +92,7 @@ export const wabtFailure = ( reason, { cause, + ...cleanupOptions, userMessage: `${reason} Supply WABT 1.0.42 via absolute REA_WABT_BIN_DIRECTORY; REA does not install tools.`, }, ); @@ -97,7 +105,7 @@ export const wabtFailure = ( "inspect_wasm_artifact", path, reason, - { cause }, + { cause, ...cleanupOptions }, ); if ( phase === "artifact" && @@ -109,11 +117,16 @@ export const wabtFailure = ( "inspect_wasm_artifact", path, cause.code, - { cause }, + { cause, ...cleanupOptions }, ); if (phase === "artifact") - return new AnalysisInputError("inspect_wasm_artifact", { cause }, [ - { path: ["path"], reason: "invalid_value", message: reason }, - ]); - return new AnalysisOutputError("inspect_wasm_artifact", reason, { cause }); + return new AnalysisInputError( + "inspect_wasm_artifact", + { cause, ...cleanupOptions }, + [{ path: ["path"], reason: "invalid_value", message: reason }], + ); + return new AnalysisOutputError("inspect_wasm_artifact", reason, { + cause, + ...cleanupOptions, + }); }; diff --git a/src/windows/WindowsPrivateRuntime.ts b/src/windows/WindowsPrivateRuntime.ts index e17544a49..2c361a6d0 100644 --- a/src/windows/WindowsPrivateRuntime.ts +++ b/src/windows/WindowsPrivateRuntime.ts @@ -1,6 +1,7 @@ import { win32 } from "node:path"; import { z } from "zod"; +import { PrivateRuntimeRootUnavailableError } from "../process/PrivateRuntimeRootUnavailableError.js"; import { requireWindowsNativeAuthority, @@ -23,6 +24,13 @@ const fileSchema = windowsFileIdentitySchema.extend({ handle: windowsHandleSchema, }); const runtimes = new Map(); +// Retry only a proven pre-allocation sharing/lock conflict, never opaque text +// or an operation that may already own an unpublished runtime directory. +const transientRuntimeAdmissionSchema = z.object({ + code: z.literal("ERR_REA_WINDOWS_NATIVE"), + win32Code: z.union([z.literal(32), z.literal(33)]), + runtimeAllocation: z.literal("not-started"), +}); /** Retain private DACL and path handles until native recursive cleanup settles. */ export class WindowsPrivateRuntime { @@ -40,9 +48,21 @@ export class WindowsPrivateRuntime { /** Create a new directory with its private DACL installed at creation. */ static create(parent: string, prefix: string): WindowsPrivateRuntime { const authority = requireWindowsNativeAuthority(); - const observation = runtimeSchema.parse( - authority.call("runtime_create", [parent, prefix]), - ); + let observed: unknown; + try { + observed = authority.call("runtime_create", [parent, prefix]); + } catch (cause: unknown) { + if ( + cause instanceof Error && + transientRuntimeAdmissionSchema.safeParse(cause).success + ) + throw new PrivateRuntimeRootUnavailableError(cause.message, { + cause, + retryable: true, + }); + throw cause; + } + const observation = runtimeSchema.parse(observed); const runtime = new WindowsPrivateRuntime(observation, authority); runtimes.set(windowsRuntimeIdentityKey(observation), runtime); return runtime; diff --git a/tests/acceptance/applications/JavaScriptModuleLookupCli.test.ts b/tests/acceptance/applications/JavaScriptModuleLookupCli.test.ts index cd045a00a..3a7fad35f 100644 --- a/tests/acceptance/applications/JavaScriptModuleLookupCli.test.ts +++ b/tests/acceptance/applications/JavaScriptModuleLookupCli.test.ts @@ -29,6 +29,14 @@ const createModuleLookupFixture = async () => { 'import "ancestor-empty";', 'import "ancestor-blocked";', 'import "ancestor-sub/parser";', + 'import "./.hidden.js";', + 'import "./..pkg.js";', + 'import "./exact.js/.";', + 'import "./exact.js/child/..";', + 'import ".hidden.js";', + 'import "..pkg.js";', + 'import ".";', + 'import "..";', "void fallback;", ].join("\n"), "esm/extensionless.js": "module.exports = 1;", @@ -36,6 +44,10 @@ const createModuleLookupFixture = async () => { "esm/explicit.js.js": "module.exports = 3;", "esm/exact.js": "module.exports = 4;", "esm/actual.cjs": "module.exports = 5;", + "esm/.hidden.js": "module.exports = 'local hidden';", + "esm/..pkg.js": "module.exports = 'local dot package';", + "node_modules/.hidden.js/index.js": "module.exports = 'hidden package';", + "node_modules/..pkg.js/index.js": "module.exports = 'dot package';", "esm/typed.mts": 'import value from "./typed-dep.js"; void value;', "esm/typed-dep.ts": "export default 42;", "cjs/entry.cjs": [ @@ -54,8 +66,15 @@ const createModuleLookupFixture = async () => { 'require("ancestor-empty");', 'require("ancestor-blocked");', 'require("ancestor-sub/parser");', + 'require(".hidden.js");', + 'require("./.hidden.js");', + 'require(".");', + 'require("..");', ].join("\n"), "cjs/directory/index.cjs": "module.exports = 6;", + "cjs/index.js": "module.exports = 'current directory';", + "index.js": "module.exports = 'parent directory';", + "cjs/.hidden.js": "module.exports = 'local hidden';", "cjs/extensionless.cjs": "module.exports = 1;", "cjs/feature.cjs": "module.exports = 2;", "cjs/module-only.mjs": "export default 42;", @@ -79,7 +98,7 @@ const createModuleLookupFixture = async () => { "node_modules/ancestor-blocked/index.js": "module.exports = 9;", "node_modules/ancestor-sub/parser.js": "module.exports = 10;", "esm/runtime-control.mjs": [ - 'const specifiers = ["./extensionless", "./directory", "./explicit.js", "./exact.js", "./actual.cjs?cache=1", "empty-main", "nested-main", "file-only", "ancestor-empty", "ancestor-blocked", "ancestor-sub/parser"];', + 'const specifiers = ["./extensionless", "./directory", "./explicit.js", "./exact.js", "./actual.cjs?cache=1", "empty-main", "nested-main", "file-only", "ancestor-empty", "ancestor-blocked", "ancestor-sub/parser", "./.hidden.js", "./..pkg.js", "./exact.js/.", "./exact.js/child/..", ".hidden.js", "..pkg.js", ".", ".."];', "const results = [];", "for (const specifier of specifiers) {", " try { const value = (await import(specifier)).default; results.push({ specifier, ok: true, value }); }", @@ -88,7 +107,7 @@ const createModuleLookupFixture = async () => { "console.log(JSON.stringify(results));", ].join("\n"), "cjs/runtime-control.cjs": [ - 'const specifiers = ["./extensionless", "./directory", "./feature", "./feature.cjs", "./module-only", "./valid-directory", "./default-js", "./default-json", "empty-main", "nested-main", "file-only", "ancestor-empty", "ancestor-blocked", "ancestor-sub/parser"];', + 'const specifiers = ["./extensionless", "./directory", "./feature", "./feature.cjs", "./module-only", "./valid-directory", "./default-js", "./default-json", "empty-main", "nested-main", "file-only", "ancestor-empty", "ancestor-blocked", "ancestor-sub/parser", ".hidden.js", "./.hidden.js", ".", ".."];', "const results = [];", "for (const specifier of specifiers) {", " try { const value = require(specifier); results.push({ specifier, ok: true, value }); }", @@ -109,6 +128,110 @@ const createModuleLookupFixture = async () => { return root; }; +type RuntimeControlResult = { + readonly specifier: string; + readonly ok: boolean; + readonly code?: string; + readonly value?: unknown; +}; + +const expectNodeRuntimeControls = ( + esmOutput: string, + cjsOutput: string, +): void => { + const esmResults = JSON.parse(esmOutput) as RuntimeControlResult[]; + const cjsResults = JSON.parse(cjsOutput) as RuntimeControlResult[]; + expect(esmResults).toEqual([ + { + specifier: "./extensionless", + ok: false, + code: "ERR_MODULE_NOT_FOUND", + }, + { + specifier: "./directory", + ok: false, + code: "ERR_UNSUPPORTED_DIR_IMPORT", + }, + { + specifier: "./explicit.js", + ok: false, + code: "ERR_MODULE_NOT_FOUND", + }, + { specifier: "./exact.js", ok: true, value: 4 }, + { specifier: "./actual.cjs?cache=1", ok: true, value: 5 }, + { specifier: "empty-main", ok: true, value: 42 }, + { specifier: "nested-main", ok: false, code: "ERR_MODULE_NOT_FOUND" }, + { specifier: "file-only", ok: false, code: "ERR_MODULE_NOT_FOUND" }, + { specifier: "ancestor-empty", ok: false, code: "ERR_MODULE_NOT_FOUND" }, + { + specifier: "ancestor-blocked", + ok: false, + code: "ERR_MODULE_NOT_FOUND", + }, + { + specifier: "ancestor-sub/parser", + ok: false, + code: "ERR_MODULE_NOT_FOUND", + }, + { specifier: "./.hidden.js", ok: true, value: "local hidden" }, + { specifier: "./..pkg.js", ok: true, value: "local dot package" }, + { + specifier: "./exact.js/.", + ok: false, + code: "ERR_UNSUPPORTED_DIR_IMPORT", + }, + { + specifier: "./exact.js/child/..", + ok: false, + code: "ERR_UNSUPPORTED_DIR_IMPORT", + }, + { + specifier: ".hidden.js", + ok: false, + code: "ERR_INVALID_MODULE_SPECIFIER", + }, + { + specifier: "..pkg.js", + ok: false, + code: "ERR_INVALID_MODULE_SPECIFIER", + }, + { specifier: ".", ok: false, code: "ERR_UNSUPPORTED_DIR_IMPORT" }, + { specifier: "..", ok: false, code: "ERR_UNSUPPORTED_DIR_IMPORT" }, + ]); + expect(cjsResults).toEqual([ + { + specifier: "./extensionless", + ok: false, + code: "MODULE_NOT_FOUND", + }, + { + specifier: "./directory", + ok: false, + code: "MODULE_NOT_FOUND", + }, + { + specifier: "./feature", + ok: false, + code: "MODULE_NOT_FOUND", + }, + { specifier: "./feature.cjs", ok: true, value: 2 }, + { specifier: "./module-only", ok: false, code: "MODULE_NOT_FOUND" }, + { specifier: "./valid-directory", ok: true, value: 42 }, + { specifier: "./default-js", ok: true, value: 3 }, + { specifier: "./default-json", ok: true, value: { value: 4 } }, + { specifier: "empty-main", ok: true, value: 42 }, + { specifier: "nested-main", ok: false, code: "MODULE_NOT_FOUND" }, + { specifier: "file-only", ok: true, value: 7 }, + { specifier: "ancestor-empty", ok: true, value: 8 }, + { specifier: "ancestor-blocked", ok: false, code: "MODULE_NOT_FOUND" }, + { specifier: "ancestor-sub/parser", ok: true, value: 10 }, + { specifier: ".hidden.js", ok: true, value: "hidden package" }, + { specifier: "./.hidden.js", ok: true, value: "local hidden" }, + { specifier: ".", ok: true, value: "current directory" }, + { specifier: "..", ok: true, value: "parent directory" }, + ]); +}; + cliTest.for(["CLI", "stdio MCP"] as const)( "matches Node module lookup for ESM and CommonJS through %s", async (surface, { cli }) => { @@ -123,79 +246,7 @@ cliTest.for(["CLI", "stdio MCP"] as const)( timeout: 5_000, }), ]); - const esmResults = JSON.parse(esmControl.stdout) as Array<{ - readonly specifier: string; - readonly ok: boolean; - readonly code?: string; - readonly value?: unknown; - }>; - const cjsResults = JSON.parse(cjsControl.stdout) as Array<{ - readonly specifier: string; - readonly ok: boolean; - readonly code?: string; - readonly value?: unknown; - }>; - expect(esmResults).toEqual([ - { - specifier: "./extensionless", - ok: false, - code: "ERR_MODULE_NOT_FOUND", - }, - { - specifier: "./directory", - ok: false, - code: "ERR_UNSUPPORTED_DIR_IMPORT", - }, - { - specifier: "./explicit.js", - ok: false, - code: "ERR_MODULE_NOT_FOUND", - }, - { specifier: "./exact.js", ok: true, value: 4 }, - { specifier: "./actual.cjs?cache=1", ok: true, value: 5 }, - { specifier: "empty-main", ok: true, value: 42 }, - { specifier: "nested-main", ok: false, code: "ERR_MODULE_NOT_FOUND" }, - { specifier: "file-only", ok: false, code: "ERR_MODULE_NOT_FOUND" }, - { specifier: "ancestor-empty", ok: false, code: "ERR_MODULE_NOT_FOUND" }, - { - specifier: "ancestor-blocked", - ok: false, - code: "ERR_MODULE_NOT_FOUND", - }, - { - specifier: "ancestor-sub/parser", - ok: false, - code: "ERR_MODULE_NOT_FOUND", - }, - ]); - expect(cjsResults).toEqual([ - { - specifier: "./extensionless", - ok: false, - code: "MODULE_NOT_FOUND", - }, - { - specifier: "./directory", - ok: false, - code: "MODULE_NOT_FOUND", - }, - { - specifier: "./feature", - ok: false, - code: "MODULE_NOT_FOUND", - }, - { specifier: "./feature.cjs", ok: true, value: 2 }, - { specifier: "./module-only", ok: false, code: "MODULE_NOT_FOUND" }, - { specifier: "./valid-directory", ok: true, value: 42 }, - { specifier: "./default-js", ok: true, value: 3 }, - { specifier: "./default-json", ok: true, value: { value: 4 } }, - { specifier: "empty-main", ok: true, value: 42 }, - { specifier: "nested-main", ok: false, code: "MODULE_NOT_FOUND" }, - { specifier: "file-only", ok: true, value: 7 }, - { specifier: "ancestor-empty", ok: true, value: 8 }, - { specifier: "ancestor-blocked", ok: false, code: "MODULE_NOT_FOUND" }, - { specifier: "ancestor-sub/parser", ok: true, value: 10 }, - ]); + expectNodeRuntimeControls(esmControl.stdout, cjsControl.stdout); const { graph } = await analyzeJavaScriptDirectory(surface, cli, root); const expectations = [ @@ -211,6 +262,14 @@ cliTest.for(["CLI", "stdio MCP"] as const)( ["import", "ancestor-empty", null, "not-found"], ["import", "ancestor-blocked", null, "not-found"], ["import", "ancestor-sub/parser", null, "not-found"], + ["import", "./.hidden.js", "esm/.hidden.js", "resolved"], + ["import", "./..pkg.js", "esm/..pkg.js", "resolved"], + ["import", ".hidden.js", null, "rejected"], + ["import", "..pkg.js", null, "rejected"], + ["import", ".", null, "not-found"], + ["import", "..", null, "not-found"], + ["import", "./exact.js/.", null, "not-found"], + ["import", "./exact.js/child/..", null, "not-found"], ["require", "./extensionless", null, "not-found"], ["require", "./directory", null, "not-found"], ["require", "./feature", null, "not-found"], @@ -242,19 +301,30 @@ cliTest.for(["CLI", "stdio MCP"] as const)( "node_modules/ancestor-sub/parser.js", "resolved", ], + ["require", ".hidden.js", "node_modules/.hidden.js/index.js", "resolved"], + ["require", "./.hidden.js", "cjs/.hidden.js", "resolved"], + ["require", ".", "cjs/index.js", "resolved"], + ["require", "..", "index.js", "resolved"], ] as const; - for (const [kind, specifier, resolvedPath, status] of expectations) - expect(graph.edges).toContainEqual( + for (const [kind, specifier, resolvedPath, status] of expectations) { + const matchingProperties = graph.edges + .filter((edge) => edge.relation === "imports") + .map((edge) => edge.properties) + .filter( + (properties) => + "module_link_kind" in properties && + properties.module_link_kind === kind && + properties.specifier === specifier, + ); + expect(matchingProperties).toContainEqual( expect.objectContaining({ - relation: "imports", - properties: expect.objectContaining({ - module_link_kind: kind, - specifier, - resolved_path: resolvedPath, - resolution_status: status, - }), + module_link_kind: kind, + specifier, + resolved_path: resolvedPath, + resolution_status: status, }), ); + } }, ); diff --git a/tests/acceptance/applications/bundlerCallbackMetadataCli.test.ts b/tests/acceptance/applications/bundlerCallbackMetadataCli.test.ts new file mode 100644 index 000000000..1f3987237 --- /dev/null +++ b/tests/acceptance/applications/bundlerCallbackMetadataCli.test.ts @@ -0,0 +1,61 @@ +import { writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { expect } from "vitest"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { cliTest } from "../../support/cli/cliFixture.js"; +import { analyzeJavaScriptDirectory } from "../../support/cli/javascriptApplication.js"; + +cliTest.for(["CLI", "stdio MCP"] as const)( + "retains both repeated chunk callback observations through %s", + async (surface, { cli }) => { + const root = await createTestTempDirectory("rea-bundler-callbacks-"); + const source = [ + '(globalThis.webpackChunkFixture = globalThis.webpackChunkFixture || []).push([[1], {a: function() {}}, function(r) { r(7); r.e("chunk-a"); }]);', + '(globalThis.webpackChunkFixture = globalThis.webpackChunkFixture || []).push([[1], {a: function() {}}, function(r) { r(8); r.e("chunk-b"); }]);', + ].join("\n"); + await writeFile(join(root, "bundle.js"), source); + const { graph } = await analyzeJavaScriptDirectory(surface, cli, root); + const chunk = graph.nodes.find(({ kind }) => kind === "javascript-chunk"); + for (const [index, entry, asyncChunk] of [ + [0, "7", "chunk-a"], + [1, "8", "chunk-b"], + ] as const) { + expect(chunk?.observations).toContainEqual( + expect.objectContaining({ + properties: expect.objectContaining({ + entry_module_keys: [entry], + async_chunk_keys: [asyncChunk], + }), + evidence: expect.objectContaining({ + location: expect.objectContaining({ + value: expect.objectContaining({ + source: "bundle.js", + start: { line: index + 1, column: 0 }, + }), + }), + }), + }), + ); + expect(graph.edges).toContainEqual( + expect.objectContaining({ + source_node_id: chunk?.node_id, + properties: expect.objectContaining({ + kind: "bundler-entry-module", + module_key: entry, + resolution_status: "not-found", + }), + }), + ); + expect(graph.edges).toContainEqual( + expect.objectContaining({ + source_node_id: chunk?.node_id, + properties: expect.objectContaining({ + kind: "bundler-async-chunk", + chunk_key: asyncChunk, + resolution_status: "not-found", + }), + }), + ); + } + }, +); diff --git a/tests/acceptance/applications/nibFieldIdentity.test.ts b/tests/acceptance/applications/nibFieldIdentity.test.ts new file mode 100644 index 000000000..5af16f890 --- /dev/null +++ b/tests/acceptance/applications/nibFieldIdentity.test.ts @@ -0,0 +1,110 @@ +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; +import { createHash } from "node:crypto"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { join, resolve } from "node:path"; +import { expect } from "vitest"; + +import { encodeNibArchiveFixture } from "../../../src/artifacts/apple/NibArchive.fixture.js"; +import { toolContract } from "../../../src/contracts/toolContracts.js"; +import { interfaceBuilderAnalysisSchema } from "../../../src/domain/apple/interfaceBuilderGraph.js"; +import { thinMach } from "../../../src/domain/binaryTarget.fixture.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { cliTest } from "../../support/cli/cliFixture.js"; + +cliTest( + "preserves literal NIB fields and UTF-8 names through CLI and stdio MCP", + async ({ cli }) => { + const root = await createTestTempDirectory("rea-nib-field-identity-"); + const app = join(root, "Fixture.app"); + const contents = join(app, "Contents"); + await mkdir(join(contents, "Resources"), { recursive: true }); + await mkdir(join(contents, "MacOS")); + await writeFile( + join(contents, "MacOS/App"), + thinMach(0xfeedfacf, 0x0100000c), + ); + await writeFile( + join(contents, "Info.plist"), + "CFBundleExecutableAppCFBundleIdentifierdev.rea.nib-fields", + ); + const archive = encodeNibArchiveFixture({ + classes: ["UIView", "\uFEFFCustomView"], + objects: [ + { + classIndex: 0, + values: { + ["__proto__"]: { ref: 1 }, + constructor: 7, + enabled: true, + "\uFEFFenabled": false, + }, + }, + { classIndex: 1, values: { ["__proto__"]: 23 } }, + ], + }); + const path = join(contents, "Resources/Panel.nib"); + await writeFile(path, archive); + const result = await cli.run({ + arguments: ["decode-interface-builder", app, "--json"], + environment: { REA_LOG_LEVEL: "silent", REA_ANALYSIS_PROVIDER: "auto" }, + }); + expect(result.exitCode, result.stdout + result.stderr).toBe(0); + const contract = toolContract("decode_interface_builder"); + const evidence = contract.outputSchema.parse(result.json); + const transport = new StdioClientTransport({ + command: process.execPath, + args: [resolve("scripts/rea.mjs"), "mcp"], + env: { + PATH: process.env.PATH ?? "", + REA_LOG_LEVEL: "silent", + REA_ANALYSIS_PROVIDER: "auto", + }, + stderr: "pipe", + }); + const client = new Client({ name: "nib-field-identity", version: "1" }); + try { + await client.connect(transport); + const opened = await client.callTool({ + name: "open_binary", + arguments: { path: app }, + }); + expect(opened.isError, JSON.stringify(opened)).not.toBe(true); + const response = await client.callTool({ + name: contract.name, + arguments: {}, + }); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + const mcp = contract.outputSchema.parse(response.structuredContent); + expect(mcp.normalized_result).toEqual(evidence.normalized_result); + } finally { + try { + await client.close(); + } finally { + await transport.close(); + } + } + const report = interfaceBuilderAnalysisSchema.parse( + evidence.normalized_result, + ); + expect(report.documents[0]?.archive_sha256).toBe( + createHash("sha256").update(archive).digest("hex"), + ); + const objects = report.graph.nodes.filter( + ({ attributes }) => attributes.interface_builder_object_id !== undefined, + ); + expect(objects).toHaveLength(2); + expect(objects[0]?.attributes.nibValues).toEqual({ + ["__proto__"]: { objectID: "1" }, + constructor: 7, + enabled: true, + "\uFEFFenabled": false, + }); + expect(objects[1]?.attributes).toMatchObject({ + class_name: "\uFEFFCustomView", + nibValues: { ["__proto__"]: 23 }, + }); + expect(await readFile(path)).toEqual(archive); + }, + 60_000, +); diff --git a/tests/acceptance/flutterAnalysis.test.ts b/tests/acceptance/flutterAnalysis.test.ts index 457dce96b..11671785e 100644 --- a/tests/acceptance/flutterAnalysis.test.ts +++ b/tests/acceptance/flutterAnalysis.test.ts @@ -2,6 +2,7 @@ import { createHash } from "node:crypto"; import { expect } from "vitest"; import { toolContract } from "../../src/contracts/toolContracts.js"; import { parseEvidence } from "../../src/domain/evidence.js"; +import { flutterResultSchemas } from "../../src/domain/flutter/flutterBuildAnalysis.js"; import { aotFixtureImage, engineFixtureImage, @@ -59,6 +60,9 @@ cliTest( }); expect(result.exitCode, result.stderr).toBe(0); const evidence = toolContract(name).outputSchema.parse(result.json); + const complete = flutterResultSchemas[name].parse( + evidence.normalized_result, + ); const response = await call(name, { path, ...(abi === undefined ? {} : { abi }), @@ -70,7 +74,7 @@ cliTest( expect(mcp.subject).toMatchObject({ local_path: path, format: "apk", - digest: { sha256: evidence.normalized_result.target.sha256 }, + digest: { sha256: complete.target.sha256 }, }); expect(mcp.evidence_id).toBe(evidence.evidence_id); if (name === "inspect_dart_aot") { @@ -134,6 +138,9 @@ cliTest( const evidence = toolContract("inspect_dart_aot").outputSchema.parse( result.json, ); + const complete = flutterResultSchemas.inspect_dart_aot.parse( + evidence.normalized_result, + ); const { call } = await connectLocalToolsMcp(); const response = await call("inspect_dart_aot", { path }); expect(response.isError, JSON.stringify(response)).not.toBe(true); @@ -146,7 +153,7 @@ cliTest( string_pool: { coverage: "complete" }, }); expect( - evidence.normalized_result.libapp.sections + complete.libapp.sections .filter((section) => section.name.endsWith("Data")) .map((section) => section.kind), ).toEqual([4, 4]); diff --git a/tests/acceptance/harmonyArtifactJourney.test.ts b/tests/acceptance/harmonyArtifactJourney.test.ts new file mode 100644 index 000000000..51178d744 --- /dev/null +++ b/tests/acceptance/harmonyArtifactJourney.test.ts @@ -0,0 +1,135 @@ +import { createHash } from "node:crypto"; +import { readFile, writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +import { Client } from "@modelcontextprotocol/client"; +import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; +import { TextReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js"; +import { expect } from "vitest"; + +import { artifactInspectionResultSchema } from "../../src/domain/artifactInspection.js"; +import { parseEvidence } from "../../src/domain/evidence.js"; +import { harmonyApplicationProjectionResultSchema } from "../../src/domain/harmony/harmonyApplication.js"; +import { workspaceCliTest as test } from "../support/cli/workspaceCliFixture.js"; + +test("preserves Harmony archive formats through the public CLI/MCP lifecycle", async ({ + cli, + workspace, +}) => { + const writer = new ZipWriter(new Uint8ArrayWriter()); + await writer.add( + "module.json", + new TextReader('{"module":{"name":"fixture"}}'), + ); + await writer.add( + "ets/modules.abc", + new TextReader("opaque bytecode fixture"), + ); + const bytes = await writer.close(); + const environment = { + PATH: process.env.PATH ?? "", + HOME: workspace.root, + USERPROFILE: workspace.root, + XDG_CONFIG_HOME: workspace.path("config"), + XDG_CACHE_HOME: workspace.path("cache"), + XDG_STATE_HOME: workspace.path("state"), + NODE_OPTIONS: "--max-old-space-size=512", + REA_LOG_LEVEL: "silent", + }; + const client = new Client({ name: "rea-harmony-acceptance", version: "1" }); + const transport = new StdioClientTransport({ + command: process.execPath, + args: [resolve("scripts/rea.mjs"), "mcp"], + env: environment, + stderr: "pipe", + }); + try { + await client.connect(transport); + await client.listTools(); + for (const { suffix, format } of [ + { suffix: "hap", format: "hap" }, + { suffix: "hsp", format: "hsp" }, + { suffix: "app", format: "app-pack" }, + ]) { + const path = workspace.path(`fixture.${suffix}`); + await writeFile(path, bytes); + const sha256 = createHash("sha256").update(bytes).digest("hex"); + const cliReply = await cli.run({ + arguments: ["inspect-artifact", path, "--format", "json"], + environment, + }); + expect(cliReply.exitCode, cliReply.stderr).toBe(0); + const cliEvidence = parseEvidence(cliReply.json); + const cliInventory = artifactInspectionResultSchema.parse( + cliEvidence.normalized_result, + ); + expect(cliInventory.subject).toMatchObject({ + root_format: format, + root_sha256: sha256, + }); + const opened = await client.callTool({ + name: "open_binary", + arguments: { path }, + }); + expect(opened.isError, JSON.stringify(opened)).not.toBe(true); + expect(opened.structuredContent).toMatchObject({ + result: { kind: "archive", format, sha256 }, + }); + const status = await client.callTool({ + name: "binary_session", + arguments: {}, + }); + expect(status.isError, JSON.stringify(status)).not.toBe(true); + expect(status.structuredContent).toMatchObject({ + result: { open: true, kind: "archive", format, sha256 }, + }); + const inspected = await client.callTool({ + name: "inspect_artifact", + arguments: {}, + }); + expect(inspected.isError, JSON.stringify(inspected)).not.toBe(true); + const inventoryEvidence = parseEvidence(inspected.structuredContent); + expect( + artifactInspectionResultSchema.parse( + inventoryEvidence.normalized_result, + ), + ).toEqual(cliInventory); + + const projected = await client.callTool({ + name: "project_harmony_application_graph", + arguments: { inventory_evidence: [inventoryEvidence] }, + }); + expect(projected.isError, JSON.stringify(projected)).not.toBe(true); + const graph = harmonyApplicationProjectionResultSchema.parse( + parseEvidence(projected.structuredContent).normalized_result, + ); + expect(graph).toMatchObject({ + root_format: format, + root_sha256: sha256, + coverage: { status: "complete-within-inventory" }, + }); + expect( + graph.components.manifests.map(({ path: member }) => member), + ).toEqual(["module.json"]); + expect( + graph.components.bytecode.map(({ path: member }) => member), + ).toEqual(["ets/modules.abc"]); + const closed = await client.callTool({ + name: "close_binary", + arguments: {}, + }); + expect(closed.isError, JSON.stringify(closed)).not.toBe(true); + const empty = await client.callTool({ + name: "binary_session", + arguments: {}, + }); + expect(empty.isError, JSON.stringify(empty)).not.toBe(true); + expect(empty.structuredContent).toMatchObject({ + result: { open: false }, + }); + expect(await readFile(path)).toEqual(Buffer.from(bytes)); + } + } finally { + await client.close(); + } +}, 120_000); diff --git a/tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts b/tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts index d9363988f..425e0e610 100644 --- a/tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts +++ b/tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts @@ -6,6 +6,17 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { cliTest } from "../../support/cli/cliFixture.js"; const cases = [ + { + client: "cursor", + path: ".cursor/mcp.json", + text: "malformed UTF-8", + bytes: Buffer.concat([ + Buffer.from('{"label":"'), + Buffer.from([0xff]), + Buffer.from('"}'), + ]), + diagnostic: "not valid UTF-8", + }, { client: "cursor", path: ".cursor/mcp.json", @@ -92,7 +103,9 @@ for (const scenario of cases) ); const config = join(home, scenario.path); await mkdir(dirname(config), { recursive: true }); - await writeFile(config, scenario.text); + const original = + "bytes" in scenario ? scenario.bytes : Buffer.from(scenario.text); + await writeFile(config, original); const environment = { HOME: home, USERPROFILE: home, @@ -146,7 +159,7 @@ for (const scenario of cases) }); if (!("syntax" in scenario)) expect(uninstall.stdout).not.toContain("not valid JSON"); - expect(await readFile(config, "utf8")).toBe(scenario.text); + expect(await readFile(config)).toEqual(original); expect(await readdir(dirname(config))).toEqual([ scenario.path.split("/").at(-1), ]); diff --git a/tests/acceptance/tools/historicalCaptureResources.test.ts b/tests/acceptance/tools/historicalCaptureResources.test.ts index d4c56d644..64a7b6638 100644 --- a/tests/acceptance/tools/historicalCaptureResources.test.ts +++ b/tests/acceptance/tools/historicalCaptureResources.test.ts @@ -5,7 +5,7 @@ import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; import { expect, it } from "vitest"; -import { HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES } from "../../../src/browser/history/CaptureRelease.js"; +import { NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES } from "../../../src/browser/history/CaptureRelease.js"; import { WEB_NETWORK_CAPTURE_LIMITS } from "../../../src/domain/webNetworkCapture.js"; import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js"; import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; @@ -46,7 +46,7 @@ const capture = (count: number) => // Node.js enforces the decoder's V8 heap flags. Bun ignores them; on Windows // the decoder's Job Object commit limit is the enforced bound instead, and // Bun elsewhere has no bound this capture can reach. -const jobLimit = HAR_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES; +const jobLimit = NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES; it.skipIf(process.versions.bun !== undefined && jobLimit === null)( "reports real HAR memory exhaustion through CLI and MCP and preserves server usability", async () => { diff --git a/tests/acceptance/tools/qlogCapture.test.ts b/tests/acceptance/tools/qlogCapture.test.ts new file mode 100644 index 000000000..be67c3a34 --- /dev/null +++ b/tests/acceptance/tools/qlogCapture.test.ts @@ -0,0 +1,457 @@ +import { execFile } from "node:child_process"; +import { writeFile, truncate, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; +import { expect, it as runtimeTest } from "vitest"; +import { + NODE_CAPTURE_HEAP_ENFORCED, + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, +} from "../../../src/browser/history/CaptureRelease.js"; +import { webNetworkCaptureSummaryViewResultSchema } from "../../../src/domain/analysisView/analysisView.js"; +import { parseEvidence } from "../../../src/domain/evidence.js"; +import { + webNetworkCaptureSchema, + WEB_NETWORK_CAPTURE_LIMITS, +} from "../../../src/domain/webNetworkCapture.js"; +import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js"; +import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +const execute = promisify(execFile); +const hasMemoryBound = + NODE_CAPTURE_HEAP_ENFORCED || + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES !== null; +const it = runtimeTest.skipIf(!hasMemoryBound); +const cli = fileURLToPath(new URL("../../../scripts/rea.mjs", import.meta.url)); +const event = { + name: "transport:packet_sent", + time: 1791819895000.25, + data: { + header: { packet_type: "1RTT", packet_number: 5 }, + frames: [ + { frame_type: "stream", stream_id: 0, offset: 10, length: 5, fin: true }, + ], + }, +}; +const qlog = (events: unknown[]) => + JSON.stringify({ + qlog_format: "JSON", + qlog_version: "0.3", + traces: [ + { + vantage_point: { name: "aioquic", type: "server" }, + common_fields: { ODCID: "trace-local" }, + events, + }, + ], + }); + +const assertAdditionalQlogFacets = async ( + call: Awaited>["call"], + retained: { kind: string; evidence_id: string }, +): Promise => { + for (const [view, expected] of [ + [ + { kind: "qlog", facet: "traces", offset: 1, limit: 1 }, + [{ trace_index: 1, event_count: 1, stream_count: 1 }], + ], + [ + { kind: "qlog", facet: "loss-declarations", trace_index: 0 }, + [{ record_ordinal: 1, packet_number: { state: "reported", value: "5" } }], + ], + [{ kind: "qlog", facet: "incomplete-records", trace_index: 0 }, []], + [ + { + kind: "qlog", + facet: "ranges", + trace_index: 0, + stream_id: "0", + direction: "sent", + }, + [{ start: "10", end: "15" }], + ], + [ + { + kind: "qlog", + facet: "final-sizes", + trace_index: 0, + stream_id: "0", + direction: "sent", + }, + ["15"], + ], + [{ kind: "qlog", facet: "traces", offset: 99 }, []], + ] as const) { + const response = await call("inspect_analysis_view", { + source: retained, + view, + }); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + expect( + parseEvidence(response.structuredContent).normalized_result, + ).toMatchObject({ + page: { items: expected }, + coverage: { exhausted: true }, + }); + } +}; + +it("pages original trace-scoped facts after source deletion without conflating selected events or identical stream IDs", async () => { + const root = await createTestTempDirectory("rea-qlog-pages-"); + const path = join(root, "input.qlog"); + const source = JSON.parse( + qlog([ + event, + { + name: "recovery:packet_lost", + time: 1791819895001, + data: { packet_number: 5, type: "1RTT" }, + }, + ]), + ); + source.traces.push({ + ...source.traces[0], + events: [ + { + ...event, + data: { + frames: [ + { + frame_type: "stream", + stream_id: 0, + offset: 100, + length: 3, + fin: true, + }, + ], + }, + }, + ], + }); + await writeFile(path, JSON.stringify(source)); + const { call } = await connectLocalToolsMcp(); + const response = await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + detail: "summary", + record_ordinals: [2], + }); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + const summary = webNetworkCaptureSummaryViewResultSchema.parse( + parseEvidence(response.structuredContent).normalized_result, + ); + expect(summary).toMatchObject({ + summary: { + total_records: 3, + retained_records: 1, + qlog: { + trace_count: 2, + retained_stream_count: 2, + loss_declaration_count: 1, + }, + }, + }); + expect(JSON.stringify(summary)).not.toContain('"contributions"'); + if ( + !("parent_evidence_id" in summary) || + typeof summary.parent_evidence_id !== "string" + ) + throw new Error("Missing retained parent"); + const retained = { + kind: "retained-evidence", + evidence_id: summary.parent_evidence_id, + }; + const parent = parseEvidence( + ( + await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + record_ordinals: [2], + }) + ).structuredContent, + ); + expect(parent.evidence_id).toBe(summary.parent_evidence_id); + const portablePath = join(root, "parent.json"); + await rm(path); + const pages = []; + for (const trace_index of [0, 1]) { + const page = await call("inspect_analysis_view", { + source: retained, + view: { kind: "qlog", facet: "streams", trace_index, limit: 1 }, + }); + expect(page.isError, JSON.stringify(page)).not.toBe(true); + pages.push(parseEvidence(page.structuredContent).normalized_result); + } + expect(pages[0]).toMatchObject({ + page: { items: [{ stream_id: "0", unique_bytes: "5" }] }, + context: { scope: "all-recorded-events-before-selection" }, + }); + expect(pages[1]).toMatchObject({ + page: { items: [{ stream_id: "0", unique_bytes: "3" }] }, + }); + await assertAdditionalQlogFacets(call, retained); + const view = { + kind: "qlog", + facet: "contributions", + trace_index: 0, + stream_id: "0", + direction: "sent", + offset: 0, + limit: 1, + }; + const contribution = parseEvidence( + (await call("inspect_analysis_view", { source: retained, view })) + .structuredContent, + ); + expect(contribution.normalized_result).toMatchObject({ + page: { + items: [{ record_ordinal: 0, frame_index: 0, offset: "10", length: "5" }], + }, + coverage: { total: 1, exhausted: true }, + }); + await writeFile( + portablePath, + JSON.stringify({ source: { kind: "inline", evidence: parent }, view }), + ); + const cliResult = await execute(process.execPath, [ + cli, + "inspect-analysis-view", + portablePath, + "--json", + ]); + expect(parseEvidence(JSON.parse(cliResult.stdout)).normalized_result).toEqual( + contribution.normalized_result, + ); + for (const invalid of [ + { kind: "qlog", facet: "streams" }, + { kind: "qlog", facet: "streams", trace_index: 99 }, + { ...view, stream_id: "99" }, + { kind: "qlog", facet: "traces", trace_index: 0 }, + ]) + expect( + parseMcpToolError( + await call("inspect_analysis_view", { + source: retained, + view: invalid, + }), + ), + ).toMatchObject({ error: { code: "invalid_request" } }); +}, 60_000); + +runtimeTest.runIf(!hasMemoryBound)( + "refuses qlog when this runtime cannot enforce a decoder memory bound", + async () => { + const { call } = await connectLocalToolsMcp(); + const root = await createTestTempDirectory("rea-qlog-unbounded-"); + const path = join(root, "input.qlog"); + await writeFile(path, qlog([event])); + expect( + parseMcpToolError( + await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + }), + ), + ).toMatchObject({ error: { code: "capability_unavailable" } }); + }, +); + +it("runs built CLI and real stdio SDK with exact evidence parity, selection, retained references and strict schemas", async () => { + const root = await createTestTempDirectory("rea-qlog-public-"); + const path = join(root, "input.qlog"); + await writeFile( + path, + qlog([ + event, + { + name: "recovery:packet_lost", + time: 1791819895001.125, + data: { packet_number: 5, type: "1RTT" }, + }, + ]), + ); + const { call, client } = await connectLocalToolsMcp(); + const input = { capture_path: path, format: "qlog", record_ordinals: [1, 0] }; + const response = await call("inspect_web_network_capture", input); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + const mcp = parseEvidence(response.structuredContent); + const result = await execute(process.execPath, [ + cli, + "inspect-web-network-capture", + path, + "qlog", + "--record", + "1", + "--record", + "0", + "--json", + ]); + const cliEvidence = parseEvidence(JSON.parse(result.stdout)); + expect(cliEvidence.evidence_id).toBe(mcp.evidence_id); + expect(cliEvidence.normalized_result).toEqual(mcp.normalized_result); + expect(mcp.analysis_profile?.parameters).toMatchObject({ + qlog_profile: "aioquic-1.5.0-json-0.3", + }); + expect(mcp.authority).toBe("historical-reference"); + const decoded = webNetworkCaptureSchema.parse(mcp.normalized_result); + expect(decoded.records.map((record) => record.ordinal)).toEqual([1, 0]); + if (decoded.format !== "qlog") throw new Error("qlog format required"); + expect(decoded.qlog.traces[0]?.streams[0]).toMatchObject({ + unique_bytes: "5", + covered_ranges: [{ start: "10", end: "15" }], + }); + const retained = await call("inspect_analysis_view", { + source: { kind: "retained-evidence", evidence_id: mcp.evidence_id }, + view: { kind: "api-surface" }, + }); + // An unsupported view over an existing retained parent proves lookup without pretending qlog is HAR. + expect(parseMcpToolError(retained)).toMatchObject({ + error: { code: "unsupported_target" }, + }); + await client.ping(); + for (const record_ordinals of [[2], [0, 0]]) { + expect( + parseMcpToolError( + await call("inspect_web_network_capture", { + ...input, + record_ordinals, + }), + ), + ).toMatchObject({ error: { code: "invalid_request" } }); + } + const hidden = await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + sensitive_values: ["trace-local", "/traces/0", "input.qlog"], + }); + expect(JSON.stringify(hidden)).not.toContain("trace-local"); + expect(JSON.stringify(hidden)).not.toContain("/traces/0"); + expect(JSON.stringify(hidden)).not.toContain("input.qlog"); + const hiddenEvidence = parseEvidence(hidden.structuredContent); + expect( + webNetworkCaptureSchema.parse(hiddenEvidence.normalized_result).artifact + .path, + ).toBe(""); + const invalid = await call("inspect_web_network_capture", { + ...input, + mysecret: true, + sensitive_values: ["mysecret"], + }); + expect(parseMcpToolError(invalid)).toMatchObject({ + error: { code: "invalid_request" }, + }); + expect(JSON.stringify(invalid)).not.toContain("mysecret"); +}, 60_000); + +it("fails whole-capture validation before selection and survives malformed, unsupported and oversized qlog", async () => { + const root = await createTestTempDirectory("rea-qlog-errors-"); + const path = join(root, "input.qlog"); + const { call, client } = await connectLocalToolsMcp(); + for (const [text, code] of [ + [qlog([event, { ...event, time: "invalid" }]), "invalid_request"], + [qlog([event]).slice(0, -1), "invalid_request"], + [ + qlog([event]).replace('"qlog_version":"0.3"', '"qlog_version":"0.4"'), + "capability_unavailable", + ], + [ + qlog([ + { + ...event, + extension: JSON.parse("[".repeat(65) + "0" + "]".repeat(65)), + }, + ]), + "invalid_request", + ], + ] as const) { + await writeFile(path, text); + expect( + parseMcpToolError( + await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + record_ordinals: [0], + }), + ), + ).toMatchObject({ error: { code } }); + const failed: unknown = await execute(process.execPath, [ + cli, + "inspect-web-network-capture", + path, + "qlog", + "--json", + ]).catch((cause: unknown) => cause); + expect(failed).toMatchObject({ + code: 1, + stdout: expect.stringContaining(`"code":"${code}"`), + }); + } + await truncate(path, WEB_NETWORK_CAPTURE_LIMITS.inputBytes + 1); + expect( + parseMcpToolError( + await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + }), + ), + ).toMatchObject({ error: { code: "invalid_request" } }); + await writeFile(path, qlog([event])); + await client.ping(); + expect( + ( + await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + }) + ).isError, + ).not.toBe(true); +}, 60_000); + +runtimeTest.skipIf(process.versions.bun !== undefined || !hasMemoryBound)( + "contains actual qlog decoder heap exhaustion and keeps MCP usable", + async () => { + const root = await createTestTempDirectory("rea-qlog-capacity-"); + const path = join(root, "dense.qlog"); + const dense = qlog(Array(100_000).fill(event)); + expect(Buffer.byteLength(dense)).toBeLessThan( + WEB_NETWORK_CAPTURE_LIMITS.inputBytes, + ); + await writeFile(path, dense); + const { call, client } = await connectLocalToolsMcp(); + const response = await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + record_ordinals: [0], + }); + expect(parseMcpToolError(response)).toMatchObject({ + error: { + code: "resource_constraint", + details: { + resource: "memory", + reported_limits: { old_generation_heap_mib: 192 }, + }, + }, + }); + const failed: unknown = await execute( + process.execPath, + [cli, "inspect-web-network-capture", path, "qlog", "--json"], + { timeout: 40_000, maxBuffer: 1024 * 1024 }, + ).catch((cause: unknown) => cause); + expect(failed).toMatchObject({ + code: 1, + stdout: expect.stringContaining('"code":"resource_constraint"'), + }); + await writeFile(path, qlog([event])); + await client.ping(); + expect( + ( + await call("inspect_web_network_capture", { + capture_path: path, + format: "qlog", + }) + ).isError, + ).not.toBe(true); + }, + 60_000, +); diff --git a/tests/boundary/android/jadxMcpTransport.test.ts b/tests/boundary/android/jadxMcpTransport.test.ts index afe79fc09..fe05f14b4 100644 --- a/tests/boundary/android/jadxMcpTransport.test.ts +++ b/tests/boundary/android/jadxMcpTransport.test.ts @@ -26,6 +26,26 @@ class FixtureProcess extends EventEmitter implements ProviderProcessHandle { } } +const fixtureLauncher = + (process: FixtureProcess): JadxLauncher => + async ({ runId }) => ({ + process, + ownership: { + runId, + leaderPid: process.pid, + processGroupId: process.pid, + expectedParentPid: process.pid, + }, + cleanup: async () => { + process.emit("exit", 0, null); + process.emit("close", 0, null); + process.stdout.end(); + process.stderr.end(); + process.stdin.end(); + return { cleaned: true, signaled: false }; + }, + }); + it("joins pending input errors before detaching the owned protocol stream", async () => { let completeWrite: ((cause: Error) => void) | undefined; const failure = new Error("owned pipe closed during cancellation"); @@ -70,26 +90,9 @@ it("joins pending input errors before detaching the owned protocol stream", asyn it("decodes split UTF-8 and newline bytes, then routes multiple complete frames", async () => { const process = new FixtureProcess(); - const launcher: JadxLauncher = async ({ runId }) => ({ - process, - ownership: { - runId, - leaderPid: process.pid, - processGroupId: process.pid, - expectedParentPid: process.pid, - }, - cleanup: async () => { - process.emit("exit", 0, null); - process.emit("close", 0, null); - process.stdout.end(); - process.stderr.end(); - process.stdin.end(); - return { cleaned: true, signaled: false }; - }, - }); const transport = new JadxMcpTransport( { command: "fixture", arguments: [] }, - launcher, + fixtureLauncher(process), ); const received: JSONRPCMessage[] = []; transport.onmessage = (message) => received.push(message); @@ -98,7 +101,9 @@ it("decodes split UTF-8 and newline bytes, then routes multiple complete frames" const first = { jsonrpc: "2.0", id: 1, - result: { content: [{ type: "text", text: "snow 雪 🦊" }] }, + result: { + content: [{ type: "text", text: "snow 雪 🦊 and literal �" }], + }, } satisfies JSONRPCMessage; const second = { jsonrpc: "2.0", @@ -120,28 +125,41 @@ it("decodes split UTF-8 and newline bytes, then routes multiple complete frames" await transport.close(); }); -it("accepts a complete JSON-RPC frame at the 8 MiB boundary", async () => { +it.each([ + ["invalid UTF-8 byte", Buffer.from([0xff])], + ["truncated UTF-8 sequence", Buffer.from([0xe2, 0x82])], +])("rejects %s in a complete JSON-RPC frame", async (_label, invalid) => { const process = new FixtureProcess(); - const launcher: JadxLauncher = async ({ runId }) => ({ - process, - ownership: { - runId, - leaderPid: process.pid, - processGroupId: process.pid, - expectedParentPid: process.pid, - }, - cleanup: async () => { - process.emit("exit", 0, null); - process.emit("close", 0, null); - process.stdout.end(); - process.stderr.end(); - process.stdin.end(); - return { cleaned: true, signaled: false }; - }, - }); const transport = new JadxMcpTransport( { command: "fixture", arguments: [] }, - launcher, + fixtureLauncher(process), + ); + const received: JSONRPCMessage[] = []; + const errors: Error[] = []; + transport.onmessage = (message) => received.push(message); + transport.onerror = (cause) => errors.push(cause); + + await transport.start(); + process.stdout.write( + Buffer.concat([ + Buffer.from('{"jsonrpc":"2.0","id":1,"result":{"text":"'), + invalid, + Buffer.from('"}}\n'), + ]), + ); + await new Promise((resolve) => setImmediate(resolve)); + await transport.close(); + + expect(received).toEqual([]); + expect(errors).toHaveLength(1); + expect(errors[0]?.message).toMatch(/encoded data was not valid/i); +}); + +it("accepts a complete JSON-RPC frame at the 8 MiB boundary", async () => { + const process = new FixtureProcess(); + const transport = new JadxMcpTransport( + { command: "fixture", arguments: [] }, + fixtureLauncher(process), ); const received: JSONRPCMessage[] = []; transport.onmessage = (message) => received.push(message); diff --git a/tests/boundary/browser/cdpScreenshotDocumentIdentity.test.ts b/tests/boundary/browser/cdpScreenshotDocumentIdentity.test.ts index 012ad9663..b3fcbc592 100644 --- a/tests/boundary/browser/cdpScreenshotDocumentIdentity.test.ts +++ b/tests/boundary/browser/cdpScreenshotDocumentIdentity.test.ts @@ -3,6 +3,37 @@ import { CdpBrowserProvider } from "../../../src/browser/CdpBrowserProvider.js"; import { captureWebScreenshotInputSchema } from "../../../src/domain/webScreenshot.js"; import { startFakeCdpBrowser } from "../../fixtures/fakeCdpBrowser.js"; describe("screenshot committed document identity", () => { + it.each([ + { offset: 8, value: 14 }, + { offset: 16, value: 0x8000_0000 }, + { offset: 20, value: 0x8000_0000 }, + ])("rejects invalid screenshot IHDR metadata", async ({ offset, value }) => { + const bytes = Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jv4sAAAAASUVORK5CYII=", + "base64", + ); + bytes.writeUInt32BE(value, offset); + const browser = await startFakeCdpBrowser({ + commandResult: ({ method }) => + method === "Page.captureScreenshot" + ? { data: bytes.toString("base64") } + : undefined, + }); + onTestFinished(async () => { + await browser.close(); + }); + const result = await new CdpBrowserProvider().captureScreenshot( + captureWebScreenshotInputSchema.parse({ + cdp_endpoint: browser.endpoint, + allowed_origins: [browser.allowedOrigin], + target_id: "allowed-page", + }), + ); + expect(result).toMatchObject({ + ok: false, + error: { reason: "protocol_error" }, + }); + }); it.each(["loader-main", "loader-reloaded"])( "distinguishes %s for the same URL", async (screenshotDocumentLoader) => { diff --git a/tests/boundary/browser/historicalCaptureDecoder.test.ts b/tests/boundary/browser/historicalCaptureDecoder.test.ts index 92b26d5df..e02524f8d 100644 --- a/tests/boundary/browser/historicalCaptureDecoder.test.ts +++ b/tests/boundary/browser/historicalCaptureDecoder.test.ts @@ -11,7 +11,7 @@ import { } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { expect, it, onTestFinished } from "vitest"; +import { expect, it, onTestFinished, vi } from "vitest"; import { HistoricalCaptureDecoder } from "../../../src/browser/history/HistoricalCaptureDecoder.js"; import { MitmproxyCaptureAdapter } from "../../../src/browser/history/MitmproxyCaptureAdapter.js"; import { HAR_CAPTURE_PROVIDER_IDENTITY } from "../../../src/browser/history/CaptureRelease.js"; @@ -22,6 +22,7 @@ import { import { historicalHar } from "../../fixtures/historicalHar.js"; import { decodeHarCapture } from "../../../src/browser/history/HarCapture.js"; import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import { OwnedFileHandle } from "../../../src/filesystem/OwnedFileHandle.js"; const linux = it.skipIf(process.platform !== "linux"); @@ -138,6 +139,66 @@ it("classifies an oversized selected capture before creating an owned decoder", }); }); +it("retains a failed capture reader and retries it before a fresh load", async () => { + const root = await mkdtemp(join(tmpdir(), "rea-capture-reader-close-")); + onTestFinished(() => rm(root, { recursive: true, force: true })); + const path = join(root, "input.har"); + await writeFile(path, JSON.stringify(historicalHar())); + const originalClose = OwnedFileHandle.prototype.close; + const close = vi.spyOn(OwnedFileHandle.prototype, "close"); + let allowClose = false; + let closeAttempts = 0; + close.mockImplementation(async function (this: OwnedFileHandle) { + closeAttempts += 1; + if (!allowClose) throw new Error("injected capture reader close failure"); + await originalClose.call(this); + }); + let decoderCalls = 0; + const decoder = new HistoricalCaptureDecoder( + [ + { + format: "har", + identity: HAR_CAPTURE_PROVIDER_IDENTITY, + command: async () => { + decoderCalls += 1; + return { + command: process.execPath, + arguments: ["-e", "process.exit(0)"], + }; + }, + }, + ], + process.env, + ); + const input = inspectWebNetworkCaptureInputSchema.parse({ + capture_path: path, + format: "har", + }); + try { + const first = await decoder.inspect(input); + expect(first.ok).toBe(false); + if (first.ok) throw new Error("Reader close failure must fail inspection"); + expect(first.error.cleanupResources).toContain(path); + expect(decoderCalls).toBe(0); + + const refused = await decoder.inspect(input); + expect(refused.ok).toBe(false); + if (refused.ok) throw new Error("Fresh read must wait for owner cleanup"); + expect(refused.error.cleanupIncomplete).toBe(true); + expect(refused.error.cleanupResources).toContain(path); + expect(decoderCalls).toBe(0); + expect(closeAttempts).toBe(2); + + allowClose = true; + await decoder.close(); + expect(closeAttempts).toBe(3); + } finally { + allowClose = true; + await decoder.close().catch(() => undefined); + close.mockRestore(); + } +}); + it("does not misclassify decoder filesystem failures as missing selected input", async () => { const root = await mkdtemp(join(tmpdir(), "rea-historical-command-")); onTestFinished(() => rm(root, { recursive: true, force: true })); diff --git a/tests/boundary/browser/historicalWebCapture.test.ts b/tests/boundary/browser/historicalWebCapture.test.ts index a0a9f10e2..781172cd3 100644 --- a/tests/boundary/browser/historicalWebCapture.test.ts +++ b/tests/boundary/browser/historicalWebCapture.test.ts @@ -7,6 +7,9 @@ import { execFile } from "node:child_process"; import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; import { parseEvidence } from "../../../src/domain/evidence.js"; +import { webNetworkCaptureSchema } from "../../../src/domain/webNetworkCapture.js"; +import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; const entrypoint = fileURLToPath( new URL("../../../scripts/rea.mjs", import.meta.url), ); @@ -41,6 +44,91 @@ const cli = async ( }; import { historicalHar } from "../../fixtures/historicalHar.js"; +it("excludes declared binary lengths through CLI, MCP and retained capture pages", async () => { + const root = await createTestTempDirectory("rea-har-byte-length-"); + const path = join(root, "capture.har"); + const fixture = historicalHar(); + const entry = fixture.log.entries[0]; + if (entry === undefined) throw new Error("fixture missing"); + const body = Buffer.alloc(12_345, "A"); + const content = body.toString("base64"); + const digest = createHash("sha256").update(body).digest("hex"); + await writeFile( + path, + JSON.stringify({ + log: { + ...fixture.log, + entries: [ + { + ...entry, + response: { + ...entry.response, + content: { + size: 99, + mimeType: "text/plain", + encoding: "base64", + text: content, + }, + }, + }, + ], + }, + }), + ); + const { call } = await connectLocalToolsMcp(); + const args = { capture_path: path, format: "har" }; + const control = await call("inspect_web_network_capture", args); + expect(control.isError).not.toBe(true); + const retained = parseEvidence(control.structuredContent); + const controlCapture = webNetworkCaptureSchema.parse( + retained.normalized_result, + ); + expect(controlCapture.records[0]?.binary_fields[0]).toMatchObject({ + state: "retained", + bytes: body.length, + content_base64: content, + sha256: digest, + }); + for (const literal of ["12345", "2345"]) { + // Only the derived count matches, so this cannot pass via another exclusion. + expect(content).not.toContain(literal); + expect(digest).not.toContain(literal); + const fromCli = await cli(path, "har", ["--sensitive-value", literal]); + expect(fromCli.ok, fromCli.stdout).toBe(true); + const evidence = parseEvidence(JSON.parse(fromCli.stdout)); + const response = await call("inspect_web_network_capture", { + ...args, + sensitive_values: [literal], + }); + expect(response.isError).not.toBe(true); + const fromMcp = parseEvidence(response.structuredContent); + expect(fromMcp.normalized_result).toEqual(evidence.normalized_result); + const capture = webNetworkCaptureSchema.parse(evidence.normalized_result); + expect(capture.records[0]?.reported).toMatchObject({ + response: { content: { size: 99, text: null } }, + }); + expect(capture.records[0]?.binary_fields[0]).toEqual({ + pointer: "/response/content/text", + representation: "har-base64-content", + state: "redacted", + bytes: null, + content_base64: null, + sha256: null, + }); + for (const detail of ["preview", "complete"]) { + const page = await call("inspect_analysis_view", { + source: { kind: "retained-evidence", evidence_id: fromMcp.evidence_id }, + view: { kind: "capture", detail }, + }); + expect(page.isError).not.toBe(true); + const result = parseEvidence(page.structuredContent); + expect(result.normalized_result).toMatchObject({ + items: [{ binary_fields: [{ state: "redacted", bytes: null }] }], + }); + } + } +}, 60_000); + it("reads actual upstream HAR packages in an owned process and retains selected producer order", async () => { const root = await mkdtemp(join(tmpdir(), "rea-history-har-")); onTestFinished(() => rm(root, { recursive: true, force: true })); diff --git a/tests/boundary/browser/sazWebCapture.test.ts b/tests/boundary/browser/sazWebCapture.test.ts new file mode 100644 index 000000000..69eca33b8 --- /dev/null +++ b/tests/boundary/browser/sazWebCapture.test.ts @@ -0,0 +1,499 @@ +import { createHash } from "node:crypto"; +import { execFile } from "node:child_process"; +import { readFile, unlink, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { promisify } from "node:util"; +import { fileURLToPath } from "node:url"; +import { gzipSync } from "node:zlib"; +import { Uint8ArrayReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js"; +import { Ajv2020 } from "ajv/dist/2020.js"; +import { expect, it as runtimeTest } from "vitest"; +import { z } from "zod"; +import { parseEvidence } from "../../../src/domain/evidence.js"; +import { webNetworkCaptureSchema } from "../../../src/domain/webNetworkCapture.js"; +import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +import { + NODE_CAPTURE_HEAP_ENFORCED, + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES, +} from "../../../src/browser/history/CaptureRelease.js"; +const hasMemoryBound = + NODE_CAPTURE_HEAP_ENFORCED || + NODE_CAPTURE_PROCESS_MEMORY_LIMIT_BYTES !== null; + +const it = runtimeTest.skipIf(!hasMemoryBound); + +// Synthetic member fixtures based on Telerik's SAZ layout; not a real-producer golden. +const compressedBody = gzipSync(Buffer.from("stored compressed body")); +const members = (): [string, Buffer][] => [ + [ + "raw/0042_s.txt", + Buffer.concat([ + Buffer.from( + "HTTP/1.1 200 OK\r\nContent-Encoding: gzip\r\nSet-Cookie: server-credential\r\n\r\n", + ), + compressedBody, + ]), + ], + [ + "raw/7_c.txt", + Buffer.concat([ + Buffer.from("POST /bytes HTTP/2.0\r\n:authority: example.test\r\n\r\n"), + Buffer.from([0xff, 0, 0x80]), + ]), + ], + [ + "raw/0042_c.txt", + Buffer.from( + "GET https://user:password@example.test/a HTTP/1.1\r\nAuthorization: Bearer client-credential\r\nCookie: cookie-credential\r\nX-Duplicate: one\r\nX-Duplicate: two\r\nX-Text: unicode-\u03b2\r\n\r\n", + ), + ], + [ + "raw/0042_m.xml", + Buffer.from( + '', + ), + ], + ["raw/0042_w.txt", Buffer.from("opaque websocket message file")], + ["raw/7_g.txt", Buffer.from([0, 1, 2])], + ["[Content_Types].xml", Buffer.from("")], +]; +const archive = async (entries = members(), password?: string, level = 6) => { + const writer = new ZipWriter(new Uint8ArrayWriter(), { + useWebWorkers: false, + level, + ...(password === undefined ? {} : { password }), + }); + for (const [name, bytes] of entries) + await writer.add(name, new Uint8ArrayReader(bytes)); + return Buffer.from(await writer.close()); +}; +const fixture = async (bytes: Buffer) => { + const root = await createTestTempDirectory("rea-saz-capture-"); + const path = join(root, "capture.saz"); + await writeFile(path, bytes); + return path; +}; +const entrypoint = fileURLToPath( + new URL("../../../scripts/rea.mjs", import.meta.url), +); +const cliResponse = async (path: string, extra: string[] = []) => { + try { + const { stdout } = await promisify(execFile)( + process.execPath, + [ + entrypoint, + "inspect-web-network-capture", + path, + "saz", + "--json", + ...extra, + ], + { timeout: 40_000, maxBuffer: 4 * 1024 * 1024 }, + ); + return { ok: true, stdout }; + } catch (cause: unknown) { + if ( + cause instanceof Error && + "stdout" in cause && + typeof cause.stdout === "string" + ) + return { ok: false, stdout: cause.stdout }; + throw cause; + } +}; +const cli = async (path: string, extra: string[] = []) => { + const result = await cliResponse(path, extra); + expect(result.ok, result.stdout).toBe(true); + return parseEvidence(JSON.parse(result.stdout)); +}; + +it("inspects native SAZ through the public CLI and MCP with equal evidence, bytes and archive coordinates", async () => { + const bytes = await archive(); + const path = await fixture(bytes); + const evidence = await cli(path, ["--record", "1", "--record", "0"]); + const capture = webNetworkCaptureSchema.parse(evidence.normalized_result); + expect(capture).toMatchObject({ + format: "saz", + total_records: 2, + runtime_attribution: "unknown", + records: [ + { ordinal: 1, reported: { session_id: "7", response: null } }, + { + ordinal: 0, + reported: { + session_id: "0042", + request: { url: "https://example.test/a" }, + response: { status: "200" }, + }, + }, + ], + }); + expect(capture.records[1]?.location).toEqual({ + kind: "archive-members", + members: [ + "raw/0042_s.txt", + "raw/0042_c.txt", + "raw/0042_m.xml", + "raw/0042_w.txt", + ], + }); + expect(capture.records[1]?.binary_fields).toContainEqual({ + pointer: "/response/body", + representation: "producer-bytes", + state: "retained", + content_base64: compressedBody.toString("base64"), + bytes: compressedBody.length, + sha256: createHash("sha256").update(compressedBody).digest("hex"), + }); + expect(capture.records[0]?.binary_fields).toContainEqual( + expect.objectContaining({ + pointer: "/request/body", + content_base64: "/wCA", + }), + ); + expect(capture.records[1]?.binary_fields).toContainEqual( + expect.objectContaining({ + pointer: "/request/body", + bytes: 0, + content_base64: "", + }), + ); + expect(capture.records[1]?.reported).toMatchObject({ + request: { + headers: [ + { name: "Authorization", value: null }, + { name: "Cookie", value: null }, + { name: "X-Duplicate", value: " one" }, + { name: "X-Duplicate", value: " two" }, + { name: "X-Text" }, + ], + }, + }); + expect(JSON.stringify(capture)).toContain("retained metadata"); + for (const secret of [ + "user:password", + "client-credential", + "server-credential", + "cookie-credential", + ]) + expect(JSON.stringify(capture)).not.toContain(secret); + expect(capture.artifact.sha256).toBe( + createHash("sha256").update(bytes).digest("hex"), + ); + expect(await readFile(path)).toEqual(bytes); + + const { client, call } = await connectLocalToolsMcp(); + const tool = (await client.listTools()).tools.find( + (item) => item.name === "inspect_web_network_capture", + ); + if (tool?.outputSchema === undefined) + throw new Error("Missing capture schema"); + const args = { capture_path: path, format: "saz", record_ordinals: [1, 0] }; + const ajv = new Ajv2020({ strict: false, validateFormats: false }); + expect(ajv.validate(tool.inputSchema, args)).toBe(true); + const response = await call("inspect_web_network_capture", args); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + const fromMcp = parseEvidence(response.structuredContent); + expect(fromMcp.normalized_result).toEqual(evidence.normalized_result); + const bundle = await client.callTool({ + name: "get_evidence_bundle", + arguments: { detail: "complete" }, + }); + const records = z + .object({ result: z.object({ records: z.array(z.unknown()) }) }) + .parse(bundle.structuredContent) + .result.records.map(parseEvidence); + expect( + records.find((record) => record.evidence_id === fromMcp.evidence_id), + ).toEqual(fromMcp); +}, 60_000); + +it("pages retained SAZ Evidence through public MCP and portable CLI after source deletion", async () => { + const path = await fixture(await archive()); + const { call } = await connectLocalToolsMcp(); + const args = { capture_path: path, format: "saz", record_ordinals: [1, 0] }; + const full = await call("inspect_web_network_capture", args); + const fromMcp = parseEvidence(full.structuredContent); + const capture = webNetworkCaptureSchema.parse(fromMcp.normalized_result); + const summaryArgs = { ...args, detail: "summary" }; + const summaryResponse = await call( + "inspect_web_network_capture", + summaryArgs, + ); + expect(summaryResponse.isError, JSON.stringify(summaryResponse)).not.toBe( + true, + ); + const summary = parseEvidence(summaryResponse.structuredContent); + expect(summary.normalized_result).toMatchObject({ + kind: "summary", + parent_evidence_id: fromMcp.evidence_id, + summary: { format: "saz", total_records: 2, retained_records: 2 }, + }); + expect(JSON.stringify(summary)).not.toContain( + compressedBody.toString("base64"), + ); + + // Retained pages must keep their snapshot semantics after the input disappears. + await unlink(path); + const source = { + kind: "retained-evidence", + evidence_id: fromMcp.evidence_id, + }; + const previewArgs = { + source, + view: { kind: "capture", offset: 0, limit: 1 }, + }; + const previewResponse = await call("inspect_analysis_view", previewArgs); + expect(previewResponse.isError, JSON.stringify(previewResponse)).not.toBe( + true, + ); + const preview = parseEvidence(previewResponse.structuredContent); + expect(preview.normalized_result).toMatchObject({ + items: [ + { + ordinal: 1, + reported: { + session_id: "7", + request: { method: "POST", url: "/bytes" }, + }, + }, + ], + coverage: { examined: 1, total: 2, next_offset: 1, exhausted: false }, + }); + expect(JSON.stringify(preview)).not.toContain("content_base64"); + const completeResponse = await call("inspect_analysis_view", { + source, + view: { kind: "capture", detail: "complete", offset: 1, limit: 1 }, + }); + expect(completeResponse.isError, JSON.stringify(completeResponse)).not.toBe( + true, + ); + const complete = parseEvidence(completeResponse.structuredContent); + expect(complete.normalized_result).toMatchObject({ + items: [capture.records[1]], + coverage: { next_offset: null, exhausted: true }, + }); + + const workflow = join(path, "..", "summary-view.json"); + await writeFile( + workflow, + JSON.stringify({ + source: { kind: "inline", evidence: fromMcp }, + view: { kind: "summary" }, + }), + ); + const standalone = await promisify(execFile)(process.execPath, [ + entrypoint, + "inspect-analysis-view", + workflow, + "--json", + ]); + expect( + parseEvidence(JSON.parse(standalone.stdout)).normalized_result, + ).toEqual(summary.normalized_result); +}, 60_000); + +it("keeps CRLF separators inside a body after LF-only HTTP headers", async () => { + const body = Buffer.from("\ufefffirst\r\n\r\nsecond\n\nthird"); + const bytes = await archive([ + [ + "raw/1_c.txt", + Buffer.concat([ + Buffer.from("POST https://example.test/ HTTP/1.1\nX-Test: request\n\n"), + body, + ]), + ], + [ + "raw/1_s.txt", + Buffer.concat([ + Buffer.from("HTTP/1.1 200 OK\nX-Test: response\n\n"), + body, + ]), + ], + ]); + const path = await fixture(bytes); + const capture = webNetworkCaptureSchema.parse( + (await cli(path)).normalized_result, + ); + expect(capture.records[0]?.reported).toMatchObject({ + request: { + headers: [{ name: "X-Test", value: " request" }], + body: body.toString("utf8"), + }, + response: { + headers: [{ name: "X-Test", value: " response" }], + body: body.toString("utf8"), + }, + }); + for (const pointer of ["/request/body", "/response/body"]) + expect(capture.records[0]?.binary_fields).toContainEqual({ + pointer, + representation: "producer-bytes", + state: "retained", + content_base64: body.toString("base64"), + bytes: body.length, + sha256: createHash("sha256").update(body).digest("hex"), + }); + expect(await readFile(path)).toEqual(bytes); +}); + +it("excludes explicit literals from XML, HTTP byte views, member coordinates and binary sidecars", async () => { + const path = await fixture(await archive()); + const result = await cli(path, [ + "--sensitive-value", + "0042", + "--sensitive-value", + "unicode-\u03b2", + "--sensitive-value", + compressedBody.toString("base64"), + "--sensitive-value", + "retained metadata", + ]); + const capture = webNetworkCaptureSchema.parse(result.normalized_result); + expect(capture.records[0]?.location).toEqual({ + kind: "unknown", + reason: "explicit-sensitive-value", + }); + expect(capture.records[0]?.binary_fields).toContainEqual({ + pointer: "/response/body", + representation: "producer-bytes", + state: "redacted", + bytes: null, + sha256: null, + content_base64: null, + }); + const text = JSON.stringify(result); + for (const secret of [ + "0042", + "unicode-", + "retained metadata", + compressedBody.toString("base64"), + createHash("sha256").update(compressedBody).digest("hex"), + ]) + expect(text).not.toContain(secret); +}); + +it("retains folded headers, stored chunk framing and BOM-marked UTF-16 metadata", async () => { + const body = "3\r\none\r\n0\r\n\r\n"; + const path = await fixture( + await archive([ + [ + "raw/1_s.txt", + Buffer.from( + `HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nX-Folded: first\r\n second\r\n\r\n${body}`, + ), + ], + [ + "raw/1_m.xml", + Buffer.from( + '\ufeff\u03b2]]>', + "utf16le", + ), + ], + [ + "raw/2_c.txt", + Buffer.from( + "CONNECT example.test:443 HTTP/1.1\nHost: example.test:443\n\n", + ), + ], + ]), + ); + const evidence = await cli(path); + const capture = webNetworkCaptureSchema.parse(evidence.normalized_result); + expect(capture.records[0]?.reported).toMatchObject({ + request: null, + response: { + body, + headers: [ + { name: "Transfer-Encoding", value: " chunked" }, + { name: "X-Folded", value: " first\r\n second" }, + ], + }, + }); + expect(capture.records[0]?.binary_fields).toContainEqual( + expect.objectContaining({ + pointer: "/response/body", + content_base64: Buffer.from(body).toString("base64"), + }), + ); + expect(JSON.stringify(capture.records[0]?.reported)).toContain("\u03b2"); + expect(capture.records[1]?.reported).toMatchObject({ + request: { method: "CONNECT", url: "example.test:443", body: "" }, + }); +}); + +it.each([ + "bad-http", + "bad-xml", + "dtd", + "unknown-member", + "encrypted", + "duplicate", + "crc", + "expanded-limit", +])("rejects %s before returning a selected subset", async (variant) => { + let entries = members(); + if (variant === "bad-http") + entries.push(["raw/8_c.txt", Buffer.from("malformed-private-input")]); + if (variant === "bad-xml") + entries.push(["raw/8_m.xml", Buffer.from("")]); + if (variant === "dtd") + entries.push([ + "raw/8_m.xml", + Buffer.from( + ']>&external;', + ), + ]); + if (variant === "unknown-member") + entries.push(["raw/8_unknown.txt", Buffer.from("unknown extension")]); + if (variant === "duplicate") + entries = [ + ["raw/8_c.txt", Buffer.from("GET /a HTTP/1.1\r\n\r\n")], + ["raw/9_c.txt", Buffer.from("GET /b HTTP/1.1\r\n\r\n")], + ]; + let bytes = await archive( + entries, + variant === "encrypted" ? "fixture-password" : undefined, + variant === "crc" ? 0 : 6, + ); + if (variant === "duplicate") + bytes = Buffer.from( + bytes.toString("latin1").replaceAll("raw/9_c.txt", "raw/8_c.txt"), + "latin1", + ); + if (variant === "crc") { + const offset = bytes.indexOf(Buffer.from("HTTP/1.1 200 OK")); + expect(offset).toBeGreaterThan(0); + bytes[offset + 9] = 0x35; + } + if (variant === "expanded-limit") { + const central = bytes.indexOf(Buffer.from([0x50, 0x4b, 0x01, 0x02])); + bytes.writeUInt32LE(33 * 1024 * 1024, central + 24); + } + const path = await fixture(bytes); + const result = await cliResponse(path, ["--record", "0"]); + expect(result.ok, result.stdout).toBe(false); + expect(JSON.parse(result.stdout).category).toBe( + ["encrypted", "unknown-member", "dtd"].includes(variant) + ? "unsupported_provider" + : variant === "expanded-limit" + ? "execution_failure" + : "invalid_input", + ); + if (variant === "expanded-limit") + expect(JSON.parse(result.stdout).code).toBe("unreadable_output"); + expect(JSON.stringify(result)).not.toContain("malformed-private-input"); +}); + +runtimeTest.runIf(!hasMemoryBound)( + "reports SAZ unavailable when its runtime cannot enforce decoder memory", + async () => { + const response = await cliResponse(await fixture(await archive())); + expect(response.ok).toBe(false); + expect(JSON.parse(response.stdout)).toMatchObject({ + code: "capability_unavailable", + }); + }, +); diff --git a/tests/boundary/captures/captureProvider.test.ts b/tests/boundary/captures/captureProvider.test.ts index 9f5fb4afc..2428b39d4 100644 --- a/tests/boundary/captures/captureProvider.test.ts +++ b/tests/boundary/captures/captureProvider.test.ts @@ -1,3 +1,4 @@ +import { packetFieldsCatalogSchema } from "../../../src/domain/captures/packetFields.js"; import { OwnedCommandFailure } from "../../../src/process/OwnedCommand.js"; import { it, expect, onTestFinished } from "vitest"; import { writeFile, readdir, chmod, symlink } from "node:fs/promises"; @@ -20,14 +21,15 @@ const fixture = async (mode = "ok", failCleanup = false) => { await writeFile( script, `import {readFileSync, writeFileSync, chmodSync, truncateSync} from 'node:fs'; -if (process.argv.includes('--version')) { console.log('TShark (Wireshark) 4.6.9 (fixture)'); console.error('version warning'); } +if (process.argv.includes('--version')) { console.log(${JSON.stringify(mode)} === 'bad-version' ? 'TShark (Wireshark) 3.0.0' : 'TShark (Wireshark) 4.6.9 (fixture)'); console.error('version warning'); } else if (${JSON.stringify(mode)} === 'nonzero') { console.error('invalid decoder'); process.exitCode = 1; } else if (${JSON.stringify(mode)} === 'malformed-copy') { chmodSync('capture', 0o600); writeFileSync('capture', 'changed'); } else if (${JSON.stringify(mode)} === 'oversized-copy') { chmodSync('capture', 0o600); truncateSync('capture', 32 * 1024 * 1024 + 1); console.log('[]'); } -else if (${JSON.stringify(mode)} === 'overflow') process.stdout.write('x'.repeat(5 * 1024 * 1024)); +else if (${JSON.stringify(mode)} === 'overflow') process.stdout.write('x'.repeat((process.argv.includes('-G') ? 33 : 5) * 1024 * 1024)); else if (${JSON.stringify(mode)} === 'wait') { console.log('ready'); setInterval(() => {}, 1000); } else if (${JSON.stringify(mode)} === 'invalid-json') console.log('not json'); else if (${JSON.stringify(mode)} === 'many') console.log(JSON.stringify(Array.from({length:90},(_,i)=>({_source:{layers:{"frame.number":[String(i+1)],"ip.addr":["192.0.2.1"]}}})))); +else if (process.argv.includes('-G')) { console.log('P\\tUniversal Serial Bus\\tusb\\nF\\tVendor ID\\tusb.idVendor\\tFT_UINT16\\tusb\\tBASE_HEX\\t0x0\\t\\nF\\tOther Vendor\\tusb.idVendor\\tFT_UINT32\\tusb\\tBASE_HEX\\t0x0\\tSecond registration\\nP\\tInternet Protocol\\tip\\nF\\tAddress\\tip.addr\\tFT_IPv4\\tip\\t\\t0x0\\tSource or destination'); console.error('glossary warning'); } else { if(readFileSync('capture', 'utf8') !== 'recording bytes') throw Error('wrong copy'); console.log(JSON.stringify([{_source:{layers:{"frame.number":["1"],"ip.addr":["192.0.2.1","192.0.2.2"]}}}])); console.error('producer warning'); } `, ); @@ -301,6 +303,9 @@ it("retains a completed observation when cancellation arrives at the service bou const execution = await f.service.provider.inspect(input); if (!execution.ok) throw execution.error; const service = new PacketCaptureService({ + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, inspect: async () => { f.controller.abort(); return execution; @@ -465,3 +470,158 @@ it("rejects oversized selector lists and UTF-8 argv expansion before provider wo } expect(f.calls()).toBe(0); }); + +it("discovers installed protocols and field definitions without a capture", async () => { + const f = await fixture(); + for (const [input, expected] of [ + [ + { query: "USB" }, + { + records: [{ abbreviation: "usb", kind: "protocol", field_type: null }], + output_window: { examined: 2, matching: 1, returned: 1 }, + }, + ], + [ + { kind: "fields", protocol: "usb", limit: 1 }, + { + records: [ + { + abbreviation: "usb.idVendor", + field_type: "FT_UINT16", + source_line: 2, + }, + ], + output_window: { + examined: 3, + matching: 2, + returned: 1, + has_more: true, + }, + }, + ], + [ + { kind: "fields", protocol: "usb", offset: 1, limit: null }, + { + records: [ + { + abbreviation: "usb.idVendor", + field_type: "FT_UINT32", + source_line: 3, + }, + ], + output_window: { matching: 2, returned: 1, has_more: false }, + }, + ], + [ + { kind: "fields", query: "destination" }, + { + records: [ + { + abbreviation: "ip.addr", + description: "Source or destination", + display_base: "", + }, + ], + }, + ], + [ + { query: "no-such-protocol" }, + { records: [], output_window: { matching: 0, returned: 0 } }, + ], + ] as const) { + const result = await f.service.inspectFields(input); + if (!result.ok) throw result.error; + const report = packetFieldsCatalogSchema.parse( + result.value.normalized_result, + ); + expect(report).toMatchObject(expected); + expect(report.tool.arguments).toEqual(["-G", "fields"]); + expect(report.tool.version_diagnostics).toBe("version warning\n"); + expect(report.diagnostics).toBe("glossary warning\n"); + expect(report.limits.output_bytes).toBe(32 * 1024 * 1024); + } + expect( + (await readdir(f.directory)).filter((name) => name.startsWith("decoder-")), + ).toEqual([]); +}); + +it("shares discovery admission with inspection and refuses work after shutdown", async () => { + const f = await fixture("gated"); + const active = f.service.inspect({ path: f.path, fields: ["ip.addr"] }); + await f.acquired; + const busy = await f.service.inspectFields({}); + f.release(); + if (!(await active).ok) throw new Error("Inspection failed"); + expect(busy).toMatchObject({ + ok: false, + error: { operation: "inspect_packet_fields", resource: "capacity" }, + }); + await f.service.close(); + expect(await f.service.inspectFields({})).toMatchObject({ + ok: false, + error: { + operation: "inspect_packet_fields", + _tag: "AnalysisCancelledError", + }, + }); +}); + +it.each([ + "bad-version", + "nonzero", + "overflow", + "wait", + "oversized-tool", + "invalid-json", +])("retains field discovery failure facts: %s", async (mode) => { + const f = await fixture(mode); + const result = await f.service.inspectFields( + {}, + { signal: f.controller.signal }, + ); + if (result.ok) throw new Error("Expected failure"); + expect(result.error).toMatchObject({ operation: "inspect_packet_fields" }); + if (mode === "bad-version") + expect(result.error.capturedOutput).toMatchObject({ + stdout: "TShark (Wireshark) 3.0.0\n", + stderr: "version warning\n", + }); + if (mode === "invalid-json") + expect(result.error.capturedOutput?.stdout).toBe("not json\n"); + if (mode === "overflow") + expect(result.error).toMatchObject({ + resource: "memory", + reportedLimits: { output_bytes: 32 * 1024 * 1024 }, + }); +}); + +it("retains completed discovery on late cancellation and cleanup failure", async () => { + for (const mode of ["post-run-abort", "cleanup"]) { + const f = await fixture(mode, mode === "cleanup"); + const result = await f.service.inspectFields( + { query: "usb" }, + { signal: f.controller.signal }, + ); + expect(result).toMatchObject({ + ok: false, + error: { + partialObservation: { + operation: "inspect_packet_fields", + normalized_result: { records: [{ abbreviation: "usb" }] }, + }, + }, + }); + if (mode === "cleanup") { + await f.service.inspectFields({}); + await f.service.inspect({ path: f.path, fields: ["ip.addr"] }); + expect(f.calls()).toBe(2); + for (let attempt = 0; attempt < 2; attempt++) + await expect(f.service.close()).rejects.toMatchObject({ + operation: "inspect_packet_fields", + cleanupIncomplete: true, + }); + } + f.allowCleanup(); + await f.service.close(); + } +}); diff --git a/tests/boundary/captures/fieldDiscovery.test.ts b/tests/boundary/captures/fieldDiscovery.test.ts new file mode 100644 index 000000000..79a27f7bf --- /dev/null +++ b/tests/boundary/captures/fieldDiscovery.test.ts @@ -0,0 +1,67 @@ +import { expect, it } from "vitest"; +import { inspectPacketFieldsInputSchema } from "../../../src/domain/captures/packetFields.js"; +import { parseFieldDiscovery } from "../../../src/captures/parseFieldDiscovery.js"; + +it("keeps duplicate registrations and source ordinals instead of overwriting abbreviations", () => { + const text = + "P\tUSB\tusb\r\nF\tVendor\tusb.idVendor\tFT_UINT16\tusb\tBASE_HEX\t0x0\t\r\nF\tVendor\tusb.idVendor\tFT_UINT32\tusb\tBASE_HEX\t0x0\t"; + const result = parseFieldDiscovery( + text, + inspectPacketFieldsInputSchema.parse({ + kind: "fields", + query: "idVendor", + offset: 1, + }), + ); + expect(result.records).toMatchObject([ + { + source_line: 3, + abbreviation: "usb.idVendor", + field_type: "FT_UINT32", + description: "", + }, + ]); + expect(result.output_window).toEqual({ + examined: 2, + matching: 2, + returned: 1, + has_more: false, + }); +}); + +it("rejects damaged records even outside the selected page", () => { + for (const text of [ + "", + "P\tmissing", + "F\tname\tabbr", + "P\tname\t", + "P\tUSB\tusb\nBAD", + ]) + expect(() => + parseFieldDiscovery( + text, + inspectPacketFieldsInputSchema.parse({ limit: 1 }), + ), + ).toThrow(); +}); + +it("bounds explicit full-result expansion while allowing a page from the same large glossary", () => { + const text = "P\t" + "Long name ".repeat(30) + "\tabbr\n"; + const glossary = text.repeat(6000); + expect(() => + parseFieldDiscovery( + glossary, + inspectPacketFieldsInputSchema.parse({ limit: null }), + ), + ).toThrow("representation budget"); + const result = parseFieldDiscovery( + glossary, + inspectPacketFieldsInputSchema.parse({ offset: 5999, limit: 1 }), + ); + expect(result.output_window).toEqual({ + examined: 6000, + matching: 6000, + returned: 1, + has_more: false, + }); +}); diff --git a/tests/boundary/cli/analysisSelectorCli.test.ts b/tests/boundary/cli/analysisSelectorCli.test.ts index 404cad6a2..5e89daa2b 100644 --- a/tests/boundary/cli/analysisSelectorCli.test.ts +++ b/tests/boundary/cli/analysisSelectorCli.test.ts @@ -12,6 +12,38 @@ const selectors = [ ] as const; describe("CLI analysis selector boundaries", () => { + cliTest( + "accepts file offsets and rejects mixed coordinate selectors before opening a target", + async ({ cli }) => { + const selected = await cli.run({ + arguments: [ + "decompile", + "does-not-exist", + "--file-offset=0x210", + "--json", + ], + environment: { REA_LOG_LEVEL: "silent" }, + }); + expect(selected.json).toMatchObject({ code: "target_unavailable" }); + const conflicting = await cli.run({ + arguments: [ + "decompile", + "does-not-exist", + "0x140001010", + "--file-offset=0x210", + "--json", + ], + environment: { REA_LOG_LEVEL: "silent" }, + }); + expect(conflicting.json).toMatchObject({ + code: "invalid_request", + details: { + operation: "procedure_pseudo_code", + issues: [{ path: ["file-offset"], reason: "invalid_value" }], + }, + }); + }, + ); cliTest( "rejects missing and conflicting selectors before opening a target", async ({ cli }) => { diff --git a/tests/boundary/cli/apktoolBooleanOptions.test.ts b/tests/boundary/cli/apktoolBooleanOptions.test.ts new file mode 100644 index 000000000..5c5578c18 --- /dev/null +++ b/tests/boundary/cli/apktoolBooleanOptions.test.ts @@ -0,0 +1,85 @@ +import { expect, it } from "vitest"; +import { Cli } from "incur"; +import pino from "pino"; + +import type { ApktoolResourceAnalysisPort } from "../../../src/application/apktool/ApktoolResourceAnalysisPort.js"; +import { createAnalysisExecution } from "../../../src/application/AnalysisProvider.js"; +import { registerApktoolCommands } from "../../../src/cli/apktoolCommands.js"; +import { presentOmittableDefaults } from "../../../src/cli/omittableDefaults.js"; +import type { ApktoolRequest } from "../../../src/domain/apktool/apktoolResourceAnalysis.js"; +import { ok } from "../../../src/domain/result.js"; + +const invoke = async (argv: readonly string[]) => { + const requests: ApktoolRequest[] = []; + const provider: ApktoolResourceAnalysisPort = { + async inspectAvailability() { + throw new Error("unexpected provider probe"); + }, + async close() {}, + async execute(request) { + requests.push(request); + return ok( + createAnalysisExecution( + { strings: [] }, + { id: "apktool", name: "Apktool", version: null }, + ), + ); + }, + }; + const cli = Cli.create("rea", { sync: false }); + registerApktoolCommands(cli, pino({ level: "silent" }), {}, provider); + presentOmittableDefaults(cli); + + let stdout = ""; + let exitCode = 0; + await cli.serve([...argv], { + env: {}, + exit: (code) => { + exitCode = code; + }, + stdout: (text) => { + stdout += text; + }, + }); + return { exitCode, stdout, requests }; +}; + +it("dispatches --no-strings as include_strings false", async () => { + const result = await invoke([ + "decode-android-resources", + "/targets/app.apk", + "--no-strings", + "--json", + ]); + + expect(result.exitCode).toBe(0); + expect(result.requests).toEqual([ + { + operation: "decode_android_resources", + input: { path: "/targets/app.apk", include_strings: false }, + }, + ]); +}); + +it("keeps string projection enabled when the flag is omitted", async () => { + const result = await invoke([ + "decode-android-resources", + "/targets/app.apk", + "--json", + ]); + + expect(result.exitCode).toBe(0); + expect(result.requests).toEqual([ + { + operation: "decode_android_resources", + input: { path: "/targets/app.apk", include_strings: true }, + }, + ]); +}); + +it("documents the supported negative flag in command help", async () => { + const result = await invoke(["decode-android-resources", "--help"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("--no-strings"); +}); diff --git a/tests/boundary/cli/captureCleanup.test.ts b/tests/boundary/cli/captureCleanup.test.ts index 1ec6adedd..6e5882cd4 100644 --- a/tests/boundary/cli/captureCleanup.test.ts +++ b/tests/boundary/cli/captureCleanup.test.ts @@ -5,6 +5,7 @@ import { silentLogger } from "../../../src/logger.js"; import { createEvidence } from "../../../src/domain/evidence.js"; import { ProviderCleanupError } from "../../../src/domain/providerCleanupError.js"; import { err } from "../../../src/domain/result.js"; +import { AnalysisInputError } from "../../../src/domain/analysisErrorCore.js"; it.each([false, true])( "awaits cleanup retry and preserves completed output when retry failure is %s", @@ -32,6 +33,9 @@ it.each([false, true])( silentLogger, {}, { + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, inspect: async () => err(original), close: async () => { await Promise.resolve(); @@ -79,6 +83,111 @@ it.each([false, true])( }, ); +it("keeps the primary CLI failure when close throws an untyped error", async () => { + const cli = Cli.create("capture-cleanup-primary-test", { sync: false }); + registerCaptureCommands( + cli, + silentLogger, + {}, + { + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, + inspect: async () => + err( + new AnalysisInputError("inspect_packet_capture", { + userMessage: "The selected capture input was rejected.", + }), + ), + close: async () => { + throw new Error("raw close failure"); + }, + }, + ); + let stdout = ""; + await cli.serve( + [ + "inspect-packet-capture", + "recording.pcap", + "--fields", + "ip.addr", + "--format", + "json", + ], + { + stdout: (text) => { + stdout += text; + }, + exit: () => {}, + }, + ); + expect(JSON.parse(stdout)).toMatchObject({ + code: "cleanup_incomplete", + message: "The selected capture input was rejected.", + details: { + diagnostics: { + primary_error: { code: "invalid_request" }, + }, + resources: [], + }, + }); +}); + +it("closes the service and retains an unexpected producer rejection", async () => { + const cli = Cli.create("capture-producer-rejection-test", { sync: false }); + let closed = false; + registerCaptureCommands( + cli, + silentLogger, + {}, + { + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, + inspect: async () => { + throw new Error("raw producer failure"); + }, + close: async () => { + closed = true; + throw new Error("raw close failure"); + }, + }, + ); + let stdout = ""; + await cli.serve( + [ + "inspect-packet-capture", + "recording.pcap", + "--fields", + "ip.addr", + "--format", + "json", + ], + { + stdout: (text) => { + stdout += text; + }, + exit: () => {}, + }, + ); + expect(closed).toBe(true); + expect(JSON.parse(stdout)).toMatchObject({ + code: "cleanup_incomplete", + details: { + diagnostics: { + primary_error: { + code: "execution_failure", + details: { + operation: "inspect_packet_capture", + provider_id: "tshark-capture", + }, + }, + cleanup_error: { code: "cleanup_incomplete" }, + }, + }, + }); +}); + it("rejects an oversized selector budget before the CLI invokes its service", async () => { const cli = Cli.create("capture-selector-test", { sync: false }); let called = false; @@ -87,6 +196,9 @@ it("rejects an oversized selector budget before the CLI invokes its service", as silentLogger, {}, { + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, inspect: async () => { called = true; throw new Error("Must not inspect"); @@ -125,6 +237,9 @@ it("rejects conflicting output options before the CLI invokes its service", asyn silentLogger, {}, { + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, inspect: async () => { called = true; throw new Error("Must not inspect"); diff --git a/tests/boundary/cli/developmentTests.test.ts b/tests/boundary/cli/developmentTests.test.ts index 21d8c5127..2987206c8 100644 --- a/tests/boundary/cli/developmentTests.test.ts +++ b/tests/boundary/cli/developmentTests.test.ts @@ -1,100 +1,175 @@ -import { execFile } from "node:child_process"; -import { mkdir, symlink, writeFile } from "node:fs/promises"; -import { join, resolve } from "node:path"; -import { promisify } from "node:util"; +import { + copyFile, + mkdir, + readFile, + symlink, + writeFile, +} from "node:fs/promises"; +import { join } from "node:path"; import { describe, expect, it } from "vitest"; +import { execFileOutput } from "../../../src/process/ExecFileOutput.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; -const execute = promisify(execFile); -const runner = resolve("scripts/run-development-tests.mjs"); - -describe("development test runner", () => { - it("rejects nonexistent explicit paths instead of returning a zero-test success", async () => { - await expect( - execute(process.execPath, [ - runner, - "focused", - "src/missing.test.ts", - "--dry-run", - ]), - ).rejects.toMatchObject({ code: 1 }); +const run = (root: string, command: string, arguments_: readonly string[]) => + execFileOutput(command, arguments_, { + cwd: root, + stopSignal: "SIGTERM", + timeout: 30_000, + maxBuffer: 1024 * 1024, }); - it("reports actionable remediation when the comparison base is unavailable", async () => { - await expect( - execute(process.execPath, [ - runner, - "changed", - "--base", - "missing-test-base", - "--dry-run", +const git = (root: string, ...arguments_: string[]) => + run(root, "git", arguments_); + +const commit = (root: string, message: string) => + git( + root, + "-c", + "user.name=REA fixture", + "-c", + "user.email=fixture@example.test", + "-c", + "commit.gpgSign=false", + "commit", + "--quiet", + "-m", + message, + ); + +const fixture = async () => { + const root = await createTestTempDirectory("rea-development-tests-"); + await mkdir(join(root, "scripts", "lib"), { recursive: true }); + await mkdir(join(root, "src")); + for (const path of [ + "scripts/run-development-tests.mjs", + "scripts/lib/development-tests.mjs", + ]) + await copyFile(join(process.cwd(), path), join(root, path)); + await symlink( + join(process.cwd(), "node_modules"), + join(root, "node_modules"), + process.platform === "win32" ? "junction" : undefined, + ); + await writeFile(join(root, "package.json"), '{"type":"module"}\n'); + await writeFile(join(root, ".gitignore"), "node_modules\nselected.txt\n"); + await writeFile( + join(root, "vitest.config.mjs"), + 'export default { test: { projects: [{ test: { name: "domain", include: ["src/**/*.test.ts"] } }] } };\n', + ); + await writeFile(join(root, "src/value.ts"), "export const value = 1;\n"); + await writeFile( + join(root, "src/value.test.ts"), + 'import { expect, it } from "vitest"; import { writeFileSync } from "node:fs"; import { value } from "./value.js"; it("checks the selected source", () => { expect(value).toBe(1); writeFileSync("selected.txt", String(value)); });\n', + ); + await git(root, "init", "--quiet", "-b", "main"); + await git(root, "add", "."); + await commit(root, "fixture"); + return root; +}; + +const testCommand = (root: string, ...arguments_: string[]) => + run(root, process.execPath, [ + "scripts/run-development-tests.mjs", + ...arguments_, + ]); + +describe("development test runner public CLI", () => { + it("runs an explicitly selected source test on a clean tree without build artifacts", async () => { + const root = await fixture(); + const { stdout: status } = await git(root, "status", "--porcelain"); + expect(status).toBe(""); + await testCommand(root, "local", "src/value.test.ts"); + expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1"); + }); + + it("plans an exact local test without building", async () => { + const root = await fixture(); + const { stdout } = await testCommand( + root, + "local", + "src/value.test.ts", + "--dry-run", + ); + expect(JSON.parse(stdout)).toMatchObject({ + needsBuild: false, + artifactTasks: [], + vitestArguments: expect.arrayContaining([ + "run", + "--project", + "domain", + "--project", + "services", + "--project", + "adapters", + "--project", + "composition", + "--project", + "conformance", + "--project", + "evaluation", + "src/value.test.ts", ]), + }); + }); + + it("uses committed dependency changes to select source tests and reports failures", async () => { + const root = await fixture(); + const { stdout: base } = await git(root, "rev-parse", "HEAD"); + await writeFile(join(root, "src/value.ts"), "export const value = 2;\n"); + await git(root, "add", "src/value.ts"); + await commit(root, "change dependency"); + await expect( + testCommand(root, "changed", "--base", base.trim()), + ).rejects.toMatchObject({ + code: 1, + stdout: expect.stringContaining("src/value.test.ts"), + stderr: expect.stringContaining("expected 2 to be 1"), + }); + }); + + it("runs changed and focused tests from a committed branch regression", async () => { + const root = await fixture(); + const { stdout: baseline } = await git(root, "rev-parse", "HEAD"); + await git(root, "update-ref", "refs/remotes/origin/main", baseline.trim()); + await git(root, "switch", "--quiet", "-c", "regression"); + await writeFile(join(root, "src/value.ts"), "export const value = 2;\n"); + await writeFile( + join(root, "src/value.test.ts"), + 'import { expect, it } from "vitest"; import { value } from "./value.js"; it("checks current source", () => expect(value).toBe(2));\n', + ); + await git(root, "add", "src"); + await commit(root, "regression fix"); + expect((await git(root, "status", "--porcelain")).stdout).toBe(""); + + const changed = await testCommand(root, "changed"); + expect(changed.stdout).toContain("1 passed"); + const focused = await testCommand(root, "focused", "src/value.test.ts"); + expect(focused.stdout).toContain("1 passed"); + }, 60_000); + + it("reports a missing comparison base and rejects missing or compiled-boundary paths", async () => { + const root = await fixture(); + await expect( + testCommand(root, "changed", "--base", "missing-test-base", "--dry-run"), ).rejects.toMatchObject({ code: 1, stderr: expect.stringContaining( "Fetch origin/main or pass --base REVISION", ), }); - }); - - it("runs a committed branch regression through real Git and Vitest without dist", async () => { - const root = await createTestTempDirectory("rea-development-tests-"); - await mkdir(join(root, "src")); - await symlink( - resolve("node_modules"), - join(root, "node_modules"), - "junction", - ); - await writeFile( - join(root, "package.json"), - JSON.stringify({ type: "module" }), - ); - await writeFile(join(root, ".gitignore"), "node_modules\n"); - await writeFile( - join(root, "vitest.config.ts"), - `export default { test: { projects: [{ test: { name: "domain", include: ["src/**/*.test.ts"] } }] } };`, - ); - await writeFile(join(root, "src/value.ts"), "export const value = 1;\n"); - await writeFile( - join(root, "src/value.test.ts"), - `import { it, expect } from "vitest"; import { value } from "./value"; it("checks current source", () => expect(value).toBe(1));\n`, - ); - const git = (arguments_: string[]) => - execute("git", arguments_, { cwd: root }); - await git(["init", "-b", "main"]); - await git(["add", ".gitignore", "package.json", "vitest.config.ts", "src"]); - const commit = [ - "-c", - "user.name=REA fixture", - "-c", - "user.email=fixture@example.test", - "commit", - "-m", - "fixture", - ]; - await git(commit); - const { stdout: baseline } = await git(["rev-parse", "HEAD"]); - await git(["update-ref", "refs/remotes/origin/main", baseline.trim()]); - await git(["switch", "-c", "regression"]); - await writeFile(join(root, "src/value.ts"), "export const value = 2;\n"); - await writeFile( - join(root, "src/value.test.ts"), - `import { it, expect } from "vitest"; import { value } from "./value"; it("checks current source", () => expect(value).toBe(2));\n`, - ); - await git(["add", "src"]); - await git(commit); - expect((await git(["status", "--porcelain"])).stdout).toBe(""); - const { stdout } = await execute(process.execPath, [runner, "changed"], { - cwd: root, + await expect( + testCommand(root, "focused", "src/missing.test.ts"), + ).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("ENOENT"), }); - expect(stdout).toContain("1 passed"); - const explicit = await execute( - process.execPath, - [runner, "focused", "src/value.test.ts"], - { cwd: root }, - ); - expect(explicit.stdout).toContain("1 passed"); - }, 30_000); + await expect( + testCommand(root, "local", "tests/acceptance/runtime.test.ts"), + ).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("Use test:focused"), + }); + }); }); diff --git a/tests/boundary/cli/dylibResolutionCli.test.ts b/tests/boundary/cli/dylibResolutionCli.test.ts index b74dae71e..66fa21ba3 100644 --- a/tests/boundary/cli/dylibResolutionCli.test.ts +++ b/tests/boundary/cli/dylibResolutionCli.test.ts @@ -4,11 +4,13 @@ import { dirname, join } from "node:path"; import { describe, expect } from "vitest"; import { + CPU, FILE_TYPE, LC, buildVersionCommand, dylibCommand, dyldEnvironmentCommand, + fatImage, machoImage, rpathCommand, } from "../../../src/artifacts/apple/MachoImage.fixture.js"; @@ -471,6 +473,64 @@ cliTest( }, ); +cliTest( + "reports each same-named slice's own embedded dyld environment", + async ({ cli }) => { + // arm64e and arm64e.x1 slices both report the architecture name arm64e. + // A plain x86_64 slice keeps the bundle openable on x64 hosts. + for (const [settings, expected] of [ + [[null, "DYLD_PRINT_RPATHS=1"], ["DYLD_PRINT_RPATHS=1"]], + [ + ["DYLD_PRINT_LIBRARIES=1", "DYLD_PRINT_RPATHS=1"], + ["DYLD_PRINT_LIBRARIES=1", "DYLD_PRINT_RPATHS=1"], + ], + ] as const) { + const app = await fixtureApp(); + await writeFiles(app, { + "Contents/MacOS/App": fatImage([ + ...[CPU.arm64e, CPU.arm64eX1].map((cpu, index) => { + const setting = settings[index]; + return { + cpu, + bytes: machoImage({ + cpu, + commands: + setting === null || setting === undefined + ? [] + : [dyldEnvironmentCommand(setting)], + }), + }; + }), + { cpu: CPU.x86_64, bytes: machoImage({ cpu: CPU.x86_64 }) }, + ]), + }); + const result = await cli.run({ + arguments: [ + "trace-dylib-resolution", + app, + "--root", + "Contents/MacOS/App", + "--json", + ], + environment: ENVIRONMENT, + }); + expect(result.exitCode, JSON.stringify(result.json)).toBe(0); + const trace = dylibResolutionResultSchema.parse( + parseEvidence(result.json).normalized_result, + ); + expect( + trace.roots.filter(({ architecture }) => architecture === "arm64e"), + ).toHaveLength(2); + const environments = trace.findings + .filter(({ kind }) => kind === "dyld-environment-present") + .map(({ explanation }) => + expected.filter((setting) => explanation.includes(setting)), + ); + expect(environments).toEqual(expected.map((setting) => [setting])); + } + }, +); + cliTest( "retains definitive load findings for an explicitly selected app library root", async ({ cli }) => { diff --git a/tests/boundary/cli/nativeSignatureCli.test.ts b/tests/boundary/cli/nativeSignatureCli.test.ts index 9302d9c24..e30581db4 100644 --- a/tests/boundary/cli/nativeSignatureCli.test.ts +++ b/tests/boundary/cli/nativeSignatureCli.test.ts @@ -21,14 +21,14 @@ const adHocProgram = async (directory: string, name: string) => { describe.skipIf(process.platform !== "darwin")( "native signature CLI with echoed path text", () => { - cliTest( - "does not read signature fields from the file name codesign echoes", - async ({ cli }) => { + cliTest.for(["\n", "\r\n"])( + "does not read signature fields from the file name codesign echoes (%j)", + async (newline, { cli }) => { const directory = await createTestTempDirectory("rea-signature-"); const forged = "Developer ID Application: Example (ABCDE12345)"; const program = await adHocProgram( directory, - `tool\nAuthority=${forged}\nTeamIdentifier=ABCDE12345`, + `tool${newline}Authority=${forged}${newline}Identifier=forged${newline}TeamIdentifier=ABCDE12345`, ); const unsignedName = await adHocProgram( directory, @@ -75,7 +75,7 @@ describe.skipIf(process.platform !== "darwin")( normalized_result: { identifier: expect.stringMatching( new RegExp( - `^tool\\nAuthority=${forged.replace(/[()]/gu, "\\$&")}\\nTeamIdentifier=ABCDE12345-`, + `^tool${newline}Authority=${forged.replace(/[()]/gu, "\\$&")}${newline}Identifier=forged${newline}TeamIdentifier=ABCDE12345-`, "u", ), ), diff --git a/tests/boundary/cli/pcapCli.test.ts b/tests/boundary/cli/pcapCli.test.ts new file mode 100644 index 000000000..1eb61cdcf --- /dev/null +++ b/tests/boundary/cli/pcapCli.test.ts @@ -0,0 +1,37 @@ +import { expect, it } from "vitest"; + +import { expectConfigurationRefusal, serveCli } from "./cliServeHarness.js"; + +it.each(["inspect-pcap-client", "inspect-pcap-capture"])( + "%s advertises a schema through the public CLI", + async (command) => { + const result = await serveCli([command, "--schema", "--json"]); + expect(result.exitCode).toBe(0); + expect(JSON.parse(result.stdout)).toBeTruthy(); + }, +); + +it.each([ + ["inspect-pcap-client"], + ["inspect-pcap-capture", "/nonexistent/capture.pcap"], +])("%s names the missing Wireshark tool to configure", async (...argv) => { + const result = await serveCli([...argv, "--json"], { + REA_TSHARK_COMMAND: "/nonexistent/tshark", + REA_CAPINFOS_COMMAND: "/nonexistent/capinfos", + }); + expectConfigurationRefusal( + result, + "Cannot run selected tool /nonexistent/tshark", + ); + expectConfigurationRefusal(result, "through absolute REA_TSHARK_COMMAND"); +}); + +it("names a relative tool selection as configuration to fix", async () => { + const result = await serveCli(["inspect-pcap-client", "--json"], { + REA_TSHARK_COMMAND: "tshark", + }); + expectConfigurationRefusal( + result, + "REA_TSHARK_COMMAND must be an absolute path to the tshark binary", + ); +}); diff --git a/tests/boundary/cli/signalCleanup.test.ts b/tests/boundary/cli/signalCleanup.test.ts index 594a46cc0..dc706c17c 100644 --- a/tests/boundary/cli/signalCleanup.test.ts +++ b/tests/boundary/cli/signalCleanup.test.ts @@ -30,6 +30,9 @@ it.each([ silentLogger, {}, { + inspectDecoders: async () => { + throw new Error("Unexpected discovery call"); + }, decode: async () => { called = true; throw new Error("Must not decode"); @@ -84,6 +87,9 @@ it.each([false, true])( silentLogger, {}, { + inspectDecoders: async () => { + throw new Error("Unexpected discovery call"); + }, decode: async () => err(original), close: async () => { await Promise.resolve(); diff --git a/tests/boundary/filesystem/analysisSnapshotInput.test.ts b/tests/boundary/filesystem/analysisSnapshotInput.test.ts new file mode 100644 index 000000000..85bd7b7d1 --- /dev/null +++ b/tests/boundary/filesystem/analysisSnapshotInput.test.ts @@ -0,0 +1,88 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; + +import { describe, expect, it } from "vitest"; + +import { readAnalysisSnapshot } from "../../../src/application/binary/AnalysisSnapshotFiles.js"; +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import { + snapshotBinding, + snapshotTarget, +} from "../../../src/domain/analysisSnapshot.js"; +import { + ANALYSIS_SNAPSHOT_PROFILE, + ANALYSIS_SNAPSHOT_TARGET, +} from "../../../src/domain/analysisSnapshot.fixture.js"; +import { createEvidenceBundle } from "../../../src/domain/evidenceBundle.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +describe.each([ + { mode: "native", paddingBytes: 0 }, + { mode: "streamed", paddingBytes: 9 * 1024 * 1024 }, +])("analysis snapshot input ($mode)", ({ paddingBytes }) => { + it.each(["[]", "null", "5", '"x"', "true"])( + "classifies a readable %s root as invalid content, not an I/O failure", + async (document) => { + const root = await createTestTempDirectory("rea-snapshot-root-"); + const path = join(root, "snapshot.json"); + const encoded = `${" ".repeat(paddingBytes)}${document}`; + await writeFile(path, encoded); + + const loaded = await readAnalysisSnapshot(path); + if (loaded.ok) throw new Error("Expected a non-object root rejection"); + const projected = projectAnalysisError(loaded.error); + expect(projected).toMatchObject({ + code: "evidence_integrity_mismatch", + details: { reason: "invalid-json" }, + }); + expect(projected.message).toContain("Repair or recreate"); + expect(loaded.error.cause).toMatchObject({ + message: "JSON document root must be an object", + }); + expect(await readFile(path, "utf8")).toBe(encoded); + }, + ); + + it("retains syntax and snapshot-member validation and loads valid objects", async () => { + const root = await createTestTempDirectory("rea-snapshot-validation-"); + const path = join(root, "snapshot.json"); + const prefix = " ".repeat(paddingBytes); + await writeFile(path, `${prefix}[`); + expect(await readAnalysisSnapshot(path)).toMatchObject({ + ok: false, + error: { _tag: "EvidenceFileError", reason: "invalid-json" }, + }); + await writeFile(path, `${prefix}{}`); + expect(await readAnalysisSnapshot(path)).toMatchObject({ + ok: false, + error: { _tag: "EvidenceIntegrityError" }, + }); + const snapshot = { + target: snapshotTarget(ANALYSIS_SNAPSHOT_TARGET), + binding: snapshotBinding(ANALYSIS_SNAPSHOT_PROFILE), + entries: [], + workflow_entries: [], + evidence_bundle: createEvidenceBundle([]), + }; + await writeFile(path, `${prefix}${JSON.stringify(snapshot)}`); + expect(await readAnalysisSnapshot(path)).toEqual({ + ok: true, + value: snapshot, + }); + }); +}); + +it("keeps file-selection failures distinct from invalid snapshot contents", async () => { + const root = await createTestTempDirectory("rea-snapshot-selection-"); + for (const [path, reason] of [ + [join(root, "missing.json"), "missing"], + [root, "not-file"], + ] as const) { + const loaded = await readAnalysisSnapshot(path); + if (loaded.ok) throw new Error("Expected a file-selection failure"); + expect(projectAnalysisError(loaded.error)).toMatchObject({ + code: "invalid_request", + details: { reason }, + }); + } +}); diff --git a/tests/boundary/filesystem/artifactZipIntegrity.test.ts b/tests/boundary/filesystem/artifactZipIntegrity.test.ts index 0bb475518..41397c520 100644 --- a/tests/boundary/filesystem/artifactZipIntegrity.test.ts +++ b/tests/boundary/filesystem/artifactZipIntegrity.test.ts @@ -38,8 +38,19 @@ it("completes an empty ZIP extraction with an empty identity", async () => { expect(await readdir(output)).toEqual([]); }); +const legacyControlNames = [ + ["legacy ASCII control", Buffer.from("Icon\r"), false, "Icon\r"], + [ + "legacy CP437 control", + Buffer.from([0x82, 0x09, 0x7f, 0x2e, 0x61]), + false, + "é\t\u007F.a", + ], +] as const; + it.each([ ["legacy CP437", Buffer.from([0x82, 0x2e, 0x74, 0x78, 0x74]), false, "é.txt"], + ...legacyControlNames, [ "EFS with leading U+FEFF", Buffer.from([0xef, 0xbb, 0xbf, 0x61, 0x62]), @@ -68,6 +79,38 @@ it.each([ }, ); +it.skipIf(process.platform === "win32").each(legacyControlNames)( + "extracts %s ZIP members under their stored names", + async (_label, rawName, utf8Flag, logicalPath) => { + const root = await createTestTempDirectory("rea-zip-extracted-name-"); + const path = join(root, "names.zip"); + await writeSingleEntryZip(path, "x.txt"); + const archive = await readFile(path); + await writeFile( + path, + rewriteSingleEntryName(archive, "x.txt", rawName, utf8Flag), + ); + const target = await parseBinaryTarget(path); + if (!target.ok) throw target.error; + + const output = join(root, "output"); + const result = await withArtifactClient(target.value, (client) => + client.execute("extract_artifact", { output_root: output }), + ); + if (!result.ok) throw result.error; + const extraction = artifactExtractionResultSchema.parse( + result.value.result, + ); + expect( + extraction.artifacts.map(({ relative_path }) => relative_path), + ).toEqual([logicalPath]); + expect(await readdir(output)).toEqual([logicalPath]); + expect(await readFile(join(output, logicalPath), "utf8")).toBe( + "member bytes", + ); + }, +); + it("preserves valid Info-ZIP Unicode Path overrides", async () => { const root = await createTestTempDirectory("rea-zip-unicode-path-"); const path = join(root, "unicode-path.zip"); diff --git a/tests/boundary/filesystem/ciChangeScope.test.ts b/tests/boundary/filesystem/ciChangeScope.test.ts index 23b809600..934d06faf 100644 --- a/tests/boundary/filesystem/ciChangeScope.test.ts +++ b/tests/boundary/filesystem/ciChangeScope.test.ts @@ -1,4 +1,5 @@ import { + chmod, cp, mkdir, readFile, @@ -7,6 +8,7 @@ import { writeFile, } from "node:fs/promises"; import { dirname, join, matchesGlob } from "node:path"; +import { fileURLToPath } from "node:url"; import { afterAll, beforeAll, expect, it } from "vitest"; import { parse } from "yaml"; @@ -78,12 +80,13 @@ async function classify( head: string, event = "pull_request", full = false, + skipFull = false, ) { const output = join(directory, "scope-output"); await writeFile(output, ""); const result = await execFileAsync( process.execPath, - [new URL("../../../scripts/ci/plan.mjs", import.meta.url).pathname], + [fileURLToPath(new URL("../../../scripts/ci/plan.mjs", import.meta.url))], { cwd: directory, env: { @@ -92,6 +95,7 @@ async function classify( HEAD_SHA: head, GITHUB_EVENT_NAME: event, CI_FULL: String(full), + CI_SKIP_FULL: String(skipFull), GITHUB_OUTPUT: output, }, }, @@ -99,6 +103,21 @@ async function classify( return z.record(z.string(), z.unknown()).parse(JSON.parse(result.stdout)); } +it("reuses only scheduled qualification and preserves every explicit full request", async () => { + const { directory, base } = await fixture(); + const reused = await classify(directory, base, base, "schedule", false, true); + expect(reused.tier).toBe("reused"); + const { CI_FLAGS } = await loadScopes(); + for (const flag of CI_FLAGS) expect(reused[flag]).toBe(false); + for (const event of ["workflow_dispatch", "pull_request", "schedule"]) + expect( + (await classify(directory, base, base, event, true, true)).tier, + ).toBe("full"); + expect( + (await classify(directory, base, base, "push", false, true)).tier, + ).toBe("fast"); +}); + it("keeps every translated root README and authored guide on the documentation lane", async () => { const { directory, base } = await fixture(); const readmes = (await readdir(new URL("../../../", import.meta.url))).filter( @@ -128,6 +147,64 @@ it("runs documentation verification when only its published-route verifier chang }); }); +it.each([ + "job-timings.mjs", + "job-timings-batch.mjs", + "test-report.mjs", + "test-timing-reporter.mjs", + "test-history.mjs", +])( + "keeps portable CI reporter %s on static checks and portable tests", + async (name) => { + const { directory, base } = await fixture(); + const head = await change(directory, [`scripts/ci/${name}`]); + const plan = await classify(directory, base, head); + const { CI_FLAGS } = await loadScopes(); + expect(plan.code).toBe(true); + for (const flag of CI_FLAGS) + if (flag !== "code") expect(plan[flag]).toBe(false); + }, +); + +it("preserves a provider lane when a portable CI reporter changes with provider source", async () => { + const { directory, base } = await fixture(); + const head = await change(directory, [ + "scripts/ci/test-report.mjs", + "src/evm/Example.ts", + ]); + expect(await classify(directory, base, head)).toMatchObject({ + code: true, + evm: true, + browser: false, + package: false, + }); +}); + +it("keeps unknown CI scripts on complete qualification", async () => { + const { directory, base } = await fixture(); + const head = await change(directory, ["scripts/ci/new-qualification.mjs"]); + const plan = await classify(directory, base, head); + const { CI_FLAGS } = await loadScopes(); + for (const flag of CI_FLAGS) expect(plan[flag]).toBe(true); +}); + +it("emits an observational owner proposal without changing ordinary or full portable execution", async () => { + const { directory, base } = await fixture(); + const head = await change(directory, ["src/evm/Example.ts"]); + expect(await classify(directory, base, head)).toMatchObject({ + code: true, + testSelection: { mode: "candidate", owners: ["evm"] }, + }); + expect( + await classify(directory, base, head, "pull_request", true), + ).toMatchObject({ + code: true, + testSelection: { mode: "full", owners: [] }, + }); + const output = await readFile(join(directory, "scope-output"), "utf8"); + expect(output).toContain('test_selection={"version":1,"mode":"full"'); +}); + it("does not charge a documentation PR for unrelated implementation updates on main", async () => { const { directory, base } = await fixture(); await git(directory, ["switch", "-c", "docs/change"]); @@ -171,13 +248,148 @@ it("retains complete checks when implementation is renamed into documentation", }); }); -it("retains the complete main-push baseline even for documentation", async () => { +it("keeps main pushes scoped when a successful ancestor baseline is available", async () => { const { directory, base } = await fixture(); const head = await change(directory, ["README_ja.md"]); expect(await classify(directory, base, head, "push")).toMatchObject({ + tier: "fast", + code: false, + package: false, + docs: true, + matrix: { + include: [ + { os: "ubuntu-latest", platform: "linux", architecture: "x64" }, + ], + }, + }); +}); + +it("includes changes from earlier cancelled pushes since the last successful baseline", async () => { + const { directory, base } = await fixture(); + await change(directory, ["src/evm/client.ts"]); + const head = await change(directory, ["README.md"]); + expect(await classify(directory, base, head, "push")).toMatchObject({ + tier: "fast", + code: true, + evm: true, + runtime: true, + package: false, + }); +}); + +it.each(["", "not-a-commit"])( + "fails closed to all lanes for a missing or invalid push baseline (%s)", + async (base) => { + const { directory } = await fixture(); + const head = await change(directory, ["README.md"]); + const plan = await classify(directory, base, head, "push"); + expect(plan).toMatchObject({ + tier: "fast", + code: true, + package: true, + evm: true, + browser: true, + reasons: expect.arrayContaining([expect.stringContaining("baseline")]), + }); + const { CI_FLAGS } = await loadScopes(); + for (const flag of CI_FLAGS) expect(plan[flag]).toBe(true); + }, +); + +it("selects only a trusted successful ancestor from recent CI push runs", async () => { + const { directory, base } = await fixture(); + const head = await change(directory, ["src/evm/client.ts"]); + const bin = join(directory, "fake-bin"); + await mkdir(bin); + const gh = join(bin, "gh"); + await writeFile(gh, '#!/bin/sh\ncat "$GH_FIXTURE_RESPONSE"\n'); + await chmod(gh, 0o755); + const response = join(directory, "runs.json"); + await writeFile( + response, + JSON.stringify({ + workflow_runs: [ + { + event: "push", + conclusion: "success", + head_branch: "main", + head_repository: { full_name: "untrusted/fork" }, + head_sha: base, + }, + { + event: "push", + conclusion: "success", + head_branch: "main", + head_repository: { full_name: "owner/repo" }, + head_sha: base, + }, + ], + }), + ); + const output = join(directory, "baseline-output"); + const result = await execFileAsync( + process.execPath, + [new URL("../../../scripts/ci/baseline.mjs", import.meta.url).pathname], + { + cwd: directory, + env: { + ...process.env, + PATH: `${bin}:${process.env.PATH}`, + GH_FIXTURE_RESPONSE: response, + CI_REPOSITORY: "owner/repo", + CI_DEFAULT_BRANCH: "main", + HEAD_SHA: head, + GITHUB_OUTPUT: output, + }, + }, + ); + expect(JSON.parse(result.stdout)).toEqual({ base, reason: "" }); + expect(await readFile(output, "utf8")).toBe(`base=${base}\nreason=\n`); +}); + +it("returns an empty baseline when GitHub lookup fails", async () => { + const { directory, base } = await fixture(); + const head = await change(directory, ["src/evm/client.ts"]); + const bin = join(directory, "fake-bin"); + await mkdir(bin); + const gh = join(bin, "gh"); + await writeFile(gh, "#!/bin/sh\nexit 1\n"); + await chmod(gh, 0o755); + const result = await execFileAsync( + process.execPath, + [new URL("../../../scripts/ci/baseline.mjs", import.meta.url).pathname], + { + cwd: directory, + env: { + ...process.env, + PATH: `${bin}:${process.env.PATH}`, + CI_REPOSITORY: "owner/repo", + CI_DEFAULT_BRANCH: "main", + HEAD_SHA: head, + }, + }, + ); + expect(JSON.parse(result.stdout)).toMatchObject({ + base: "", + reason: expect.stringContaining("Could not read"), + }); + expect(head).not.toBe(base); +}); + +it("fails closed when the successful push baseline is not an ancestor", async () => { + const { directory, base } = await fixture(); + await git(directory, ["switch", "-c", "unrelated"]); + const unrelated = await change(directory, ["other.txt"]); + await git(directory, ["switch", "main"]); + const head = await change(directory, ["README.md"]); + expect(await classify(directory, unrelated, head, "push")).toMatchObject({ + tier: "fast", code: true, package: true, + evm: true, + browser: true, }); + expect(head).not.toBe(base); }); it("fails classification rather than treating an invalid Git comparison as a scope", async () => { @@ -217,7 +429,8 @@ it("retains native Inspector verification on every documented package host", asy ); expect(packageInspector.if).toBeUndefined(); expect( - (await classify((await fixture()).directory, "", "", "push")).matrix, + (await classify((await fixture()).directory, "", "", "workflow_dispatch")) + .matrix, ).toEqual({ include: [ { os: "ubuntu-latest", platform: "linux", architecture: "x64" }, @@ -237,7 +450,14 @@ it("retains native Inspector verification on every documented package host", asy it.each([ [ "src/evm/client.ts", - { code: true, runtime: true, evm: true, browser: false, package: false }, + { + code: true, + runtime: true, + evm: true, + browser: false, + package: false, + sqlite: false, + }, ], [ "src/browser/execution/evaluate.ts", @@ -334,6 +554,38 @@ it.each([ "src/process/ProcessOwnership.test.ts", { code: true, package: true, apple: false, evm: false, browser: false }, ], + [ + "src/sqlite/SqliteDatabaseProvider.ts", + { code: true, sqlite: true, runtime: true, package: false }, + ], + [ + "src/application/sqlite/SqliteDatabaseService.test.ts", + { code: true, sqlite: true, runtime: false }, + ], + [ + "tests/boundary/sqlite/sqliteDatabaseProvider.test.ts", + { code: true, sqlite: true, runtime: false }, + ], + [ + "tests/fixtures/sqlite/database.ts", + { code: true, sqlite: true, runtime: false }, + ], + ["tests/acceptance/sqliteDatabaseCli.test.ts", { code: true, sqlite: true }], + [ + "tests/boundary/mcp/serverLifecycleMcp.test.ts", + { code: true, sqlite: true }, + ], + ["src/process/OwnedCommand.ts", { code: true, sqlite: true, runtime: true }], + ["src/server/createServer.ts", { code: true, sqlite: true, runtime: true }], + [ + "src/contracts/toolContracts.ts", + { code: true, sqlite: true, runtime: true }, + ], + [ + "src/domain/analysisErrorProjection.ts", + { code: true, sqlite: true, runtime: true }, + ], + ["src/domain/javascript/example.ts", { code: true, sqlite: false }], ])("selects the appropriate lanes for %s", async (path, expected) => { const { directory, base } = await fixture(); const head = await change(directory, [path]); @@ -376,6 +628,52 @@ it("scopes package script edits while retaining broad dependency checks", async }); }); +it.each(["test:sqlite", "test:sqlite:run"])( + "routes %s script changes to the SQLite runtime matrix", + async (script) => { + const { directory } = await fixture(); + const base = await change( + directory, + ["package.json"], + JSON.stringify({ scripts: { [script]: "vitest run" } }), + ); + const head = await change( + directory, + ["package.json"], + JSON.stringify({ + scripts: { [script]: "vitest run --reporter=default" }, + }), + ); + expect(await classify(directory, base, head)).toMatchObject({ + code: true, + sqlite: true, + evm: false, + package: false, + }); + }, +); + +it("keeps unrelated test script changes off the SQLite runtime matrix", async () => { + const { directory } = await fixture(); + const base = await change( + directory, + ["package.json"], + JSON.stringify({ scripts: { "test:domain": "vitest run src/domain" } }), + ); + const head = await change( + directory, + ["package.json"], + JSON.stringify({ + scripts: { "test:domain": "vitest run src/domain --reporter=default" }, + }), + ); + expect(await classify(directory, base, head)).toMatchObject({ + code: true, + sqlite: false, + evm: false, + }); +}); + it.each([ ["browser", "real-browser"], ["binary_layout", "real-binary-layout"], @@ -392,7 +690,9 @@ it.each([ async (scope, name) => { const workflow = z .object({ - on: z.object({ workflow_call: z.null() }).passthrough(), + on: z + .object({ workflow_call: z.object({}).passthrough().nullable() }) + .passthrough(), }) .parse( parse( @@ -429,10 +729,19 @@ it.each([ ); it("rejects skipped selected work while allowing unselected lanes to skip", async () => { - const command = new URL("../../../scripts/ci/required.mjs", import.meta.url) - .pathname; + const command = fileURLToPath( + new URL("../../../scripts/ci/required.mjs", import.meta.url), + ); + const { CI_FLAGS } = await loadScopes(); const jobs = { - changes: { result: "success", outputs: { evm: "true" } }, + changes: { + result: "success", + outputs: { + ...Object.fromEntries(CI_FLAGS.map((flag) => [flag, "false"])), + tier: "fast", + evm: "true", + }, + }, static: { result: "success" }, test: { result: "success" }, evm: { result: "success" }, @@ -468,7 +777,10 @@ it.each([ "src/process/capture/example.test.ts", { code: true, runtime: false, browser: false, package: false }, ], - [".nvmrc", { code: true, package: true, browser: true, evm: true }], + [ + ".nvmrc", + { code: true, package: true, browser: true, evm: true, sqlite: true }, + ], [ "tsconfig.build.json", { code: true, package: true, browser: true, evm: true }, @@ -605,8 +917,10 @@ it.each(["workflow_dispatch", "schedule"])( async (event) => { const { directory, base } = await fixture(); expect(await classify(directory, base, base, event)).toMatchObject({ + tier: "full", code: true, package: true, + sqlite: true, evm: true, browser: true, }); @@ -620,7 +934,14 @@ it("honors ci:full for successive PR revisions", async () => { for (const head of [first, second]) { expect( await classify(directory, base, head, "pull_request", true), - ).toMatchObject({ code: true, package: true, evm: true, browser: true }); + ).toMatchObject({ + tier: "full", + code: true, + package: true, + sqlite: true, + evm: true, + browser: true, + }); } }); @@ -660,7 +981,7 @@ const INTEL_HOST = { architecture: "x64", }; -it("keeps macOS x64 package verification for ci:full and non-PR events", async () => { +it("keeps macOS x64 package verification only for full qualification", async () => { const { directory, base } = await fixture(); const head = await change(directory, ["src/windows/Example.ts"]); const matrix = z.object({ include: z.array(z.unknown()) }); @@ -671,7 +992,8 @@ it("keeps macOS x64 package verification for ci:full and non-PR events", async ( expect(pullRequest).toHaveLength(3); expect(pullRequest).not.toContainEqual(INTEL_HOST); expect(await hosts("pull_request", true)).toContainEqual(INTEL_HOST); - for (const event of ["push", "schedule", "workflow_dispatch"]) + expect(await hosts("push", false)).not.toContainEqual(INTEL_HOST); + for (const event of ["schedule", "workflow_dispatch"]) expect(await hosts(event, false)).toContainEqual(INTEL_HOST); }); @@ -684,6 +1006,7 @@ const workflowFile = async (name: string): Promise => ); const scopesSchema = z.object({ + CI_FLAGS: z.array(z.string()), SCOPES: z.record(z.string(), z.array(z.string())), MANUAL_VERIFIERS: z.array(z.string()), }); diff --git a/tests/boundary/filesystem/ciJobTimings.test.ts b/tests/boundary/filesystem/ciJobTimings.test.ts new file mode 100644 index 000000000..85a2ddd1f --- /dev/null +++ b/tests/boundary/filesystem/ciJobTimings.test.ts @@ -0,0 +1,243 @@ +import { chmod, mkdir, readFile, writeFile } from "node:fs/promises"; +import { delimiter, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { expect, it } from "vitest"; + +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { + executeWorkflowFixture, + workflowGit, +} from "../../support/workflowGit.js"; + +const reporter = fileURLToPath( + new URL("../../../scripts/ci/job-timings.mjs", import.meta.url), +); + +it("merges paginated jobs, reports elapsed metrics, and preserves raw responses", async () => { + const fixture = await createFixture([ + { + total_count: 4, + jobs: [ + { + name: "Build package", + workflow_name: "CI", + status: "completed", + conclusion: "success", + created_at: "2026-10-13T00:00:00Z", + started_at: "2026-10-13T00:00:10Z", + completed_at: "2026-10-13T00:01:10Z", + steps: [ + { + name: "Install dependencies (npm ci)", + started_at: "2026-10-13T00:00:10Z", + completed_at: "2026-10-13T00:00:40Z", + }, + { + name: "Upload artifact", + started_at: "2026-10-13T00:00:40Z", + completed_at: "2026-10-13T00:00:41Z", + }, + ], + }, + ], + }, + { + total_count: 4, + jobs: [ + { + name: "Queued lane", + status: "queued", + created_at: "2026-10-13T00:00:00Z", + started_at: "2026-10-13T00:00:00Z", + completed_at: null, + steps: [], + }, + { + name: "Running lane", + status: "in_progress", + created_at: "2026-10-13T00:00:00Z", + started_at: "2026-10-13T00:00:15Z", + completed_at: null, + steps: [ + { + name: "Download artifacts", + started_at: "2026-10-13T00:00:20Z", + completed_at: "2026-10-13T00:00:22Z", + }, + ], + }, + { + name: "Skipped lane", + status: "completed", + conclusion: "skipped", + created_at: "2026-10-13T00:00:00Z", + started_at: "2026-10-13T00:00:00Z", + completed_at: "2026-10-13T00:00:00Z", + steps: [], + }, + ], + }, + ]); + const result = await runReporter(fixture); + const report = JSON.parse( + await readFile(join(fixture.outputDirectory, "report.json"), "utf8"), + ); + + expect(report.run.snapshot).toContain("partial"); + expect(report.counts).toMatchObject({ + jobs: 4, + completed: 2, + skipped: 1, + queueUnknown: 2, + executionUnknown: 3, + completedExecutionUnknown: 0, + }); + expect(report.aggregates.queueSeconds).toMatchObject({ + count: 2, + p50: 10, + p95: 15, + }); + expect(report.aggregates.completedExecutionSeconds).toMatchObject({ + count: 1, + p50: 60, + p95: 60, + }); + expect(report.aggregates.summedCompletedJobElapsedSeconds).toMatchObject({ + value: 60, + knownCount: 1, + unknownCount: 0, + label: expect.stringContaining("not CPU time"), + }); + expect(report.jobs[1].queue).toEqual({ + seconds: null, + reason: "job start is not established by its status", + }); + expect(report.jobs[3].queue).toEqual({ + seconds: null, + reason: "job was skipped", + }); + expect(report.jobs[3].execution).toEqual({ + seconds: null, + reason: "job was skipped", + }); + expect(report.stepCosts.npmCi[0].duration.seconds).toBe(30); + expect(report.stepCosts.artifactUpload[0].duration.seconds).toBe(1); + expect(report.stepCosts.artifactDownload[0].duration.seconds).toBe(2); + expect(report.stepCostInterpretation).toContain( + "not total artifact transfer costs", + ); + expect(report.cpuSeconds).toBeUndefined(); + expect(result.stdout).toContain("4 job timing records"); + expect( + await readFile(join(fixture.outputDirectory, "jobs.json"), "utf8"), + ).toBe(fixture.raw); + const summary = await readFile(fixture.summary, "utf8"); + expect(summary).toContain("point-in-time snapshot"); + expect(summary).toContain("unknown"); + expect(summary).toContain("not CPU time"); + expect(summary).toContain("60 s"); + expect(summary).toContain("not total artifact transfer costs"); + const args = JSON.parse(await readFile(fixture.args, "utf8")); + expect(args).toEqual([ + "api", + "--paginate", + "--slurp", + "repos/example/rea/actions/runs/42/attempts/2/jobs?per_page=100", + ]); +}); + +it("marks invalid and out-of-order timestamps unknown instead of emitting negative durations", async () => { + const fixture = await createFixture([ + { + jobs: [ + { + name: "Invalid dates", + status: "completed", + created_at: "not-a-date", + started_at: "2026-10-13T00:00:10Z", + completed_at: "2026-10-13T00:00:05Z", + steps: [], + }, + ], + }, + ]); + await runReporter(fixture); + const report = JSON.parse( + await readFile(join(fixture.outputDirectory, "report.json"), "utf8"), + ); + + expect(report.jobs[0].queue).toEqual({ + seconds: null, + reason: "invalid timestamp", + }); + expect(report.jobs[0].execution).toEqual({ + seconds: null, + reason: "timestamps out of order", + }); + expect(report.counts.completedExecutionUnknown).toBe(1); + expect(report.aggregates.summedCompletedJobElapsedSeconds).toMatchObject({ + value: null, + unknownCount: 1, + }); +}); + +it("fails on malformed pages or a failed GitHub API request", async () => { + const malformed = await createFixture([{ jobs: "not-an-array" }]); + await expect(runReporter(malformed)).rejects.toThrow(); + await expect( + readFile(join(malformed.outputDirectory, "jobs.json"), "utf8"), + ).resolves.toBe(malformed.raw); + + const failedApi = await createFixture([], { exitCode: 1 }); + await expect(runReporter(failedApi)).rejects.toThrow(); +}); + +async function createFixture( + pages: unknown[], + { exitCode = 0 }: { exitCode?: number } = {}, +) { + const directory = await createTestTempDirectory("rea-ci-job-timings-"); + await workflowGit(directory, ["init", "--initial-branch=main"]); + const fakeBin = join(directory, "bin"); + await mkdir(fakeBin); + const raw = JSON.stringify(pages); + const rawPath = join(directory, "gh-response.json"); + const args = join(directory, "gh-args.json"); + await writeFile(rawPath, raw); + const fakeGh = join(fakeBin, "gh"); + await writeFile( + fakeGh, + `#!/usr/bin/env node\nconst fs = require("node:fs");\nfs.writeFileSync(process.env.CI_GH_ARGS, JSON.stringify(process.argv.slice(2)));\nprocess.stdout.write(fs.readFileSync(process.env.CI_GH_RESPONSE, "utf8"));\nprocess.exitCode = ${String(exitCode)};\n`, + ); + await chmod(fakeGh, 0o755); + const outputDirectory = join(directory, ".cache", "ci-job-timings"); + const summary = join(directory, "summary.md"); + await writeFile(summary, ""); + return { + directory, + fakeBin, + raw, + rawPath, + args, + outputDirectory, + summary, + }; +} + +function runReporter(fixture: Awaited>) { + return executeWorkflowFixture(process.execPath, [reporter], { + cwd: fixture.directory, + env: { + ...process.env, + PATH: `${fixture.fakeBin}${delimiter}${process.env.PATH ?? ""}`, + CI_REPOSITORY: "example/rea", + CI_JOB_TIMINGS_DIRECTORY: fixture.outputDirectory, + CI_GH_ARGS: fixture.args, + CI_GH_RESPONSE: fixture.rawPath, + CI_TIMING_RUN_ID: "42", + CI_TIMING_RUN_ATTEMPT: "2", + GITHUB_STEP_SUMMARY: fixture.summary, + }, + }); +} diff --git a/tests/boundary/filesystem/ciJobTimingsBatch.test.ts b/tests/boundary/filesystem/ciJobTimingsBatch.test.ts new file mode 100644 index 000000000..6c2658c00 --- /dev/null +++ b/tests/boundary/filesystem/ciJobTimingsBatch.test.ts @@ -0,0 +1,288 @@ +import { chmod, mkdir, readFile, writeFile } from "node:fs/promises"; +import { delimiter, join } from "node:path"; +import { fileURLToPath, pathToFileURL } from "node:url"; + +import { expect, it } from "vitest"; + +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { executeWorkflowFixture } from "../../support/workflowGit.js"; + +const batchScript = fileURLToPath( + new URL("../../../scripts/ci/job-timings-batch.mjs", import.meta.url), +); + +it("collects the latest attempt for recent completed CI and Release runs into a bounded manifest", async () => { + const recent = new Date().toISOString(); + const fixture = await createFixture([ + { + workflow_runs: [ + { + id: 42, + run_attempt: 3, + status: "completed", + conclusion: "failure", + created_at: new Date(Date.parse(recent) + 1_000).toISOString(), + }, + { + id: 41, + run_attempt: 1, + status: "completed", + conclusion: "cancelled", + created_at: recent, + }, + ], + }, + { + workflow_runs: [ + { + id: 43, + run_attempt: 2, + status: "completed", + conclusion: "success", + created_at: new Date(Date.parse(recent) + 2_000).toISOString(), + }, + ], + }, + [ + { + jobs: [ + { + name: "Release lane", + status: "completed", + conclusion: "success", + created_at: recent, + started_at: recent, + completed_at: new Date(Date.parse(recent) + 50_000).toISOString(), + steps: [], + }, + ], + }, + ], + [ + { + jobs: [ + { + name: "Failed lane", + status: "completed", + conclusion: "failure", + created_at: recent, + started_at: recent, + completed_at: new Date(Date.parse(recent) + 55_000).toISOString(), + steps: [], + }, + ], + }, + ], + [ + { + jobs: [ + { + name: "Cancelled lane", + status: "completed", + conclusion: "cancelled", + created_at: recent, + started_at: recent, + completed_at: new Date(Date.parse(recent) + 30_000).toISOString(), + steps: [], + }, + ], + }, + ], + ]); + const result = await runBatch(fixture); + const manifest = JSON.parse( + await readFile( + join(fixture.outputDirectory, "batch-manifest.json"), + "utf8", + ), + ); + const calls = JSON.parse(await readFile(fixture.calls, "utf8")); + + expect(result.stdout).toContain("3 collected runs"); + expect( + await readFile(join(fixture.directory, "summary.md"), "utf8"), + ).toContain("collected 3 of 3"); + expect(manifest.selection).toMatchObject({ + lookbackHours: 24, + maxRunsPerWorkflow: 100, + exhaustive: false, + }); + expect(manifest.coverage).toMatchObject({ + workflowsQueried: ["CI", "Release"], + selectedRuns: 3, + collectedRuns: 3, + }); + expect(manifest.truncation).toEqual([]); + expect(manifest.errors).toEqual([]); + expect(manifest.runs).toMatchObject([ + { id: 43, runAttempt: 2, conclusion: "success" }, + { id: 42, runAttempt: 3, conclusion: "failure" }, + { id: 41, runAttempt: 1, conclusion: "cancelled" }, + ]); + expect(manifest.runs).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + status: "collected", + rawPath: expect.any(String), + reportPath: expect.any(String), + }), + ]), + ); + expect(calls).toContainEqual([ + "api", + "--paginate", + "--slurp", + "repos/example/rea/actions/runs/42/attempts/3/jobs?per_page=100", + ]); + expect(calls).toContainEqual([ + "api", + "--paginate", + "--slurp", + "repos/example/rea/actions/runs/41/attempts/1/jobs?per_page=100", + ]); + const failedReport = JSON.parse( + await readFile( + join(fixture.outputDirectory, "runs/42-3/report.json"), + "utf8", + ), + ); + expect(failedReport.jobs[0].conclusion).toBe("failure"); + expect(failedReport.jobs[0].execution.seconds).toBe(55); +}); + +it("records listing and per-run errors without claiming complete coverage", async () => { + const recent = new Date().toISOString(); + const fixture = await createFixture([ + { + workflow_runs: [ + { + id: 7, + run_attempt: 2, + status: "completed", + conclusion: "success", + created_at: recent, + }, + ], + }, + { error: true }, + { jobs: "malformed" }, + ]); + await runBatch(fixture); + const manifest = JSON.parse( + await readFile( + join(fixture.outputDirectory, "batch-manifest.json"), + "utf8", + ), + ); + expect(manifest.selection.exhaustive).toBe(false); + expect(manifest.errors).toMatchObject([ + { scope: "workflow:Release" }, + { scope: "run" }, + ]); + expect(manifest.runs[0]).toMatchObject({ + id: 7, + runAttempt: 2, + status: "error", + }); +}); + +it("retains a partial manifest when its collection budget is exhausted", async () => { + const fixture = await createFixture([ + { + workflow_runs: [8, 9].map((id) => ({ + id, + run_attempt: 1, + status: "completed", + created_at: new Date().toISOString(), + })), + }, + { workflow_runs: [] }, + ]); + await executeWorkflowFixture( + process.execPath, + [ + "--input-type=module", + "-e", + ` + const { collectJobTimingsBatch } = await import(${JSON.stringify(pathToFileURL(batchScript).href)}); + let clock = Date.now(); + await collectJobTimingsBatch({ + repository: "example/rea", + outputDirectory: process.env.CI_JOB_TIMINGS_DIRECTORY, + now: () => clock, + collect: async () => { + clock += 240001; + throw new Error("fixture request exhausted the remaining budget"); + }, + }); + `, + ], + { cwd: fixture.directory, env: fixtureEnvironment(fixture) }, + ); + const manifest = JSON.parse( + await readFile( + join(fixture.outputDirectory, "batch-manifest.json"), + "utf8", + ), + ); + expect(manifest.coverage).toMatchObject({ + selectedRuns: 2, + collectedRuns: 0, + }); + expect(manifest.runs).toHaveLength(1); + expect(manifest.runs[0]).toMatchObject({ status: "error" }); + expect(manifest.truncation.join(" ")).toContain("Time budget"); +}); + +async function createFixture(responses: unknown[]) { + const directory = await createTestTempDirectory("rea-ci-job-timings-batch-"); + const fakeBin = join(directory, "bin"); + await mkdir(fakeBin); + const responsePath = join(directory, "responses.json"); + const calls = join(directory, "calls.json"); + await writeFile(responsePath, JSON.stringify(responses)); + await writeFile(calls, "[]"); + const fakeGh = join(fakeBin, "gh"); + await writeFile( + fakeGh, + `#!/usr/bin/env node +const fs = require("node:fs"); +const calls = JSON.parse(fs.readFileSync(process.env.CI_GH_CALLS, "utf8")); +calls.push(process.argv.slice(2)); +fs.writeFileSync(process.env.CI_GH_CALLS, JSON.stringify(calls)); +const responses = JSON.parse(fs.readFileSync(process.env.CI_GH_RESPONSES, "utf8")); +const response = responses[calls.length - 1]; +if (response && response.error) { process.stderr.write("fixture API error"); process.exitCode = 1; } +else process.stdout.write(JSON.stringify(response)); +`, + ); + await chmod(fakeGh, 0o755); + return { + directory, + fakeBin, + responses: responsePath, + calls, + outputDirectory: join(directory, ".cache", "ci-job-timings"), + }; +} + +function runBatch(fixture: Awaited>) { + return executeWorkflowFixture(process.execPath, [batchScript], { + cwd: fixture.directory, + env: fixtureEnvironment(fixture), + }); +} + +function fixtureEnvironment( + fixture: Awaited>, +) { + return { + ...process.env, + PATH: `${fixture.fakeBin}${delimiter}${process.env.PATH ?? ""}`, + CI_REPOSITORY: "example/rea", + CI_JOB_TIMINGS_DIRECTORY: fixture.outputDirectory, + CI_GH_CALLS: fixture.calls, + CI_GH_RESPONSES: fixture.responses, + GITHUB_STEP_SUMMARY: join(fixture.directory, "summary.md"), + }; +} diff --git a/tests/boundary/filesystem/ciPrEvents.test.ts b/tests/boundary/filesystem/ciPrEvents.test.ts new file mode 100644 index 000000000..3562b5df9 --- /dev/null +++ b/tests/boundary/filesystem/ciPrEvents.test.ts @@ -0,0 +1,98 @@ +import { readFile } from "node:fs/promises"; +import { expect, it } from "vitest"; +import { parse } from "yaml"; +import { z } from "zod"; +import { executeWorkflowFixture } from "../../support/workflowGit.js"; + +async function workflow(name: string) { + return z + .object({ + on: z.record(z.string(), z.unknown()), + permissions: z.record(z.string(), z.string()), + concurrency: z.object({ group: z.string() }).optional(), + jobs: z.record( + z.string(), + z.object({ + name: z.string().optional(), + if: z.string().optional(), + uses: z.string().optional(), + with: z.record(z.string(), z.string()).optional(), + steps: z + .array( + z.object({ + run: z.string().optional(), + uses: z.string().optional(), + env: z.record(z.string(), z.string()).optional(), + }), + ) + .optional(), + }), + ), + }) + .parse( + parse( + await readFile( + new URL(`../../../.github/workflows/${name}`, import.meta.url), + "utf8", + ), + ), + ); +} + +it("refreshes title validation on edits without checking out PR code or cancelling CI", async () => { + const title = await workflow("pr-title.yml"); + expect(title.on.pull_request).toMatchObject({ + types: ["opened", "synchronize", "reopened", "edited"], + }); + expect(title.permissions).toEqual({}); + expect(title.concurrency?.group).not.toBe( + (await workflow("ci.yml")).concurrency?.group, + ); + const jobs = Object.values(title.jobs); + expect(jobs).toHaveLength(1); + expect(jobs[0]?.name).toBe("Conventional PR title"); + expect(jobs[0]?.if).toBeUndefined(); // A skipped check must not green-light an invalid title on body edits. + const steps = jobs[0]?.steps ?? []; + expect(steps).toHaveLength(1); + expect(steps[0]?.uses).toBeUndefined(); + expect(steps[0]?.env).toEqual({ + PR_TITLE: "${{ github.event.pull_request.title }}", + }); + const command = z.string().parse(steps[0]?.run); + for (const title of [ + "fix(ci): repair workflow", + "feat!: changed contract", + "docs: literal $(exit 91) `exit 92` text", + ]) { + await expect( + executeWorkflowFixture("bash", ["-c", command], { + env: { ...process.env, PR_TITLE: title }, + }), + ).resolves.toMatchObject({ stderr: "" }); + } + for (const title of ["", "Fix CI", "feat: "]) { + await expect( + executeWorkflowFixture("bash", ["-c", command], { + env: { ...process.env, PR_TITLE: title }, + }), + ).rejects.toMatchObject({ code: 1 }); + } + expect((await workflow("ci.yml")).jobs["pr-title"]).toBeUndefined(); +}); + +it("qualifies only ci:full label additions at the caller's merge revision", async () => { + const full = await workflow("ci-full-pr.yml"); + expect(full.on.pull_request).toMatchObject({ types: ["labeled"] }); + expect(full.permissions).toEqual({ contents: "read", actions: "read" }); + expect(Object.values(full.jobs)).toEqual([ + { + name: "Qualify labeled PR revision", + if: "github.event.label.name == 'ci:full'", + uses: "./.github/workflows/ci.yml", + with: { source_sha: "${{ github.sha }}" }, + }, + ]); + // Metadata events must not create skipped replacements for the main CI checks. + expect(full.jobs.required).toBeUndefined(); + expect(full.concurrency).toBeUndefined(); +}); diff --git a/tests/boundary/filesystem/ciQualification.test.ts b/tests/boundary/filesystem/ciQualification.test.ts new file mode 100644 index 000000000..b6a5a1e1a --- /dev/null +++ b/tests/boundary/filesystem/ciQualification.test.ts @@ -0,0 +1,375 @@ +import { chmod, mkdir, readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { expect, it } from "vitest"; +import { parse } from "yaml"; +import { z } from "zod"; + +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { + executeWorkflowFixture, + workflowGit, +} from "../../support/workflowGit.js"; + +const qualificationScript = fileURLToPath( + new URL("../../../scripts/ci/qualification.mjs", import.meta.url), +); +const requiredScript = fileURLToPath( + new URL("../../../scripts/ci/required.mjs", import.meta.url), +); +const now = Date.now(); +const validSha = "a".repeat(40); +const repository = "example/rea"; + +function artifact(overrides: Record = {}) { + return { + id: 42, + name: "ci-full-qualification-v1", + expired: false, + created_at: new Date(now - 60_000).toISOString(), + workflow_run: { + id: 7, + repository_id: 1, + head_repository_id: 1, + head_branch: "main", + head_sha: validSha, + }, + ...overrides, + }; +} + +function run(overrides: Record = {}) { + return { + id: 7, + status: "completed", + conclusion: "success", + path: ".github/workflows/ci.yml", + event: "schedule", + created_at: new Date(now - 120_000).toISOString(), + head_sha: validSha, + head_branch: "main", + head_repository: { full_name: repository }, + ...overrides, + }; +} + +async function admissionFixture( + candidate: Record = artifact(), + candidateRun: Record = run(), + options: { apiError?: boolean; malformed?: boolean; force?: boolean } = {}, +) { + const directory = await createTestTempDirectory("rea-ci-qualification-"); + const bin = join(directory, "bin"); + await mkdir(bin); + const fixturePath = join(directory, "api.json"); + await writeFile( + fixturePath, + options.malformed + ? "not-json" + : JSON.stringify({ artifacts: [candidate], run: candidateRun }), + ); + const gh = join(bin, "gh"); + await writeFile( + gh, + [ + "#!/bin/sh", + 'if [ "$GH_API_ERROR" = "true" ]; then exit 1; fi', + 'case "$*" in', + ' *actions/artifacts*) cat "$GH_FIXTURE_RESPONSE" ;;', + " *actions/runs/7*) node -e 'const x=require(process.env.GH_FIXTURE_RESPONSE); process.stdout.write(JSON.stringify(x.run))' ;;", + " *) exit 2 ;;", + "esac", + "", + ].join("\n"), + ); + await chmod(gh, 0o755); + const output = join(directory, "github-output"); + await writeFile(output, ""); + const env = { + ...process.env, + PATH: `${bin}:${process.env.PATH ?? ""}`, + GH_FIXTURE_RESPONSE: fixturePath, + GH_API_ERROR: String(options.apiError ?? false), + CI_REPOSITORY: repository, + CI_REPOSITORY_ID: "1", + CI_DEFAULT_BRANCH: "main", + HEAD_SHA: validSha, + GITHUB_RUN_ID: "100", + GITHUB_OUTPUT: output, + ...(options.force ? { CI_FORCE_FULL: "true" } : {}), + }; + return { directory, output, env }; +} + +async function decide( + candidate?: Record, + candidateRun?: Record, + options?: { apiError?: boolean; malformed?: boolean; force?: boolean }, +) { + const fixture = await admissionFixture(candidate, candidateRun, options); + const result = await executeWorkflowFixture( + process.execPath, + [qualificationScript], + { + cwd: fixture.directory, + env: fixture.env, + }, + ); + return { + ...fixture, + decision: z + .record(z.string(), z.unknown()) + .parse(JSON.parse(result.stdout)), + outputText: await readFile(fixture.output, "utf8"), + }; +} + +it("reuses only a recent trusted full qualification for the exact default-branch SHA", async () => { + const { decision, outputText } = await decide(); + expect(decision).toMatchObject({ run_full: false, run_id: 7 }); + expect(Object.keys(decision).sort()).toEqual([ + "reason", + "run_full", + "run_id", + ]); + expect(outputText).toContain("run_full=false\n"); + expect(outputText).toContain("run_id=7\n"); +}); + +const rejectedCandidates: Array< + [string, () => Record, () => Record] +> = [ + [ + "old", + () => + artifact({ + created_at: new Date(now - 24 * 60 * 60 * 1000 - 1).toISOString(), + }), + run, + ], + [ + "future", + () => artifact({ created_at: new Date(now + 60_000).toISOString() }), + run, + ], + ["expired", () => artifact({ expired: true }), run], + [ + "foreign repository", + () => + artifact({ + workflow_run: { ...artifact().workflow_run, repository_id: 2 }, + }), + run, + ], + [ + "foreign branch", + () => + artifact({ + workflow_run: { ...artifact().workflow_run, head_branch: "other" }, + }), + run, + ], + [ + "foreign SHA", + () => + artifact({ + workflow_run: { ...artifact().workflow_run, head_sha: "b".repeat(40) }, + }), + run, + ], + [ + "untrusted workflow", + artifact, + () => run({ path: ".github/workflows/release.yml" }), + ], + ["failed run", artifact, () => run({ conclusion: "failure" })], + [ + "old producer rerun with a fresh artifact", + artifact, + () => + run({ created_at: new Date(now - 25 * 60 * 60 * 1000).toISOString() }), + ], + ["wrong workflow event", artifact, () => run({ event: "push" })], +]; + +it.each(rejectedCandidates)( + "runs full qualification for a %s candidate", + async (_name, makeArtifact, makeRun) => { + const { decision } = await decide(makeArtifact(), makeRun()); + expect(decision.run_full).toBe(true); + }, +); + +it.each([ + ["API error", { apiError: true }], + ["malformed query response", { malformed: true }], +] as const)("fails closed on %s", async (_name, options) => { + const { decision } = await decide(undefined, undefined, options); + expect(decision.run_full).toBe(true); +}); + +it("lets the daily force-full setting bypass the GitHub API", async () => { + const { decision } = await decide(undefined, undefined, { + force: true, + apiError: true, + }); + expect(decision).toMatchObject({ run_full: true }); + expect(decision.reason).toContain("Forced"); +}); + +async function workflowContract() { + const workflowPath = new URL( + "../../../.github/workflows/ci.yml", + import.meta.url, + ); + const parsed = parse(await readFile(workflowPath, "utf8")); + return z + .object({ + jobs: z.record( + z.string(), + z.object({ needs: z.unknown().optional() }).passthrough(), + ), + }) + .parse(parsed).jobs; +} + +async function requiredRun( + changes: Record, + overrides: { failed?: string; runAttempt?: string; event?: string } = {}, +) { + const directory = await createTestTempDirectory("rea-ci-receipt-"); + await workflowGit(directory, ["init", "--initial-branch=main"]); + await writeFile(join(directory, "fixture.txt"), "qualified source\n"); + await workflowGit(directory, ["add", "."]); + await workflowGit(directory, ["commit", "-m", "fixture source"]); + const head = await workflowGit(directory, ["rev-parse", "HEAD"]); + const jobs = await workflowContract(); + const results: Record< + string, + { result: string; outputs?: Record } + > = {}; + for (const name of z.array(z.string()).parse(jobs.required?.needs)) { + results[name] = { + result: + name === overrides.failed + ? "failure" + : changes.tier === "reused" + ? "skipped" + : "success", + }; + } + results.changes = { result: "success", outputs: changes }; + const receiptDirectory = join(directory, ".cache", "receipt"); + const output = join(directory, "github-output"); + await writeFile(output, ""); + const env = { + ...process.env, + CI_JOBS: JSON.stringify(results), + CI_QUALIFICATION_DIRECTORY: receiptDirectory, + GITHUB_EVENT_NAME: overrides.event ?? "schedule", + GITHUB_SHA: head, + GITHUB_RUN_ID: "100", + GITHUB_RUN_ATTEMPT: overrides.runAttempt ?? "1", + GITHUB_REPOSITORY: repository, + GITHUB_OUTPUT: output, + }; + const result = executeWorkflowFixture(process.execPath, [requiredScript], { + cwd: directory, + env, + }); + return { directory, head, output, result }; +} + +it("writes a full receipt only after every canonical flag and workflow need pass", async () => { + const scopesPath = new URL("../../../scripts/ci/scopes.mjs", import.meta.url); + const { CI_FLAGS } = await import(scopesPath.href); + const changes = Object.fromEntries( + CI_FLAGS.map((flag: string) => [flag, "true"]), + ); + changes.tier = "full"; + const { directory, head, output, result } = await requiredRun(changes); + await expect(result).resolves.toMatchObject({ stderr: "" }); + const receiptPath = join(directory, ".cache", "receipt", "receipt.json"); + const receipt = z + .object({ + sourceSha: z.string(), + runId: z.number(), + runAttempt: z.number(), + }) + .parse(JSON.parse(await readFile(receiptPath, "utf8"))); + expect(receipt).toMatchObject({ sourceSha: head, runId: 100, runAttempt: 1 }); + expect(await readFile(output, "utf8")).toContain( + `receipt_path=${receiptPath}\n`, + ); + expect(await readFile(output, "utf8")).toContain( + "receipt_name=ci-full-qualification-v1\n", + ); +}); + +it.each([ + ["failed selected lane", { failed: "sqlite-runtime" }], + ["partial full scope", {}], +] as const)( + "does not issue a receipt after %s", + async (caseName, overrides) => { + const scopesPath = new URL( + "../../../scripts/ci/scopes.mjs", + import.meta.url, + ); + const { CI_FLAGS } = await import(scopesPath.href); + const changes = Object.fromEntries( + CI_FLAGS.map((flag: string) => [flag, "true"]), + ); + changes.tier = "full"; + if (caseName === "partial full scope") changes.sqlite = "false"; + const outcome = await requiredRun(changes, overrides); + await expect(outcome.result).rejects.toMatchObject({ code: 1 }); + await expect( + readFile(join(outcome.directory, ".cache", "receipt", "receipt.json")), + ).rejects.toMatchObject({ code: "ENOENT" }); + expect(await readFile(outcome.output, "utf8")).not.toContain("receipt_"); + }, +); + +it("never writes a fresh receipt for a reused scheduled qualification", async () => { + const scopesPath = new URL("../../../scripts/ci/scopes.mjs", import.meta.url); + const { CI_FLAGS } = await import(scopesPath.href); + const changes = Object.fromEntries( + CI_FLAGS.map((flag: string) => [flag, "false"]), + ); + changes.tier = "reused"; + changes.qualification_run_id = "7"; + const outcome = await requiredRun(changes); + const result = await outcome.result; + await expect( + readFile(join(outcome.directory, ".cache", "receipt", "receipt.json")), + ).rejects.toMatchObject({ code: "ENOENT" }); + expect(result.stdout).toContain("Qualification reused from run 7"); + expect(await readFile(outcome.output, "utf8")).not.toContain("receipt_"); +}); + +it.each([ + ["missing receipt run", { qualification_run_id: "" }, "schedule"], + ["selected validation lane", { sqlite: "true" }, "schedule"], + ["manual dispatch", {}, "workflow_dispatch"], +] as const)( + "rejects qualification reuse with %s", + async (_name, override, event) => { + const { CI_FLAGS } = await import( + new URL("../../../scripts/ci/scopes.mjs", import.meta.url).href + ); + const changes: Record = { + ...Object.fromEntries(CI_FLAGS.map((flag: string) => [flag, "false"])), + tier: "reused", + qualification_run_id: "7", + ...override, + }; + const outcome = await requiredRun(changes, { event }); + await expect(outcome.result).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("scheduled admission receipt"), + }); + expect(await readFile(outcome.output, "utf8")).not.toContain("receipt_"); + }, +); diff --git a/tests/boundary/filesystem/ciRequiredLanes.test.ts b/tests/boundary/filesystem/ciRequiredLanes.test.ts index 4cff44e96..b6e02b54a 100644 --- a/tests/boundary/filesystem/ciRequiredLanes.test.ts +++ b/tests/boundary/filesystem/ciRequiredLanes.test.ts @@ -26,7 +26,19 @@ const workflow = async (filename = "ci.yml") => ), ); +const scopeFlags = async () => + z + .object({ CI_FLAGS: z.array(z.string()) }) + .parse( + await import( + new URL("../../../scripts/ci/scopes.mjs", import.meta.url).href + ), + ).CI_FLAGS; + it("binds SQLite compatibility jobs to the build's prepared runtime artifact and root layout", async () => { + expect((await workflow()).jobs["sqlite-runtime"]?.if).toBe( + "needs.changes.outputs.sqlite == 'true'", + ); const steps = z.array( z.object({ uses: z.string().optional(), @@ -52,6 +64,77 @@ it("binds SQLite compatibility jobs to the build's prepared runtime artifact and expect(downloads[0]?.with).toEqual({ name, path: "." }); }); +it("exports every canonical scope with read authority for admission and keeps telemetry outside the gate", async () => { + const { jobs } = await workflow(); + const CI_FLAGS = await scopeFlags(); + const outputs = z.record(z.string(), z.string()).parse(jobs.changes?.outputs); + expect(jobs.changes?.permissions).toEqual({ + contents: "read", + actions: "read", + }); + expect(jobs.build?.permissions).toEqual({ + contents: "read", + actions: "read", + }); + for (const flag of CI_FLAGS) + expect(outputs[flag]).toBe(`\${{ steps.plan.outputs.${flag} }}`); + const steps = z + .array( + z.object({ + run: z.string().optional(), + if: z.string().optional(), + }), + ) + .parse(jobs.required?.steps); + const telemetry = steps.find((step) => + step.run?.includes("scripts/ci/job-timings.mjs"), + ); + expect(telemetry).toBeUndefined(); + const timings = z + .object({ + on: z.object({ + schedule: z.array(z.object({ cron: z.string() })), + workflow_dispatch: z.unknown(), + workflow_run: z.unknown().optional(), + }), + permissions: z.record(z.string(), z.string()), + jobs: z.object({ + report: z.object({ + steps: z.array( + z.object({ + uses: z.string().optional(), + run: z.string().optional(), + with: z.record(z.string(), z.unknown()).optional(), + env: z.record(z.string(), z.unknown()).optional(), + }), + ), + }), + }), + }) + .parse( + parse( + await readFile( + new URL("../../../.github/workflows/ci-timings.yml", import.meta.url), + "utf8", + ), + ), + ); + expect(timings.on.workflow_run).toBeUndefined(); + expect(timings.on.schedule).toHaveLength(1); + expect(timings.permissions).toEqual({ contents: "read", actions: "read" }); + const checkout = timings.jobs.report.steps.find((step) => + step.uses?.startsWith("actions/checkout@"), + ); + expect(checkout?.with).toEqual({ + ref: "${{ github.event.repository.default_branch }}", + "persist-credentials": false, + }); + const report = timings.jobs.report.steps.find((step) => + step.run?.includes("scripts/ci/job-timings-batch.mjs"), + ); + expect(report?.env?.CI_REPOSITORY).toBe("${{ github.repository }}"); +}); + const requiredNeeds = async () => { const { jobs } = await workflow(); return { jobs, needs: z.array(z.string()).parse(jobs.required?.needs) }; @@ -64,6 +147,240 @@ it("makes the required gate wait for every CI lane, including future additions", ); }); +it("holds native and provider fan-out behind static validation while portable feedback stays independent", async () => { + const { jobs } = await workflow(); + const earlyJobs = new Set([ + "changes", + "static", + "build", + "test-shard", + "test", + "docs", + "required", + ]); + for (const [name, job] of Object.entries(jobs)) { + if (earlyJobs.has(name)) continue; + expect(job.needs, `${name} must wait for static validation`).toContain( + "static", + ); + expect(job.if).not.toMatch(/always\(|cancelled\(/u); + } + expect(jobs["test-shard"]?.needs).not.toContain("static"); +}); + +it("binds provider build reuse to the current run while keeping standalone dispatches independent", async () => { + const { jobs } = await workflow(); + const consumers = [ + "browser", + "binary_layout", + "evm", + "javascript_recovery", + "recorded_crash", + "web_network", + "web_runtime", + "web_source_map", + ]; + const buildTerms = z + .string() + .parse(jobs.build?.if) + .split("||") + .map((term) => term.trim()); + // Provider workflow edits select their lane without code=true. The build + // producer must still run, without selecting the portable test shards. + expect(new Set(buildTerms)).toEqual( + new Set( + ["code", ...consumers].map( + (scope) => `needs.changes.outputs.${scope} == 'true'`, + ), + ), + ); + expect(jobs["test-shard"]?.if).toBe("needs.changes.outputs.code == 'true'"); + for (const name of consumers) { + const caller = jobs[name]; + expect(caller?.needs).toContain("build"); + expect(caller?.with).toEqual({ build_cache_artifact: "rea-build-cache" }); + const path = z.string().parse(caller?.uses); + const called = z + .object({ + on: z.object({ + workflow_call: z.object({ + inputs: z.record(z.string(), z.unknown()), + }), + workflow_dispatch: z.unknown(), + }), + jobs: z.record( + z.string(), + z.object({ + steps: z.array( + z.object({ + uses: z.string().optional(), + with: z.record(z.string(), z.unknown()).optional(), + }), + ), + }), + ), + }) + .parse( + parse( + await readFile(new URL(`../../../${path}`, import.meta.url), "utf8"), + ), + ); + expect(called.on.workflow_call.inputs.build_cache_artifact).toMatchObject({ + type: "string", + default: "", + }); + expect(Object.hasOwn(called.on, "workflow_dispatch")).toBe(true); + for (const job of Object.values(called.jobs)) + expect( + job.steps.find( + (step) => step.uses === "./.github/actions/portable-build-cache", + )?.with, + ).toEqual({ build_cache_artifact: "${{ inputs.build_cache_artifact }}" }); + } + const action = z + .object({ + runs: z.object({ + steps: z.array( + z.object({ + id: z.string().optional(), + uses: z.string().optional(), + if: z.string().optional(), + with: z.record(z.string(), z.unknown()).optional(), + "continue-on-error": z.boolean().optional(), + }), + ), + }), + }) + .parse( + parse( + await readFile( + new URL( + "../../../.github/actions/portable-build-cache/action.yml", + import.meta.url, + ), + "utf8", + ), + ), + ); + const download = action.runs.steps.find( + (step) => step.uses === "actions/download-artifact@v4", + ); + expect(download?.with).toEqual({ + name: "${{ inputs.build_cache_artifact }}", + path: ".turbo/cache/", + }); + expect(download?.if).toBe("inputs.build_cache_artifact != ''"); + expect(download?.["continue-on-error"]).not.toBe(true); + for (const step of action.runs.steps.filter( + (step) => step.id === "plan" || step.uses?.startsWith("actions/cache"), + )) + expect(step.if).toContain("inputs.build_cache_artifact == ''"); +}); + +it("runs workflow validation inside required static checks when selected", async () => { + const { jobs } = await workflow(); + const steps = z + .array(z.object({ run: z.string().optional(), if: z.string().optional() })) + .parse(jobs.static?.steps); + const validation = steps.filter((step) => step.run?.includes("actionlint")); + expect(validation).toHaveLength(1); + expect(validation[0]?.if).toBe("needs.changes.outputs.workflows == 'true'"); + expect(jobs.workflows).toBeUndefined(); +}); + +it("leaves cancellation ownership with CI so child lanes cannot cancel another tier", async () => { + const { jobs } = await workflow(); + const children = Object.values(jobs).flatMap((job) => + typeof job.uses === "string" && job.uses.startsWith("./.github/workflows/") + ? [job.uses] + : [], + ); + expect(children.length).toBeGreaterThan(0); + for (const path of children) { + const child = z + .object({ concurrency: z.unknown().optional() }) + .parse( + parse( + await readFile(new URL(`../../../${path}`, import.meta.url), "utf8"), + ), + ); + expect( + child.concurrency, + `${path} must use caller scheduling`, + ).toBeUndefined(); + } +}); + +it("keeps fast feedback separate from complete qualification and release proof", async () => { + const ci = z + .object({ + on: z.object({ + push: z.unknown(), + pull_request: z.unknown(), + schedule: z.array(z.object({ cron: z.string() })), + workflow_call: z.object({ + inputs: z.object({ + source_sha: z.object({ + required: z.literal(true), + type: z.literal("string"), + }), + }), + }), + }), + concurrency: z.object({ + group: z.string(), + "cancel-in-progress": z.string(), + }), + jobs: z.record( + z.string(), + z.object({ + if: z.string().optional(), + steps: z + .array( + z.object({ + run: z.string().optional(), + if: z.string().optional(), + with: z.record(z.string(), z.unknown()).optional(), + }), + ) + .optional(), + }), + ), + }) + .parse( + parse( + await readFile( + new URL("../../../.github/workflows/ci.yml", import.meta.url), + "utf8", + ), + ), + ); + expect(ci.on.schedule).toEqual([ + { cron: "23 0-2,4-23 * * *" }, + { cron: "23 3 * * *" }, + ]); + expect(ci.concurrency.group).toContain("'qualification' || 'feedback'"); + expect(ci.concurrency.group).toContain("inputs.source_sha ||"); + expect(ci.concurrency.group).toContain("github.ref"); + expect(ci.concurrency["cancel-in-progress"]).toBe( + "${{ github.event_name == 'pull_request' && inputs.source_sha == '' && !contains(github.event.pull_request.labels.*.name, 'ci:full') }}", + ); + expect(ci.jobs.required?.if).toBe("${{ always() }}"); + const shards = ci.jobs["test-shard"]?.steps ?? []; + const fast = shards.find((step) => step.run?.includes("npm run test:run")); + const full = shards.find((step) => step.run?.includes("test:ci:shard:run")); + expect(fast?.if).toBe("needs.changes.outputs.tier == 'fast'"); + expect(fast?.run).toContain("--reporter=blob"); + expect(fast?.run).not.toContain("--coverage"); + expect(full?.if).toBe("needs.changes.outputs.tier == 'full'"); + const proof = ci.jobs["package-e2e"]?.steps?.find( + (step) => step.with?.name === "verified-release-package", + ); + expect(proof?.if).toContain("needs.changes.outputs.tier == 'full'"); + expect(proof?.if).toContain("matrix.platform == 'linux'"); + expect(proof?.if).toContain("matrix.architecture == 'x64'"); +}); + it.each([ ["true", "success", true], ["true", "failure", false], @@ -71,34 +388,119 @@ it.each([ ["true", "skipped", false], ["true", "missing", false], ["false", "skipped", true], + ["false", "failure", false], ] as const)( - "enforces the SQLite required gate for code=%s and result=%s", - async (code, result, passes) => { + "enforces mapped required scopes for selected=%s and result=%s", + async (selected, result, passes) => { const workflow = await requiredNeeds(); - // GitHub exposes only direct dependencies in the required job's needs context. - const needs: Record< - string, - { result: string; outputs?: Record } - > = Object.fromEntries( - workflow.needs.map((name) => [name, { result: "success" }]), - ); - needs.changes = { result: "success", outputs: { code } }; - if (result === "missing") delete needs["sqlite-runtime"]; - else if ("sqlite-runtime" in needs) needs["sqlite-runtime"] = { result }; - const execution = executeWorkflowFixture( + for (const [scope, lane] of [ + ["sqlite", "sqlite-runtime"], + ["workflows", "static"], + ] as const) { + // GitHub exposes only direct dependencies in the required job's needs context. + const needs: Record< + string, + { result: string; outputs?: Record } + > = Object.fromEntries( + workflow.needs.map((name) => [name, { result: "success" }]), + ); + needs.changes = { + result: "success", + outputs: { + ...Object.fromEntries( + (await scopeFlags()).map((flag) => [flag, "false"]), + ), + tier: "fast", + code: "true", + [scope]: selected, + }, + }; + if (result === "missing") delete needs[lane]; + else needs[lane] = { result }; + const execution = executeWorkflowFixture( + process.execPath, + [ + fileURLToPath( + new URL("../../../scripts/ci/required.mjs", import.meta.url), + ), + ], + { env: { ...process.env, CI_JOBS: JSON.stringify(needs) } }, + ); + // Static checks remain required even without workflow edits. + const expected = passes && !(lane === "static" && result !== "success"); + if (expected) + await expect(execution).resolves.toMatchObject({ stderr: "" }); + else + await expect(execution).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining(lane), + }); + } + }, +); + +it("rejects incomplete or malformed classification even when available jobs succeeded", async () => { + const flags = await scopeFlags(); + const valid = { + ...Object.fromEntries(flags.map((flag) => [flag, "false"])), + tier: "fast", + }; + const run = (outputs: unknown) => + executeWorkflowFixture( process.execPath, [ fileURLToPath( new URL("../../../scripts/ci/required.mjs", import.meta.url), ), ], - { env: { ...process.env, CI_JOBS: JSON.stringify(needs) } }, + { + env: { + ...process.env, + CI_JOBS: JSON.stringify({ + changes: { result: "success", outputs }, + static: { result: "success" }, + test: { result: "success" }, + }), + CI_QUALIFICATION_DIRECTORY: "", + }, + }, ); - if (passes) await expect(execution).resolves.toMatchObject({ stderr: "" }); - else - await expect(execution).rejects.toMatchObject({ - code: 1, - stderr: expect.stringContaining("sqlite-runtime"), - }); - }, -); + await expect(run(valid)).resolves.toMatchObject({ stderr: "" }); + // Metadata is not a scope, even when its string happens to be "true". + await expect( + run({ ...valid, qualification_run_id: "true" }), + ).resolves.toMatchObject({ stderr: "" }); + for (const outputs of [ + undefined, + null, + {}, + { ...valid, tier: undefined }, + { ...valid, tier: "" }, + { ...valid, tier: "unknown" }, + ]) { + await expect(run(outputs)).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("valid tier"), + }); + } + for (const flag of flags) { + await expect(run({ ...valid, [flag]: undefined })).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining(`scope outputs: ${flag}`), + }); + } + for (const value of ["", "TRUE", "yes", true, false, 0, null, [], {}]) { + await expect(run({ ...valid, sqlite: value })).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("scope outputs: sqlite"), + }); + } + for (const tier of ["full", "reused"]) { + await expect( + run({ ...valid, tier, sqlite: undefined }), + ).rejects.toMatchObject({ + code: 1, + stderr: expect.stringContaining("scope outputs: sqlite"), + }); + } +}); diff --git a/tests/boundary/filesystem/ciTestHistory.test.ts b/tests/boundary/filesystem/ciTestHistory.test.ts new file mode 100644 index 000000000..411e9ece9 --- /dev/null +++ b/tests/boundary/filesystem/ciTestHistory.test.ts @@ -0,0 +1,188 @@ +import { chmod, mkdir, readFile, writeFile } from "node:fs/promises"; +import { delimiter, dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { expect, it } from "vitest"; + +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { executeWorkflowFixture } from "../../support/workflowGit.js"; + +const script = fileURLToPath( + new URL("../../../scripts/ci/test-history.mjs", import.meta.url), +); +const repository = "example/rea"; +const repositoryId = 1; +const now = Date.now(); + +function artifact(id: number, overrides: Record = {}) { + return { + id: id + 100, + name: "test-timings", + expired: false, + created_at: new Date(now - 60_000).toISOString(), + workflow_run: { + id, + repository_id: repositoryId, + head_repository_id: repositoryId, + head_branch: "main", + }, + ...overrides, + }; +} + +function run(id: number, overrides: Record = {}) { + return { + id, + status: "completed", + conclusion: "success", + path: ".github/workflows/ci.yml", + event: "schedule", + created_at: new Date(now - 120_000).toISOString(), + head_branch: "main", + head_repository: { full_name: repository }, + ...overrides, + }; +} + +async function invoke( + artifacts: unknown[], + runs: Record, + options: { + apiError?: boolean; + repository?: string; + repositoryId?: string; + } = {}, +) { + const directory = await createTestTempDirectory("rea-ci-test-history-"); + const fakeBin = join(directory, "bin"); + await mkdir(fakeBin); + const fixture = join(directory, "api.json"); + const calls = join(directory, "api-calls"); + const output = join(directory, "github-output"); + await writeFile(fixture, JSON.stringify({ artifacts, runs })); + await writeFile(output, ""); + await writeFile(calls, ""); + const fakeGh = join(fakeBin, "gh"); + await writeFile( + fakeGh, + [ + "#!/bin/sh", + 'printf \'%s\\n\' "$*" >> "$GH_API_CALLS"', + 'if [ "$GH_API_ERROR" = "true" ]; then exit 1; fi', + 'if [ "$4" = "repos/example/rea/actions/artifacts" ]; then', + ' node -e \'const fs=require("node:fs"); const x=JSON.parse(fs.readFileSync(process.env.GH_FIXTURE_RESPONSE,"utf8")); process.stdout.write(JSON.stringify({artifacts:x.artifacts}));\'', + "else", + ' run_id="${4##*/}"', + ' node -e \'const fs=require("node:fs"); const x=JSON.parse(fs.readFileSync(process.env.GH_FIXTURE_RESPONSE,"utf8")); process.stdout.write(JSON.stringify(x.runs[Number(process.argv[1])] ?? {}));\' "$run_id"', + "fi", + "", + ].join("\n"), + ); + await chmod(fakeGh, 0o755); + const node24 = dirname(process.execPath); + const result = await executeWorkflowFixture(process.execPath, [script], { + cwd: directory, + env: { + ...process.env, + PATH: [fakeBin, node24, process.env.PATH ?? ""].join(delimiter), + GH_FIXTURE_RESPONSE: fixture, + GH_API_CALLS: calls, + GH_API_ERROR: String(options.apiError ?? false), + GH_TOKEN: "fixture-token", + CI_REPOSITORY: options.repository ?? repository, + CI_REPOSITORY_ID: options.repositoryId ?? String(repositoryId), + CI_DEFAULT_BRANCH: "main", + GITHUB_OUTPUT: output, + }, + }); + return { + result, + output: await readFile(output, "utf8"), + calls: await readFile(calls, "utf8"), + }; +} + +it("selects the latest trusted full run that actually published timing history", async () => { + const { result, output, calls } = await invoke( + [ + artifact(15), + artifact(14), + artifact(13, { + workflow_run: { ...artifact(13).workflow_run, head_repository_id: 2 }, + }), + artifact(12, { + workflow_run: { ...artifact(12).workflow_run, head_branch: "feature" }, + }), + artifact(11), + ], + { + 15: run(15, { conclusion: "failure" }), + 14: run(14, { path: ".github/workflows/release.yml" }), + 11: run(11, { event: "workflow_dispatch" }), + }, + ); + + expect(JSON.parse(result.stdout)).toEqual({ run_id: "11" }); + expect(output).toBe("run-id=11\n"); + expect(calls).toContain("name=test-timings"); + expect(calls).toContain("per_page=100"); + expect(calls.match(/actions\/runs\//gu)).toHaveLength(3); + expect(calls).not.toContain("actions/workflows"); +}); + +it("rejects expired, foreign, old, and non-full run candidates", async () => { + const { result, output } = await invoke( + [ + artifact(15, { expired: true }), + artifact(14, { + workflow_run: { ...artifact(14).workflow_run, head_repository_id: 2 }, + }), + artifact(13, { + created_at: new Date(now - 31 * 24 * 60 * 60 * 1000).toISOString(), + }), + artifact(12), + ], + { + 12: run(12, { event: "pull_request" }), + }, + ); + + expect(JSON.parse(result.stdout)).toEqual({ run_id: "" }); + expect(output).toBe("run-id=\n"); +}); + +it("writes an empty run id when GitHub history is unavailable", async () => { + const { result, output } = await invoke([], {}, { apiError: true }); + expect(JSON.parse(result.stdout)).toEqual({ run_id: "" }); + expect(output).toBe("run-id=\n"); +}); + +it("bounds run lookups to five artifacts even when inventory has more", async () => { + const ids = [25, 24, 23, 22, 21, 20, 19]; + const { result, calls } = await invoke( + ids.map((id) => artifact(id)), + Object.fromEntries( + ids.map((id, index) => [ + id, + run(id, index < 5 ? { conclusion: "failure" } : {}), + ]), + ), + ); + + expect(JSON.parse(result.stdout)).toEqual({ run_id: "" }); + expect(calls.match(/actions\/runs\//gu)).toHaveLength(5); +}); + +it("returns empty history without querying for an invalid repository identity", async () => { + const { result, output, calls } = await invoke( + [], + {}, + { + repository: "owner/repo?per_page=100", + repositoryId: "not-an-id", + }, + ); + expect(JSON.parse(result.stdout)).toEqual({ run_id: "" }); + expect(output).toBe("run-id=\n"); + expect(calls).toBe(""); +}); diff --git a/tests/boundary/filesystem/ciTestReports.test.ts b/tests/boundary/filesystem/ciTestReports.test.ts index 0c9bb4ccf..06212ad07 100644 --- a/tests/boundary/filesystem/ciTestReports.test.ts +++ b/tests/boundary/filesystem/ciTestReports.test.ts @@ -1,5 +1,5 @@ import { execFile } from "node:child_process"; -import { readFile, writeFile } from "node:fs/promises"; +import { mkdir, readFile, rm, writeFile } from "node:fs/promises"; import { join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; @@ -8,8 +8,11 @@ import { expect, it } from "vitest"; import { parse } from "yaml"; import { z } from "zod"; +import { planTestSelection } from "../../../scripts/ci/test-selection.mjs"; + import { parseTestDurations } from "../../ciTestSequencer.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { workflowGit } from "../../support/workflowGit.js"; const execute = promisify(execFile); const script = new URL("../../../scripts/ci/test-report.mjs", import.meta.url); @@ -53,6 +56,23 @@ it("collects failed-shard diagnostics before enforcing the shard result", async expect(upload).toBeGreaterThan(merge); expect(gate).toBeGreaterThan(upload); expect(steps[merge]?.if).not.toContain("needs.test-shard.result"); + const merges = steps.filter((step) => step.run?.includes("--reporter=json")); + expect(merges).toHaveLength(2); + for (const step of merges) + expect(step.run).toContain( + "--reporter=./scripts/ci/test-timing-reporter.mjs", + ); + expect(steps[upload]?.with?.path).toContain("test-timings.json"); + expect(steps[upload]?.with).toMatchObject({ "include-hidden-files": true }); + expect(steps[upload]?.with?.path).toContain( + ".cache/ci-test-selection/report.json", + ); + const summary = steps.find((step) => + step.run?.includes("scripts/ci/test-report.mjs"), + ); + expect(summary?.env?.CI_TEST_SELECTION).toBe( + "${{ needs.changes.outputs.test_selection }}", + ); const command = steps[gate]?.run; if (command === undefined) throw new Error("Missing shard result gate"); for (const result of ["failure", "cancelled", "skipped", ""]) { @@ -77,11 +97,67 @@ it("keeps diagnosis available after merge failure and publishes only complete su const history = steps.find((step) => step.with?.name === "test-timings"); expect(history?.if).toContain("success()"); expect(history?.if).toContain("needs.test-shard.result == 'success'"); + expect(history?.if).toContain("needs.changes.outputs.tier == 'full'"); expect(history?.with?.path).toBe(".cache/ci-test-history/test-results.json"); - const download = (await workflow()).build!.steps.find( + const buildSteps = (await workflow()).build!.steps; + const lookup = buildSteps.find((step) => + step.run?.includes("test-history.mjs"), + ); + expect(lookup?.env).toMatchObject({ + CI_REPOSITORY: "${{ github.repository }}", + CI_REPOSITORY_ID: "${{ github.repository_id }}", + CI_DEFAULT_BRANCH: "${{ github.event.repository.default_branch }}", + }); + const download = buildSteps.find( (step) => step.name === "Download previous timing report", ); expect(download?.with?.name).toBe(history?.with?.name); + expect(download?.with?.["run-id"]).toBe( + "${{ steps.history.outputs.run-id }}", + ); +}); + +it("rejects successful shard reports with missing or duplicate portable files", async () => { + const root = await createTestTempDirectory("rea-ci-report-inventory-"); + await workflowGit(root, ["init"]); + await mkdir(join(root, "tests")); + for (const name of ["first", "second"]) + await writeFile(join(root, `tests/${name}.test.ts`), "// fixture\n"); + await workflowGit(root, ["add", "tests"]); + const run = async (names: readonly string[]) => { + await writeFile( + join(root, "test-timings.json"), + JSON.stringify({ + version: 1, + success: true, + files: names.map((name) => ({ name, durationMs: 1 })), + }), + ); + return execute(process.execPath, [fileURLToPath(script)], { + cwd: root, + env: { + ...process.env, + SHARD_RESULT: "success", + MERGE_RESULT: "success", + CI_VERIFY_TEST_INVENTORY: "true", + }, + }); + }; + await expect( + run(["tests/first.test.ts", "tests/second.test.ts"]), + ).resolves.toMatchObject({ stderr: "" }); + for (const names of [ + ["tests/first.test.ts"], + ["tests/first.test.ts", "tests/second.test.ts", "tests/unplanned.test.ts"], + ["tests/first.test.ts", "tests/first.test.ts", "tests/second.test.ts"], + ]) { + await expect(run(names)).rejects.toMatchObject({ + stderr: expect.stringContaining("Incomplete portable test inventory"), + }); + await expect( + readFile(join(root, ".cache/ci-test-history/test-results.json")), + ).rejects.toMatchObject({ code: "ENOENT" }); + } }); it("runs the existing onboarding and Python producer guards from their selected CI owners", async () => { @@ -116,20 +192,25 @@ it("exports portable timing history and removes it on a failed, partial, or inva const summary = join(root, "summary.md"); const history = join(root, ".cache/ci-test-history/test-results.json"); const report = { + version: 1, success: true, - numFailedTests: 0, - testResults: [ + files: [ { name: join(root, "tests/slow.test.ts"), - startTime: 10, - endTime: 110, - assertionResults: [{ large: "not timing data" }], + durationMs: 100, + phases: { + execution: 20, + preparation: 20, + environment: 10, + imports: 40, + setup: 10, + }, }, - { name: join(root, "tests/fast.test.ts"), startTime: 20, endTime: 30 }, + { name: join(root, "tests/fast.test.ts"), durationMs: 10 }, ], }; const run = async (value: unknown, shards = "success", merge = "success") => { - await writeFile(join(root, "test-results.json"), JSON.stringify(value)); + await writeFile(join(root, "test-timings.json"), JSON.stringify(value)); await writeFile(summary, ""); return execute(process.execPath, [fileURLToPath(script)], { cwd: root, @@ -143,7 +224,8 @@ it("exports portable timing history and removes it on a failed, partial, or inva }; await run(report); const contents = await readFile(history, "utf8"); - expect(contents).not.toContain("assertionResults"); + expect(contents).not.toContain("phases"); + expect(contents).not.toContain("startTime"); expect(contents).not.toContain(root); expect( parseTestDurations(contents, resolve(root, "different-checkout")), @@ -154,7 +236,7 @@ it("exports portable timing history and removes it on a failed, partial, or inva ]), ); for (const [value, shards, merge] of [ - [{ ...report, success: false, numFailedTests: 1 }, "failure", "failure"], + [{ ...report, success: false }, "failure", "failure"], [report, "cancelled", "success"], [report, "success", "failure"], ] as const) { @@ -167,8 +249,211 @@ it("exports portable timing history and removes it on a failed, partial, or inva await expect( run({ ...report, - testResults: [{ name: "../outside.test.ts", startTime: 1, endTime: 3 }], + files: [{ name: "../outside.test.ts", durationMs: 2 }], + }), + ).rejects.toMatchObject({ code: 1 }); + await expect(readFile(history)).rejects.toMatchObject({ code: "ENOENT" }); + await run(report); + await expect( + run({ + ...report, + files: [{ name: "tests/invalid.test.ts", durationMs: -1 }], }), ).rejects.toMatchObject({ code: 1 }); await expect(readFile(history)).rejects.toMatchObject({ code: "ENOENT" }); }); + +it("recovers complete module costs from real blob reports without executing tests again", async () => { + const root = await createTestTempDirectory("rea-ci-module-timing-"); + const config = join(root, "vitest.config.mjs"); + await writeFile( + config, + 'export default { test: { globals: true, include: ["sample.test.js"], maxWorkers: 1 } };', + ); + await writeFile( + join(root, "sample.test.js"), + [ + 'import { writeFileSync } from "node:fs";', + "beforeAll(() => new Promise(resolve => setTimeout(resolve, 80)));", + "afterAll(() => new Promise(resolve => setTimeout(resolve, 80)));", + 'it("has cheap assertions and expensive outer hooks", () => { writeFileSync("executed", "yes"); expect(1).toBe(1); });', + ].join("\n"), + ); + const vitest = fileURLToPath( + new URL("../../../node_modules/vitest/vitest.mjs", import.meta.url), + ); + const reporter = fileURLToPath( + new URL("../../../scripts/ci/test-timing-reporter.mjs", import.meta.url), + ); + const run = (args: string[]) => + execute(process.execPath, [vitest, ...args, "--config", config], { + cwd: root, + env: process.env, + timeout: 20_000, + }); + await run(["run", "--reporter=blob"]); + expect(await readFile(join(root, "executed"), "utf8")).toBe("yes"); + await rm(join(root, "executed")); + await run([ + "--merge-reports", + `--reporter=${reporter}`, + "--reporter=json", + "--outputFile.json=body.json", + ]); + await expect(readFile(join(root, "executed"))).rejects.toMatchObject({ + code: "ENOENT", + }); + const report = z + .object({ + version: z.literal(1), + success: z.literal(true), + files: z.array( + z.object({ + name: z.string(), + durationMs: z.number(), + phases: z.record(z.string(), z.number()), + }), + ), + }) + .parse(JSON.parse(await readFile(join(root, "test-timings.json"), "utf8"))); + expect( + JSON.parse(await readFile(join(root, "test-timings.json"), "utf8")), + ).toMatchObject({ + reason: "passed", + unhandledErrors: 0, + files: [{ state: "passed" }], + }); + expect(report.files).toHaveLength(1); + const file = report.files[0]!; + const json = z + .object({ + testResults: z.array( + z.object({ startTime: z.number(), endTime: z.number() }), + ), + }) + .parse(JSON.parse(await readFile(join(root, "body.json"), "utf8"))); + const body = json.testResults[0]!; + expect( + file.phases.execution! - (body.endTime - body.startTime), + ).toBeGreaterThan(100); + expect(file.phases.imports).toBeGreaterThan(0); + expect(file.phases.preparation).toBeGreaterThan(0); + expect(file.durationMs).toBeCloseTo( + Object.values(file.phases).reduce((sum, value) => sum + value, 0), + ); + await execute(process.execPath, [fileURLToPath(script)], { + cwd: root, + env: { ...process.env, SHARD_RESULT: "success", MERGE_RESULT: "success" }, + }); + expect( + parseTestDurations( + await readFile( + join(root, ".cache/ci-test-history/test-results.json"), + "utf8", + ), + root, + )?.get("sample.test.js"), + ).toBe(file.durationMs); + + await writeFile( + join(root, "sample.test.js"), + 'it("fails", () => { throw new Error("fixture failure"); });', + ); + await expect(run(["run", "--reporter=blob"])).rejects.toMatchObject({ + code: 1, + }); + await expect( + run(["--merge-reports", `--reporter=${reporter}`]), + ).rejects.toMatchObject({ code: 1 }); + const failed = JSON.parse( + await readFile(join(root, "test-timings.json"), "utf8"), + ) as unknown; + expect(failed).toMatchObject({ + version: 1, + success: false, + reason: "failed", + unhandledErrors: 0, + files: [{ state: "failed" }], + }); + // Even a caller accidentally marking the merge successful cannot publish this report. + await execute(process.execPath, [fileURLToPath(script)], { + cwd: root, + env: { ...process.env, SHARD_RESULT: "success", MERGE_RESULT: "success" }, + }); + await expect( + readFile(join(root, ".cache/ci-test-history/test-results.json")), + ).rejects.toMatchObject({ code: "ENOENT" }); +}); + +it("records failed omissions from full reports without treating partial or unhandled outcomes as parity", async () => { + const root = await createTestTempDirectory("rea-ci-selection-report-"); + await workflowGit(root, ["init"]); + const paths = [ + "src/sqlite/provider.test.ts", + "src/evm/provider.test.ts", + "tests/boundary/mcp/workflow.test.ts", + ]; + for (const path of paths) { + await mkdir(join(root, path, ".."), { recursive: true }); + await writeFile(join(root, path), "// fixture\n"); + } + await workflowGit(root, ["add", "src", "tests"]); + const timing = { + version: 1, + success: false, + reason: "failed", + unhandledErrors: 0, + files: paths.map((name, index) => ({ + name, + durationMs: 10, + state: index === 1 ? "failed" : "passed", + })), + }; + const run = async (report: unknown) => { + await writeFile(join(root, "test-timings.json"), JSON.stringify(report)); + await execute(process.execPath, [fileURLToPath(script)], { + cwd: root, + env: { + ...process.env, + SHARD_RESULT: "failure", + MERGE_RESULT: "failure", + CI_VERIFY_TEST_INVENTORY: "true", + CI_TEST_SELECTION: JSON.stringify( + planTestSelection(["src/sqlite/Provider.ts"], "pull_request", "fast"), + ), + GITHUB_SHA: "merge-sha", + CI_PR_HEAD_SHA: "pr-head-sha", + }, + }); + return JSON.parse( + await readFile( + join(root, ".cache/ci-test-selection/report.json"), + "utf8", + ), + ) as unknown; + }; + expect(await run(timing)).toMatchObject({ + observational: true, + complete: true, + selected: [paths[0], paths[2]], + omitted: [paths[1]], + missedFailures: [paths[1]], + executionSha: "merge-sha", + prHeadSha: "pr-head-sha", + }); + for (const report of [ + { ...timing, files: timing.files.slice(0, 1) }, + { ...timing, unhandledErrors: 1 }, + { ...timing, reason: "interrupted" }, + ]) + expect(await run(report)).toMatchObject({ complete: false }); + await expect(run({ ...timing, files: "invalid" })).rejects.toMatchObject({ + code: 1, + }); + await expect( + readFile(join(root, ".cache/ci-test-selection/report.json")), + ).rejects.toMatchObject({ code: "ENOENT" }); + await expect( + readFile(join(root, ".cache/ci-test-history/test-results.json")), + ).rejects.toMatchObject({ code: "ENOENT" }); +}); diff --git a/tests/boundary/filesystem/ciTestSequencer.test.ts b/tests/boundary/filesystem/ciTestSequencer.test.ts index 6177d9481..fec32826d 100644 --- a/tests/boundary/filesystem/ciTestSequencer.test.ts +++ b/tests/boundary/filesystem/ciTestSequencer.test.ts @@ -17,24 +17,24 @@ describe("CI test history", () => { const root = resolve("/workspace/rea"); const durations = parseTestDurations( JSON.stringify({ + version: 1, success: true, - numFailedTests: 0, - testResults: [ + files: [ { name: join(root, "tests/slow.test.ts"), - startTime: 10, - endTime: 110, + durationMs: 100, }, { name: join(root, "tests/slow.test.ts"), - startTime: 20, - endTime: 80, + durationMs: 60, }, { name: resolve(root, "../outside.test.ts"), - startTime: 10, - endTime: 1000, + durationMs: 990, }, + { name: "tests/negative.test.ts", durationMs: -1 }, + { name: "tests/zero.test.ts", durationMs: 0 }, + { name: "tests/invalid.test.ts", durationMs: "100" }, null, ], }), @@ -43,7 +43,20 @@ describe("CI test history", () => { expect(durations).toEqual(new Map([["tests/slow.test.ts", 100]])); expect( - parseTestDurations('{"success": false, "numFailedTests": 1}', root), + parseTestDurations('{"version": 1, "success": false, "files": []}', root), + ).toBeUndefined(); + // Legacy test-body spans must not be mixed with complete module costs. + expect( + parseTestDurations( + JSON.stringify({ + success: true, + numFailedTests: 0, + testResults: [ + { name: "tests/legacy.test.ts", startTime: 0, endTime: 100 }, + ], + }), + root, + ), ).toBeUndefined(); expect(parseTestDurations("not json", root)).toBeUndefined(); expect(parseTestDurations("null", root)).toBeUndefined(); diff --git a/tests/boundary/filesystem/ciVerifiedPackage.test.ts b/tests/boundary/filesystem/ciVerifiedPackage.test.ts new file mode 100644 index 000000000..ff5045024 --- /dev/null +++ b/tests/boundary/filesystem/ciVerifiedPackage.test.ts @@ -0,0 +1,137 @@ +import { createHash } from "node:crypto"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { expect, it } from "vitest"; + +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { + executeWorkflowFixture, + workflowGit, +} from "../../support/workflowGit.js"; + +const validator = fileURLToPath( + new URL("../../../scripts/ci/verified-package.mjs", import.meta.url), +); +type Fixture = Awaited>; +type FixtureOptions = { + override?: Record; + manifestContents?: string; + writeManifest?: boolean; +}; + +it("validates a tarball against the exact checkout and current workflow attempt", async () => { + const fixture = await createFixture(); + const result = await validate(fixture); + + expect(result.stdout.trim()).toBe( + join(fixture.artifactDirectory, "package.tgz"), + ); + expect(await readFile(fixture.output, "utf8")).toBe( + `tarball=${join(fixture.artifactDirectory, "package.tgz")}\n`, + ); +}); + +it("rejects a workflow SHA that differs from the checked out HEAD", async () => { + const fixture = await createFixture(); + + await expect(validate(fixture, "c".repeat(40))).rejects.toThrow(); +}); + +it.each([ + ["wrong checkout SHA", { sourceSha: "c".repeat(40) }], + ["wrong workflow run", { runId: 124 }], + ["future workflow attempt", { runAttempt: 3 }], + ["wrong verifier platform", { platform: "darwin" }], + ["wrong verifier architecture", { architecture: "arm64" }], + ["wrong package digest", { sha256: "c".repeat(64) }], +])("rejects %s", async (_label, override) => { + const fixture = await createFixture({ override }); + + await expect(validate(fixture)).rejects.toThrow(); +}); + +it("accepts an earlier successful attempt from the same workflow run", async () => { + const fixture = await createFixture({ override: { runAttempt: 1 } }); + + await expect(validate(fixture)).resolves.toMatchObject({ + stdout: expect.any(String), + }); +}); + +it.each([ + ["malformed manifest", "{"], + ["manifest with missing fields", JSON.stringify({ schemaVersion: 1 })], +])("rejects %s", async (_label, contents) => { + const fixture = await createFixture({ manifestContents: contents }); + + await expect(validate(fixture)).rejects.toThrow(); +}); + +it("rejects an absent manifest", async () => { + const fixture = await createFixture({ writeManifest: false }); + + await expect(validate(fixture)).rejects.toThrow(); +}); + +async function createFixture({ + override = {}, + manifestContents, + writeManifest = true, +}: FixtureOptions = {}) { + const directory = await createTestTempDirectory("rea-verified-package-"); + await workflowGit(directory, ["init", "--initial-branch=main"]); + await writeFile( + join(directory, "package.json"), + '{"name":"fixture","version":"1.2.3"}\n', + ); + await workflowGit(directory, ["add", "package.json"]); + await workflowGit(directory, [ + "commit", + "-m", + "test: verified package fixture", + ]); + const sourceSha = await workflowGit(directory, ["rev-parse", "HEAD"]); + const artifactDirectory = join(directory, "artifact"); + await mkdir(artifactDirectory); + const archive = "verified tarball fixture"; + await writeFile(join(artifactDirectory, "package.tgz"), archive); + const manifest = { + schemaVersion: 1, + sourceSha, + runId: 123, + runAttempt: 2, + platform: "linux", + architecture: "x64", + packageVersion: "1.2.3", + nodeVersion: process.version, + sha256: createHash("sha256").update(archive).digest("hex"), + ...override, + }; + if (writeManifest) + await writeFile( + join(artifactDirectory, "manifest.json"), + manifestContents ?? JSON.stringify(manifest), + ); + const output = join(directory, "github-output"); + await writeFile(output, ""); + return { directory, sourceSha, artifactDirectory, output }; +} + +function validate(fixture: Fixture, sourceSha = fixture.sourceSha) { + return executeWorkflowFixture( + process.execPath, + [validator, "validate", fixture.artifactDirectory], + { + cwd: fixture.directory, + env: { + ...process.env, + GITHUB_SHA: sourceSha, + GITHUB_RUN_ID: "123", + GITHUB_RUN_ATTEMPT: "2", + GITHUB_OUTPUT: fixture.output, + }, + }, + ); +} diff --git a/tests/boundary/filesystem/clientConfigurationTransactions.test.ts b/tests/boundary/filesystem/clientConfigurationTransactions.test.ts index 477085381..507b7137e 100644 --- a/tests/boundary/filesystem/clientConfigurationTransactions.test.ts +++ b/tests/boundary/filesystem/clientConfigurationTransactions.test.ts @@ -1,13 +1,91 @@ import { chmod, readFile, writeFile } from "node:fs/promises"; +import { createHash } from "node:crypto"; import { join } from "node:path"; import { describe, expect, it } from "vitest"; import { parse as parseToml } from "smol-toml"; -import { configureClientConfiguration } from "../../../src/application/SetupClientConfiguration.js"; +import { + configureClientConfiguration, + inspectClientConfiguration, +} from "../../../src/application/SetupClientConfiguration.js"; import { systemUninstallHost } from "../../../src/application/Uninstall.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +it("accepts a literal UTF-8 replacement character without changing its value", async () => { + const root = await createTestTempDirectory("rea-client-config-utf8-"); + const configPath = join(root, "config.json"); + const original = Buffer.concat([ + Buffer.from('{"label":"'), + Buffer.from("\uFFFD"), + Buffer.from('"}'), + ]); + await writeFile(configPath, original); + const result = await configureClientConfiguration( + { name: "cursor", format: "json", configPath }, + {}, + ["rea", "mcp"], + ); + expect(result.status).toBe("configured"); + expect(await readFile(`${configPath}.rea.backup`)).toEqual(original); + expect(JSON.parse(await readFile(configPath, "utf8")).label).toBe("\uFFFD"); +}); + +it("previews and creates a current recovery backup while preserving the first backup", async () => { + const root = await createTestTempDirectory("rea-client-current-recovery-"); + const configPath = join(root, "config.json"); + const firstOriginal = '{"keep":"first"}\n'; + const currentOriginal = '{"keep":"current"}\n'; + const client = { name: "cursor", format: "json", configPath } as const; + await writeFile(configPath, currentOriginal); + await writeFile(`${configPath}.rea.backup`, firstOriginal); + + const recoveryPath = `${configPath}.rea.backup.${createHash("sha256") + .update(currentOriginal, "utf8") + .digest("hex")}.recovery`; + expect(await inspectClientConfiguration(client, {}, ["rea", "mcp"])).toEqual({ + status: "update", + backupPath: recoveryPath, + }); + + expect( + await configureClientConfiguration(client, {}, ["rea", "mcp"]), + ).toEqual({ status: "configured", backupPath: recoveryPath }); + expect(await readFile(`${configPath}.rea.backup`, "utf8")).toBe( + firstOriginal, + ); + expect(await readFile(recoveryPath, "utf8")).toBe(currentOriginal); +}); + +it("blocks configuration when the planned content-addressed backup is occupied", async () => { + const root = await createTestTempDirectory("rea-client-recovery-conflict-"); + const configPath = join(root, "config.json"); + const firstOriginal = '{"keep":"first"}\n'; + const currentOriginal = '{"keep":"current"}\n'; + const client = { name: "cursor", format: "json", configPath } as const; + await writeFile(configPath, currentOriginal); + await writeFile(`${configPath}.rea.backup`, firstOriginal); + const recoveryPath = `${configPath}.rea.backup.${createHash("sha256") + .update(currentOriginal, "utf8") + .digest("hex")}.recovery`; + await writeFile(recoveryPath, "occupied by other data"); + + expect( + await inspectClientConfiguration(client, {}, ["rea", "mcp"]), + ).toMatchObject({ + status: "invalid", + remediation: expect.stringContaining(recoveryPath), + }); + expect( + await configureClientConfiguration(client, {}, ["rea", "mcp"]), + ).toEqual({ status: "failed", reason: "backup" }); + expect(await readFile(configPath, "utf8")).toBe(currentOriginal); + expect(await readFile(`${configPath}.rea.backup`, "utf8")).toBe( + firstOriginal, + ); + expect(await readFile(recoveryPath, "utf8")).toBe("occupied by other data"); +}); + describe("client configuration write failures", () => { it.skipIf(process.platform === "win32" || process.getuid?.() === 0).each([ ["json", configureClientConfiguration], diff --git a/tests/boundary/filesystem/developmentTests.test.ts b/tests/boundary/filesystem/developmentTests.test.ts deleted file mode 100644 index 1b52bb475..000000000 --- a/tests/boundary/filesystem/developmentTests.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - copyFile, - mkdir, - readFile, - symlink, - writeFile, -} from "node:fs/promises"; -import { join } from "node:path"; - -import { expect, it } from "vitest"; - -import { execFileOutput } from "../../../src/process/ExecFileOutput.js"; -import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; - -const run = (root: string, command: string, arguments_: readonly string[]) => - execFileOutput(command, arguments_, { - cwd: root, - stopSignal: "SIGTERM", - timeout: 20_000, - }); - -const commit = (root: string, message: string) => - run(root, "git", [ - "-c", - "user.name=REA fixture", - "-c", - "user.email=fixture@example.invalid", - "-c", - "commit.gpgSign=false", - "commit", - "--quiet", - "-m", - message, - ]); - -const fixture = async () => { - const root = await createTestTempDirectory("rea-development-tests-"); - await mkdir(join(root, "scripts", "lib"), { recursive: true }); - await mkdir(join(root, "src")); - for (const path of [ - "scripts/run-development-tests.mjs", - "scripts/lib/development-tests.mjs", - ]) - await copyFile(join(process.cwd(), path), join(root, path)); - await symlink( - join(process.cwd(), "node_modules"), - join(root, "node_modules"), - process.platform === "win32" ? "junction" : undefined, - ); - await writeFile(join(root, "package.json"), '{"type":"module"}\n'); - await writeFile(join(root, ".gitignore"), "node_modules\nselected.txt\n"); - await writeFile( - join(root, "vitest.config.mjs"), - 'export default { test: { projects: [{ test: { name: "domain", include: ["src/**/*.test.ts"] } }] } };\n', - ); - await writeFile(join(root, "src", "value.ts"), "export const value = 1;\n"); - await writeFile( - join(root, "src", "value.test.ts"), - 'import { expect, it } from "vitest"; import { writeFileSync } from "node:fs"; import { value } from "./value.js"; it("checks the selected source", () => { expect(value).toBe(1); writeFileSync("selected.txt", String(value)); });\n', - ); - await run(root, "git", ["init", "--quiet"]); - await run(root, "git", ["add", "."]); - await commit(root, "fixture"); - return root; -}; - -const testCommand = (root: string, ...arguments_: string[]) => - run(root, process.execPath, [ - "scripts/run-development-tests.mjs", - ...arguments_, - ]); - -it("executes an explicitly selected source test on a clean tree without build artifacts", async () => { - const root = await fixture(); - const { stdout: status } = await run(root, "git", ["status", "--porcelain"]); - expect(status).toBe(""); - await testCommand(root, "local", "src/value.test.ts"); - expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1"); -}); - -it("uses committed dependency changes since the requested Git base to select source tests", async () => { - const root = await fixture(); - const { stdout: base } = await run(root, "git", ["rev-parse", "HEAD"]); - await writeFile(join(root, "src", "value.ts"), "export const value = 2;\n"); - await run(root, "git", ["add", "src/value.ts"]); - await commit(root, "change dependency"); - await expect( - testCommand(root, "changed", "--base", base.trim()), - ).rejects.toMatchObject({ - code: 1, - stdout: expect.stringContaining("src/value.test.ts"), - stderr: expect.stringContaining("expected 2 to be 1"), - }); -}); - -it("rejects a compiled boundary in the source-only command and a missing exact test", async () => { - const root = await fixture(); - await expect( - testCommand(root, "local", "tests/acceptance/runtime.test.ts"), - ).rejects.toMatchObject({ - code: 1, - stderr: expect.stringContaining("Use test:focused"), - }); - await expect( - testCommand(root, "local", "src/missing.test.ts"), - ).rejects.toMatchObject({ - code: 1, - stderr: expect.stringContaining("ENOENT"), - }); -}); diff --git a/tests/boundary/filesystem/ghidraPspExtension.test.ts b/tests/boundary/filesystem/ghidraPspExtension.test.ts index 88e25939a..65a4d1512 100644 --- a/tests/boundary/filesystem/ghidraPspExtension.test.ts +++ b/tests/boundary/filesystem/ghidraPspExtension.test.ts @@ -52,7 +52,7 @@ const target = { const host: GhidraInstallationHost = { platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.3\n", + readText: () => "application.version=12.1.3\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.12", @@ -191,12 +191,9 @@ describe.skipIf(process.platform === "win32")( it.each([ ["name=other\nversion=12.1.3\n", "does not match"], ["name=ghidra-allegrex\nversion=12.1.4\n", "does not match"], - [ - "name=ghidra-allegrex\nversion=12.1.3\nversion=12.1.3\n", - "exactly one version", - ], + ["name=ghidra-allegrex\nversion=12.1.\\uZZZZ\n", "Unicode escape"], ])( - "rejects incompatible or ambiguous extension metadata %s", + "rejects mismatched or malformed extension metadata %s", async (properties, reason) => { const { root } = await installation(); await writeFile(join(root, "extension.properties"), properties); @@ -504,3 +501,38 @@ describe.skipIf(process.platform === "win32")( }); }, ); + +describe.skipIf(process.platform === "win32")( + "PSP extension property syntax", + () => { + it.each([ + { + form: "escaped key and value with colon separator", + properties: "n\\u0061me : ghidra-allegrex\nver\\u0073ion=12.1.3\n", + }, + { + form: "continued key and value lines", + properties: "name=ghidra-\\\n allegrex\nversion=12.1.\\\n 3\n", + }, + { + form: "duplicate keys use the last value", + properties: + "name=wrong\nname=ghidra-allegrex\nversion=12.1.4\nversion=12.1.3\n", + }, + ])( + "accepts Java Properties $form and hashes raw bytes", + async ({ properties }) => { + const { root } = await installation(); + const canonical = await inspectGhidraPspExtension(root, "12.1.3"); + const latin1Properties = Buffer.from( + `${properties}author=caf\u00e9\n`, + "latin1", + ); + await writeFile(join(root, "extension.properties"), latin1Properties); + const extension = await inspectGhidraPspExtension(root, "12.1.3"); + expect(extension.id).toBe("ghidra-allegrex"); + expect(extension.sha256).not.toBe(canonical.sha256); + }, + ); + }, +); diff --git a/tests/boundary/filesystem/installScript.test.ts b/tests/boundary/filesystem/installScript.test.ts index 3fbcf7a3c..0f2e14730 100644 --- a/tests/boundary/filesystem/installScript.test.ts +++ b/tests/boundary/filesystem/installScript.test.ts @@ -11,6 +11,7 @@ import { import { join } from "node:path"; import { promisify } from "node:util"; +import { spawn as spawnPty } from "@lydell/node-pty"; import { describe, expect, it } from "vitest"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; @@ -185,6 +186,69 @@ describe("curl installer scenarios", { timeout: 20_000 }, () => { }); }); +describe("installer TTY fallback", { timeout: 20_000 }, () => { + it("skips automatic setup when stderr is redirected", async () => { + const fixture = await createFixture(); + const script = join(process.cwd(), "install.sh"); + const wrapper = ` + const { spawnSync } = require("node:child_process"); + const { openSync, closeSync } = require("node:fs"); + const stderr = openSync(process.argv[2], "w"); + const child = spawnSync("/bin/bash", [process.argv[1], ...process.argv.slice(3)], { + stdio: ["inherit", "inherit", stderr], + env: process.env, + }); + closeSync(stderr); + process.exit(child.status ?? 1); + `; + let output = ""; + const terminal = spawnPty( + process.execPath, + ["-e", wrapper, script, fixture.installerStderrLog, "--version", "0.3.0"], + { + cwd: process.cwd(), + env: { + ...process.env, + HOME: fixture.home, + TMPDIR: fixture.temporary, + PATH: `${fixture.bin}:/usr/bin:/bin`, + FAKE_NPM_LOG: fixture.npmLog, + FAKE_REA_LOG: fixture.reaLog, + FAKE_REA_SOURCE: join(fixture.bin, "rea-source"), + FAKE_NPM_PREFIX: join(fixture.home, ".npm-global"), + TERM: "xterm-256color", + }, + name: "xterm-256color", + cols: 120, + rows: 40, + }, + ); + let timedOut = false; + const exitCode = await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + timedOut = true; + terminal.kill(); + }, 10_000); + terminal.onData((data) => { + output += data; + }); + terminal.onExit(({ exitCode: code }) => { + clearTimeout(timeout); + if (timedOut) + reject(new Error(`Installer PTY timed out after output: ${output}`)); + else resolve(code); + }); + }); + + expect(exitCode).toBe(0); + expect(output).toContain( + `Run ${join(fixture.home, ".local/bin/rea")} setup to configure Hopper and agents.`, + ); + expect(await readFile(fixture.reaLog, "utf8")).toBe("--version\n"); + expect(await readFile(fixture.installerStderrLog, "utf8")).toBe(""); + }); +}); + describe("truncated installer download", { timeout: 20_000 }, () => { it("runs nothing from a download truncated after the npm install line", async () => { const fixture = await createFixture(); @@ -433,6 +497,7 @@ interface InstallerFixture { readonly temporary: string; readonly npmLog: string; readonly reaLog: string; + readonly installerStderrLog: string; } const getProcessOutput = ( @@ -456,6 +521,7 @@ const createFixture = async (): Promise => { const temporary = join(root, "tmp"); const npmLog = join(root, "npm.log"); const reaLog = join(root, "rea.log"); + const installerStderrLog = join(root, "installer.stderr.log"); await Promise.all([mkdir(home), mkdir(bin), mkdir(temporary)]); await Promise.all([ executable( @@ -507,7 +573,7 @@ exit 0 symlink(`/usr/bin/${command}`, join(bin, command)), ), ]); - return { home, bin, temporary, npmLog, reaLog }; + return { home, bin, temporary, npmLog, reaLog, installerStderrLog }; }; const executable = async (path: string, source: string): Promise => { diff --git a/tests/boundary/filesystem/javascript-applications/javascriptModuleRelationships.test.ts b/tests/boundary/filesystem/javascript-applications/javascriptModuleRelationships.test.ts index be51b9bb4..cdd95bc97 100644 --- a/tests/boundary/filesystem/javascript-applications/javascriptModuleRelationships.test.ts +++ b/tests/boundary/filesystem/javascript-applications/javascriptModuleRelationships.test.ts @@ -15,6 +15,60 @@ import { } from "../../../support/javascriptApplicationFixture.js"; describe("TypeScript source module loader semantics", () => { + it("keeps whole type-only declarations out of runtime module relationships", async () => { + const root = await createTestTempDirectory("rea-type-module-links-"); + await writeFixtureFiles(root, { + "main.ts": ` + import type { Whole } from "./whole"; + export type { Remote } from "./remote"; + import { type Inline } from "./inline"; + export type LocalType = string; + export interface LocalInterface { value: string } + `, + "whole.ts": "export interface Whole { value: string }", + "remote.ts": "export interface Remote { value: string }", + "inline.ts": "export interface Inline { value: string }", + }); + + const { graph } = await reconstructJavaScriptFixture(root); + const source = findSourceModule(graph, "main.ts"); + const sourceProperties = source?.observations.find( + ({ properties }) => properties.semantic_role === "source-module", + )?.properties; + + expect(sourceProperties).toMatchObject({ + import_relationships: 0, + type_relationships: 5, + export_names: [], + type_export_names: ["LocalInterface", "LocalType", "Remote"], + }); + expect( + graph.edges.filter( + ({ relation, properties }) => + relation === "imports" && + ["./whole", "./remote"].includes(String(properties.specifier)), + ), + ).toEqual([]); + expect( + graph.edges.find( + ({ source_node_id, relation, properties }) => + source_node_id === source?.node_id && + relation === "imports" && + properties.kind === "static-import" && + properties.specifier === "./inline", + ), + ).toBeDefined(); + expect( + source?.observations + .flatMap(({ evidence }) => evidence.limitations) + .join(" "), + ).toContain( + "inline type-only imports or re-exports may preserve a module side-effect dependency", + ); + expect(findExportNode(graph, "main.ts", "LocalType")).toBeUndefined(); + expect(findExportNode(graph, "main.ts", "LocalInterface")).toBeUndefined(); + }); + it("uses emitted TypeScript loader semantics without changing dynamic imports", async () => { const root = await createTestTempDirectory("rea-cts-module-loader-"); await writeFixtureFiles(root, { @@ -98,7 +152,7 @@ describe("TypeScript source module loader semantics", () => { }); }); -describe("CommonJS and ESM module relationships", () => { +describe("JavaScript module relationships", () => { it("composes bindings, re-exports, dynamic imports, and JSON modules", async () => { const root = await moduleFixture(); const first = await reconstructJavaScriptFixture(root); @@ -234,6 +288,122 @@ describe("CommonJS and ESM module relationships", () => { }); }); +describe("Compiler-dependent TypeScript resolution", () => { + it("retains only compiler-independent targets for .ts static imports", async () => { + const root = await createTestTempDirectory("rea-ts-conditional-loader-"); + await writeFixtureFiles(root, { + "package.json": '{"type":"commonjs"}', + "main.ts": `import { value as different } from "different"; +import { value as same } from "same"; +void different; void same;`, + "node_modules/different/package.json": JSON.stringify({ + exports: { + ".": { + import: "./import.mjs", + require: "./require.cjs", + }, + }, + }), + "node_modules/different/import.mjs": "export const value = 'import';", + "node_modules/different/require.cjs": "exports.value = 'require';", + "node_modules/same/package.json": JSON.stringify({ + exports: { ".": { import: "./shared.js", require: "./shared.js" } }, + }), + "node_modules/same/shared.js": "export const value = 'shared';", + }); + + const { graph } = await reconstructJavaScriptFixture(root); + const different = findRelationshipEdge(graph, { + kind: "import", + specifier: "different", + localName: "different", + }); + const same = findRelationshipEdge(graph, { + kind: "import", + specifier: "same", + localName: "same", + resolvedPath: "node_modules/same/shared.js", + }); + const staticFinding = (specifier: string) => + graph.edges.find( + ({ relation, properties }) => + relation === "imports" && + properties.kind === "static-import" && + properties.specifier === specifier, + ); + + expect( + findSourceModule(graph, "main.ts")?.observations[0]?.properties, + ).toMatchObject({ module_format: "unknown" }); + expect(different).toMatchObject({ + properties: { + resolution_mode: "compiler-dependent", + resolution_status: "unavailable", + resolved_path: null, + conditional_resolutions: [ + { + mode: "import", + resolution_status: "resolved", + resolved_path: "node_modules/different/import.mjs", + }, + { + mode: "require", + resolution_status: "resolved", + resolved_path: "node_modules/different/require.cjs", + }, + ], + }, + }); + expect(same).toMatchObject({ + properties: { + resolution_mode: "compiler-dependent", + resolved_path: "node_modules/same/shared.js", + resolution_status: "resolved", + }, + evidence: { + limitations: expect.arrayContaining([ + expect.stringContaining( + "compiler-dependent without retained compiler options", + ), + ]), + }, + }); + expect(staticFinding("different")).toMatchObject({ + properties: { + resolution_mode: "compiler-dependent", + resolution_status: "unavailable", + conditional_resolutions: [ + { + mode: "import", + resolved_path: "node_modules/different/import.mjs", + }, + { + mode: "require", + resolved_path: "node_modules/different/require.cjs", + }, + ], + }, + evidence: { + limitations: expect.arrayContaining([ + expect.stringContaining( + "compiler-dependent without retained compiler options", + ), + ]), + }, + }); + expect(staticFinding("same")).toMatchObject({ + properties: { resolved_path: "node_modules/same/shared.js" }, + evidence: { + limitations: expect.arrayContaining([ + expect.stringContaining( + "compiler-dependent without retained compiler options", + ), + ]), + }, + }); + }); +}); + it("does not assign one module origin to an export with colliding path encodings", async () => { const root = await createTestTempDirectory("rea-ambiguous-module-origin-"); await writeFixtureFiles(root, { diff --git a/tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts b/tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts index 17c3f0048..b79407821 100644 --- a/tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts +++ b/tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts @@ -21,6 +21,7 @@ import { type ApplicationVersionComparisonResult, } from "../../../src/domain/javascript/javascriptApplicationVersionComparisonSchemas.js"; import { javascriptRuntimeReconciliationResultSchema } from "../../../src/domain/javascript/javascriptRuntimeReconciliationSchemas.js"; +import { electronPageInspectionSchema } from "../../../src/domain/javascript/electronObservation.js"; import { compareJavaScriptApplicationVersions } from "../../../src/domain/javascript/javascriptApplicationVersionComparison.js"; import { createJavaScriptApplicationGraph } from "../../../src/domain/javascript/javascriptApplicationGraph.js"; import { traceApplicationFeature } from "../../../src/domain/javascript/javascriptFeatureTrace.js"; @@ -444,6 +445,73 @@ describe("JavaScript application workflow error diagnostics", () => { }); describe("JavaScript runtime reconciliation local paths", () => { + it.each([ + { + name: "case-sensitive POSIX input root", + root: null, + path: "/applications/Example.app/Contents/Resources/app/renderer.js", + status: "unknown", + }, + { + name: "case-sensitive POSIX mapping root", + root: "/runtime/App", + path: "/runtime/app/renderer.js", + status: "unknown", + }, + { + name: "matching POSIX mapping root", + root: "/runtime/App", + path: "/runtime/App/renderer.js", + status: "matched", + }, + { + name: "case-insensitive Windows mapping root", + root: String.raw`C:\runtime\App`, + path: String.raw`c:\runtime\app\renderer.js`, + status: "matched", + }, + ])("uses $name on every host", ({ root, path, status }) => { + const base = JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE; + const original = base.runtime_observations[0]!; + const inspection = electronPageInspectionSchema.parse( + original.normalized_result, + ); + const runtime = createEvidence(undefined, original.provider, { + predicateType: original.predicate_type, + operation: original.operation, + parameters: { ...original.parameters, include_script_sources: false }, + result: { + ...inspection, + scripts: { + ...inspection.scripts, + items: inspection.scripts.items.map((script) => ({ + ...script, + file_path: path, + source: { included: false, reason: "not-requested" }, + })), + }, + }, + confidence: original.confidence, + authority: original.authority, + }); + const reconciled = reconcileJavaScriptRuntimeEvidence({ + static_layers: base.static_layers.map((layer) => ({ + ...layer, + runtime_mappings: root === null ? [] : [{ kind: "file-root", root }], + })), + runtime_observations: [runtime], + }); + if (!reconciled.ok) throw reconciled.error; + const result = javascriptRuntimeReconciliationResultSchema.parse( + reconciled.value.normalized_result, + ); + expect( + result.reconciliations.find( + ({ entity_kind }) => entity_kind === "script", + ), + ).toMatchObject({ status }); + }); + it("resolves relative file mapping roots before deriving result Evidence", () => { const absoluteRoot = resolve(process.cwd(), "runtime-cache-fixture"); const relativeRoot = relative(process.cwd(), absoluteRoot); diff --git a/tests/boundary/filesystem/referenceSourceCleanupOwnership.test.ts b/tests/boundary/filesystem/referenceSourceCleanupOwnership.test.ts index 815402ad5..3ad4665bf 100644 --- a/tests/boundary/filesystem/referenceSourceCleanupOwnership.test.ts +++ b/tests/boundary/filesystem/referenceSourceCleanupOwnership.test.ts @@ -3,6 +3,7 @@ import { open as fsOpen, opendir as fsOpendir, writeFile, + type FileHandle, } from "node:fs/promises"; import { join } from "node:path"; @@ -99,8 +100,18 @@ it("preserves admission EIO and retains an invalidated failed-close owner", asyn expect(closeCalls).toBe(1); }); -it("retains partial file bytes and retries the same live owner before new work", async () => { - const root = await createTestTempDirectory("rea-reference-file-owner-"); +const assertSourceCleanupRetry = async (enclosingGit: boolean) => { + const workspace = await createTestTempDirectory("rea-reference-file-owner-"); + const root = join(workspace, "source"); + await mkdir(root); + if (enclosingGit) { + const gitDirectory = join(workspace, ".git"); + await mkdir(gitDirectory); + await writeFile( + join(gitDirectory, "HEAD"), + "0123456789abcdef0123456789abcdef01234567\n", + ); + } const file = join(root, "source.ts"); const bytes = "export const answer = 'retained';\n"; await writeFile(file, bytes); @@ -113,10 +124,13 @@ it("retains partial file bytes and retries the same live owner before new work", }); let closeCalls = 0; let openCalls = 0; + let sourceHandle: FileHandle | undefined; openMock.mockImplementation(async (...args) => { + if (args[0] !== file) return actual.open(...args); openCalls += 1; const handle = await actual.open(...args); + sourceHandle = handle; const close = handle.close.bind(handle); vi.spyOn(handle, "close").mockImplementation(async () => { closeCalls += 1; @@ -157,6 +171,7 @@ it("retains partial file bytes and retries the same live owner before new work", }); expect(openCalls).toBe(1); expect(closeCalls).toBe(1); + expect(sourceHandle?.fd).toBeGreaterThanOrEqual(0); const blocked = await readReferenceSource(root, resources); expect(blocked).toMatchObject({ @@ -168,12 +183,19 @@ it("retains partial file bytes and retries the same live owner before new work", }); expect(openCalls).toBe(1); expect(closeCalls).toBe(2); + expect(sourceHandle?.fd).toBeGreaterThanOrEqual(0); allowClose = true; await resources.close(); expect(openCalls).toBe(1); expect(closeCalls).toBe(3); -}); + expect(sourceHandle?.fd).toBe(-1); +}; + +it.each([false, true])( + "retains partial file bytes and retries the same live owner before new work (enclosing Git repository: %s)", + assertSourceCleanupRetry, +); it("preserves a directory read failure when closing that directory also fails", async () => { const root = await createTestTempDirectory( diff --git a/tests/boundary/filesystem/referenceSourceImport.test.ts b/tests/boundary/filesystem/referenceSourceImport.test.ts index 75eab7acb..8443dfbdd 100644 --- a/tests/boundary/filesystem/referenceSourceImport.test.ts +++ b/tests/boundary/filesystem/referenceSourceImport.test.ts @@ -378,6 +378,44 @@ describe("reference source path selection", () => { }); describe("reference source rooted module specifiers", () => { + it("keeps dot-prefixed bare specifiers external while resolving explicit relative paths", async () => { + const root = await createTestTempDirectory("rea-reference-dot-prefix-"); + await Promise.all([ + writeFile( + join(root, "main.js"), + 'import ".hidden.js"; import "..pkg.js"; import "./.hidden.js"; require(".hidden.js");\n', + ), + writeFile(join(root, ".hidden.js"), "export {};\n"), + writeFile(join(root, "..pkg.js"), "export {};\n"), + ]); + const result = await importTree(root); + if (!result.ok) throw result.error; + expect(result.value.relationships).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + to: ".hidden.js", + kind: "imports", + resolution: "external", + }), + expect.objectContaining({ + to: "..pkg.js", + kind: "imports", + resolution: "external", + }), + expect.objectContaining({ + to: ".hidden.js", + kind: "imports", + resolution: "internal", + }), + expect.objectContaining({ + to: ".hidden.js", + kind: "requires", + resolution: "external", + }), + ]), + ); + }); + it("does not rebase an absolute import onto a coincidentally matching source member", async () => { const root = await createTestTempDirectory("rea-reference-rooted-"); await mkdir(join(root, "src", "outside"), { recursive: true }); diff --git a/tests/boundary/filesystem/referenceSourceTypeScriptExtensions.test.ts b/tests/boundary/filesystem/referenceSourceTypeScriptExtensions.test.ts index d537a1dca..7b3d8189c 100644 --- a/tests/boundary/filesystem/referenceSourceTypeScriptExtensions.test.ts +++ b/tests/boundary/filesystem/referenceSourceTypeScriptExtensions.test.ts @@ -6,6 +6,31 @@ import { expect, it } from "vitest"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { importReferenceSource } from "../../support/referenceSourceResourceScope.js"; +it("imports valid CommonJS wrapper syntax without inventing a parse failure", async () => { + const root = await createTestTempDirectory("rea-reference-commonjs-mode-"); + await Promise.all([ + writeFile( + join(root, "main.cjs"), + 'void new.target; require("./dep.cjs"); return;\n', + ), + writeFile(join(root, "dep.cjs"), "module.exports = 1;\n"), + ]); + const imported = await importReferenceSource({ + root, + caller: "native-commonjs-source", + policy: { secretPatterns: [] }, + }); + if (!imported.ok) throw imported.error; + expect(imported.value.parse_failures).toEqual([]); + expect(imported.value.relationships).toContainEqual({ + from_path: "main.cjs", + to: "dep.cjs", + kind: "requires", + resolution: "internal", + parse_state: "parsed", + }); +}); + it.each([ ["main.ts", "dep.js", "dep.ts"], ["main.mts", "dep.mjs", "dep.mts"], diff --git a/tests/boundary/filesystem/releaseCheckpoint.test.ts b/tests/boundary/filesystem/releaseCheckpoint.test.ts index e3d425810..d511a6a58 100644 --- a/tests/boundary/filesystem/releaseCheckpoint.test.ts +++ b/tests/boundary/filesystem/releaseCheckpoint.test.ts @@ -649,9 +649,8 @@ it.skipIf(process.platform === "win32").each([ const sourceSha = await candidate(f, valid ? "6.0.0" : "5.1.0"); const workflow = z .object({ - jobs: z.record( - z.string(), - z.object({ + jobs: z.object({ + [job]: z.object({ steps: z.array( z.object({ name: z.string().optional(), @@ -659,7 +658,7 @@ it.skipIf(process.platform === "win32").each([ }), ), }), - ), + }), }) .parse( parse( diff --git a/tests/boundary/filesystem/releaseWorkflow.test.ts b/tests/boundary/filesystem/releaseWorkflow.test.ts index 0bfebd1d2..4d3859433 100644 --- a/tests/boundary/filesystem/releaseWorkflow.test.ts +++ b/tests/boundary/filesystem/releaseWorkflow.test.ts @@ -34,6 +34,12 @@ async function readReleaseWorkflow() { "release-proposal": jobSchema, "release-please": jobSchema, "merged-release": jobSchema, + qualification: z.object({ + if: z.string(), + needs: z.array(z.string()), + uses: z.string(), + with: z.record(z.string(), z.string()), + }), publish: jobSchema, "publish-mcp": jobSchema, }), @@ -271,10 +277,19 @@ it("binds npm and MCP publication to the same immutable release SHA", async () = release_created: "${{ steps.release.outputs.release_created }}", sha: "${{ steps.release.outputs.sha }}", }); - expect(workflow.jobs.publish.if).toContain("inputs.phase == 'publish'"); - expect(workflow.jobs.publish.if).toContain( + expect(workflow.jobs.qualification.if).toContain("inputs.phase == 'publish'"); + expect(workflow.jobs.qualification.if).toContain( "needs.release-please.outputs.release_created", ); + expect(workflow.jobs.qualification.uses).toBe("./.github/workflows/ci.yml"); + expect(workflow.jobs.qualification.with).toEqual({ + source_sha: + "${{ needs.merged-release.outputs.sha || needs.release-please.outputs.sha }}", + }); + expect(workflow.jobs.publish.needs).toContain("qualification"); + expect(workflow.jobs.publish.if).toContain( + "needs.qualification.result == 'success'", + ); expect(workflow.jobs["publish-mcp"].if).toContain( "needs.publish.result == 'success'", ); @@ -309,7 +324,7 @@ it("binds npm and MCP publication to the same immutable release SHA", async () = )?.run; expect(publishCommand).toContain("scripts/release-npm-tag.mjs"); expect(publishCommand).toContain( - 'npm publish --access public --tag "${tag}"', + 'npm publish "${VERIFIED_PACKAGE_TARBALL}" --access public --tag "${tag}"', ); for (const [version, tag] of [ ["6.1.0", "latest"], @@ -644,7 +659,7 @@ it("routes website verification through the central PR policy", async () => { // Publishing is irreversible. Keep the release authority invariant as a static // boundary check; it is not proof that package installation or publishing works. -it("requires package verification before publishing and retains the registry canary", async () => { +it("requires qualified package validation before publishing and retains the registry canary", async () => { const workflow = z .object({ jobs: z.object({ @@ -663,7 +678,7 @@ it("requires package verification before publishing and retains the registry can ); const commands = workflow.jobs.publish.steps.map(({ run }) => run ?? ""); const verify = commands.findIndex((command) => - command.includes("npm run verify:package"), + command.includes("scripts/ci/verified-package.mjs validate"), ); const publish = commands.findIndex((command) => command.includes("npm publish"), diff --git a/tests/boundary/filesystem/safeOutputTree.test.ts b/tests/boundary/filesystem/safeOutputTree.test.ts index f67704456..3e82a62ab 100644 --- a/tests/boundary/filesystem/safeOutputTree.test.ts +++ b/tests/boundary/filesystem/safeOutputTree.test.ts @@ -489,4 +489,28 @@ describe("safe artifact output Windows stream paths", () => { await expect(access(output)).rejects.toMatchObject({ code: "ENOENT" }); expect(await readdir(parent)).toEqual([]); }); + + it.each(["Folder/Icon\r", "Fold\ter/file.txt"])( + "refuses Windows control characters before creating %j", + async (path) => { + const parent = await createTestTempDirectory("rea-safe-output-control-"); + const output = join(parent, "published"); + const tree = await SafeOutputTree.create(output, "win32"); + const bytes = Buffer.from("regular file content"); + await expect( + tree.write(path, Readable.from(bytes), { + sha256: createHash("sha256").update(bytes).digest("hex"), + bytes: bytes.byteLength, + }), + ).rejects.toMatchObject({ + reason: "path", + message: `Windows destination cannot materialize artifact path: ${JSON.stringify(path)}; Windows names cannot contain U+0001-U+001F.`, + }); + expect(await readdir(output)).toEqual([]); + expect(await tree.rollback()).toEqual({ + status: "complete", + residualPaths: [], + }); + }, + ); }); diff --git a/tests/boundary/filesystem/safeOutputTreeCloseFailures.test.ts b/tests/boundary/filesystem/safeOutputTreeCloseFailures.test.ts index ee285dbd5..d835b1e46 100644 --- a/tests/boundary/filesystem/safeOutputTreeCloseFailures.test.ts +++ b/tests/boundary/filesystem/safeOutputTreeCloseFailures.test.ts @@ -10,6 +10,8 @@ const injectedFilesystemFailures = vi.hoisted(() => ({ closeNext: false, blockCloseRetries: false, chmodNext: false, + syncAbortAfter: undefined as AbortController | undefined, + syncCount: 0, rootIdentityPath: undefined as string | undefined, })); @@ -44,6 +46,15 @@ vi.mock("node:fs/promises", async (importOriginal) => { await close(); }; } + if (injectedFilesystemFailures.syncAbortAfter !== undefined) { + const sync = handle.sync.bind(handle); + handle.sync = async () => { + await sync(); + injectedFilesystemFailures.syncCount += 1; + if (injectedFilesystemFailures.syncCount === 2) + injectedFilesystemFailures.syncAbortAfter?.abort(); + }; + } return handle; }, }; @@ -82,6 +93,34 @@ describe("safe artifact output close failures", () => { }, ); + it.skipIf(process.platform === "win32")( + "keeps the tree unpublished when cancellation arrives during commit durability", + async () => { + const parent = await createTestTempDirectory("rea-safe-output-cancel-"); + const output = join(parent, "unpublished"); + const tree = await SafeOutputTree.create(output); + const bytes = Buffer.from("pending output"); + await tree.write("file.txt", Readable.from(bytes), { + sha256: createHash("sha256").update(bytes).digest("hex"), + bytes: bytes.byteLength, + }); + const controller = new AbortController(); + injectedFilesystemFailures.syncCount = 0; + injectedFilesystemFailures.syncAbortAfter = controller; + try { + await expect(tree.commit(controller.signal)).rejects.toMatchObject({ + reason: "cancelled", + }); + expect(tree.published).toBe(false); + } finally { + injectedFilesystemFailures.syncAbortAfter = undefined; + injectedFilesystemFailures.syncCount = 0; + } + expect(await tree.rollback()).toMatchObject({ status: "complete" }); + await expect(access(output)).rejects.toMatchObject({ code: "ENOENT" }); + }, + ); + it.skipIf(process.platform === "win32")( "preserves setup failure when closing the staging handle also fails", async () => { diff --git a/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts b/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts index 3bf33c312..ab2b5e5a7 100644 --- a/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts +++ b/tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts @@ -11,6 +11,7 @@ import { } from "../../../src/application/SetupHost.js"; import { RegularFileCleanupFailure } from "../../../src/application/RegularFileRead.js"; import { configureDetectedClients } from "../../../src/application/SetupClients.js"; +import { systemUninstallHost } from "../../../src/application/Uninstall.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; vi.mock("node:fs/promises", async (importOriginal) => { @@ -31,6 +32,61 @@ beforeEach(async () => { afterEach(() => openMock.mockReset()); +const holdReadHandle = (path: string, reason: string) => { + const closeAttempts: object[] = []; + let released = false; + openMock.mockImplementation(async (...args) => { + const handle = await actualFs.open(...args); + if (String(args[0]) !== path) return handle; + const nativeClose = handle.close.bind(handle); + vi.spyOn(handle, "close").mockImplementation(async () => { + closeAttempts.push(handle); + if (!released) throw new Error(reason); + await nativeClose(); + }); + return handle; + }); + return { + closeAttempts, + release: () => { + released = true; + }, + }; +}; + +it("retains invalid UTF-8 diagnostics and the uninstall read owner when close fails", async () => { + const home = await createTestTempDirectory("rea-uninstall-utf8-close-"); + const path = join(home, "client.json"); + const original = Buffer.from([0xff]); + await writeFile(path, original); + const { closeAttempts, release } = holdReadHandle( + path, + "held uninstall handle", + ); + const host = systemUninstallHost(home, undefined, { HOME: home }, "linux"); + try { + expect( + await host.removeClient({ + name: "cursor", + format: "json", + configPath: path, + }), + ).toMatchObject({ + status: "failed", + detail: expect.stringContaining("not valid UTF-8"), + }); + expect(await readFile(path)).toEqual(original); + expect(closeAttempts).toHaveLength(2); + release(); + expect(await host.close?.()).toBeUndefined(); + expect(closeAttempts).toHaveLength(3); + expect(closeAttempts[2]).toBe(closeAttempts[0]); + } finally { + release(); + await host.close?.(); + } +}); + describe("ZCode fallback cleanup ownership", () => { it.each(["preflight", "configure"])( "retains a failed ZCode fallback close during %s until host cleanup", @@ -49,19 +105,10 @@ describe("ZCode fallback cleanup ownership", () => { await mkdir(dirname(fallback), { recursive: true }); const original = '{"mcpServers":{"other":{"command":"other"}}}\n'; await writeFile(fallback, original); - const closeAttempts: object[] = []; - let allowClose = false; - openMock.mockImplementation(async (...args) => { - const handle = await actualFs.open(...args); - if (String(args[0]) !== fallback) return handle; - const nativeClose = handle.close.bind(handle); - vi.spyOn(handle, "close").mockImplementation(async () => { - closeAttempts.push(handle); - if (!allowClose) throw new Error("held fallback handle"); - await nativeClose(); - }); - return handle; - }); + const { closeAttempts, release } = holdReadHandle( + fallback, + "held fallback handle", + ); try { const action = operation === "preflight" @@ -79,12 +126,12 @@ describe("ZCode fallback cleanup ownership", () => { await expect(readFile(client.configPath)).rejects.toMatchObject({ code: "ENOENT", }); - allowClose = true; + release(); expect(await host.close?.()).toBeUndefined(); expect(closeAttempts).toHaveLength(3); expect(closeAttempts[2]).toBe(closeAttempts[0]); } finally { - allowClose = true; + release(); await host.close?.(); } }, @@ -92,83 +139,87 @@ describe("ZCode fallback cleanup ownership", () => { }); describe("setup client configuration cleanup ownership", () => { - it("stops client configuration and retries the same alignment handle from host close", async () => { - const home = await createTestTempDirectory("rea-setup-config-close-"); - const environment = { - HOME: home, - XDG_CONFIG_HOME: join(home, "xdg"), - }; - const host = systemSetupHost( - { platform: "linux", homeDirectory: home } as DoctorHost, - environment, - ); - const client = (await host.supportedClients()).find( - ({ name }) => name === "vscode", - ); - if (client === undefined) throw new Error("VS Code setup client missing"); - await mkdir(dirname(client.configPath), { recursive: true }); - const original = Buffer.from('{"servers": {"other": {}}}\n'); - await writeFile(client.configPath, original); + it.each([ + ["valid UTF-8", Buffer.from('{"servers": {"other": {}}}\n')], + ["malformed UTF-8", Buffer.from([0xff])], + ] as const)( + "stops configuration and retains the %s read owner until host close", + async (encoding, original) => { + const home = await createTestTempDirectory("rea-setup-config-close-"); + const environment = { + HOME: home, + XDG_CONFIG_HOME: join(home, "xdg"), + }; + const host = systemSetupHost( + { platform: "linux", homeDirectory: home } as DoctorHost, + environment, + ); + const client = (await host.supportedClients()).find( + ({ name }) => name === "vscode", + ); + if (client === undefined) throw new Error("VS Code setup client missing"); + await mkdir(dirname(client.configPath), { recursive: true }); + await writeFile(client.configPath, original); - const closeAttempts: object[] = []; - let allowClose = false; - openMock.mockImplementation(async (...args) => { - const handle = await actualFs.open(...args); - if (String(args[0]) !== client.configPath) return handle; - const nativeClose = handle.close.bind(handle); - vi.spyOn(handle, "close").mockImplementation(async () => { - closeAttempts.push(handle); - if (!allowClose) throw new Error("test holds the config handle open"); - await nativeClose(); - }); - return handle; - }); - const configure = vi.spyOn(host, "configureClient"); + const { closeAttempts, release } = holdReadHandle( + client.configPath, + "test holds the config handle open", + ); + const configure = vi.spyOn(host, "configureClient"); - try { - const failure = await filterClientsNeedingConfigure(host, [client], {}, [ - "rea", - "mcp", - ]) - .then((detectedClients) => - configureDetectedClients({ - host, - detectedClients, - providerEnvironment: {}, - command: ["rea", "mcp"], - clients: {}, - appliedActions: [], - }), + try { + const failure = await filterClientsNeedingConfigure( + host, + [client], + {}, + ["rea", "mcp"], ) - .then( - () => undefined, - (cause: unknown) => cause, - ); - expect(failure).toBeInstanceOf(ConfigurationError); - expect(failure).toMatchObject({ - _tag: "ConfigurationError", - cause: expect.any(RegularFileCleanupFailure), - cleanup: { - resources: [client.configPath], - reason: expect.stringContaining("test holds the config handle open"), - }, - }); - expect(configure).not.toHaveBeenCalled(); - expect(closeAttempts).toHaveLength(2); - expect(closeAttempts[0]).toBe(closeAttempts[1]); - expect(await readFile(client.configPath)).toEqual(original); + .then((detectedClients) => + configureDetectedClients({ + host, + detectedClients, + providerEnvironment: {}, + command: ["rea", "mcp"], + clients: {}, + appliedActions: [], + }), + ) + .then( + () => undefined, + (cause: unknown) => cause, + ); + expect(failure).toBeInstanceOf(ConfigurationError); + if (encoding === "malformed UTF-8") + expect(failure).toMatchObject({ + cause: { + outcome: { kind: "failed", cause: expect.any(TypeError) }, + }, + }); + expect(failure).toMatchObject({ + _tag: "ConfigurationError", + cause: expect.any(RegularFileCleanupFailure), + cleanup: { + resources: [client.configPath], + reason: expect.stringContaining( + "test holds the config handle open", + ), + }, + }); + expect(configure).not.toHaveBeenCalled(); + expect(closeAttempts).toHaveLength(2); + expect(closeAttempts[0]).toBe(closeAttempts[1]); + expect(await readFile(client.configPath)).toEqual(original); - allowClose = true; - const close = host.close; - if (close === undefined) throw new Error("Setup host close is missing"); - expect(await close()).toBeUndefined(); - expect(closeAttempts).toHaveLength(3); - expect(closeAttempts[2]).toBe(closeAttempts[0]); - } finally { - allowClose = true; - await host.close?.(); - } - }); + release(); + expect(await host.close?.()).toBeUndefined(); + expect(closeAttempts).toHaveLength(3); + expect(closeAttempts[2]).toBe(closeAttempts[0]); + } finally { + release(); + await host.close?.(); + } + }, + ); it("waits for an admitted configuration read and rejects later admissions", async () => { const home = await createTestTempDirectory("rea-setup-config-inflight-"); diff --git a/tests/boundary/filesystem/sourceToBundlePaths.test.ts b/tests/boundary/filesystem/sourceToBundlePaths.test.ts index 19aa07a1a..8bc9caa27 100644 --- a/tests/boundary/filesystem/sourceToBundlePaths.test.ts +++ b/tests/boundary/filesystem/sourceToBundlePaths.test.ts @@ -6,7 +6,7 @@ import { analyzeJavaScriptApplication } from "../../support/javascriptApplicatio import { parseApplicationGraphEvidence } from "../../../src/application/javascript/JavaScriptApplicationEvidenceGraph.js"; import { findApplicationFeatureSeeds } from "../../../src/domain/javascript/javascriptFeatureSeed.js"; import { compareSourceToBundle } from "../../../src/domain/javascript/sourceToBundleComparison.js"; -import { resolveSourceMapSource } from "../../../src/javascript/sourceMaps/DecodedSourceMap.js"; +import { resolveJavaScriptSourceMapUrl } from "../../../src/domain/javascript/javascriptSourceMapPaths.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { importReferenceSource } from "../../support/referenceSourceResourceScope.js"; @@ -180,7 +180,7 @@ it.each([ decoy: decoyPath = "src/a.js", }) => { if (sourceRoot !== undefined) { - const resolved = resolveSourceMapSource( + const resolved = resolveJavaScriptSourceMapUrl( source, sourceRoot, `https://example.test/${mapPath}`, diff --git a/tests/boundary/filesystem/stableArtifact.test.ts b/tests/boundary/filesystem/stableArtifact.test.ts index 454d9064b..3bd587ad0 100644 --- a/tests/boundary/filesystem/stableArtifact.test.ts +++ b/tests/boundary/filesystem/stableArtifact.test.ts @@ -31,9 +31,12 @@ it("reads exact binary and empty bytes and rejects symlink/size/cancellation bou }); const controller = new AbortController(); controller.abort(); - await expect(readStableArtifact(real, 3, controller.signal)).rejects.toBe( - controller.signal.reason, - ); + await expect( + readStableArtifact(real, 3, controller.signal), + ).rejects.toMatchObject({ + reason: "cancelled", + cause: controller.signal.reason, + }); }); const checkChange = async ( diff --git a/tests/boundary/filesystem/staticCheckReports.test.ts b/tests/boundary/filesystem/staticCheckReports.test.ts index c2708e1db..7d022da72 100644 --- a/tests/boundary/filesystem/staticCheckReports.test.ts +++ b/tests/boundary/filesystem/staticCheckReports.test.ts @@ -1,6 +1,6 @@ import { spawnSync } from "node:child_process"; import { access, mkdir, readFile, writeFile } from "node:fs/promises"; -import { join, sep } from "node:path"; +import { dirname, join, sep } from "node:path"; import { fileURLToPath } from "node:url"; import { expect, it } from "vitest"; import { z } from "zod"; @@ -138,6 +138,36 @@ it("keeps lint errors failing and visible alongside the retained warnings", asyn ); }); +it("excludes translation staging while retaining authored website errors", async () => { + const root = await fixture(); + for (const name of [".gitignore", ".oxlintrc.json"]) + await writeFile(join(root, name), await readFile(join(repository, name))); + const authored = "website/public/assets/authored.js"; + const staged = + "website/.i18n-regression/site/examples/notes-electron/main.js"; + for (const name of [authored, staged]) { + const path = join(root, name); + await mkdir(dirname(path), { recursive: true }); + await writeFile( + path, + 'const source = require("node:fs");\nconsole.log(source);\n', + ); + } + + const result = invoke(root, "lint"); + expect(result.error).toBeUndefined(); + expect(result.status).toBe(1); + expect(result.stdout).toContain("1 errors, 0 warnings"); + expect(result.stderr).toContain(authored); + expect(await lintDiagnostics(root)).toEqual([ + expect.objectContaining({ + severity: "error", + code: "typescript(no-var-requires)", + filename: authored, + }), + ]); +}); + it("keeps malformed source failing with its parser diagnostic", async () => { const root = await fixture(); await writeFile(join(root, "src/malformed.js"), "const value = ;\n"); diff --git a/tests/boundary/filesystem/testTaskCache.test.ts b/tests/boundary/filesystem/testTaskCache.test.ts index 7e06ce1a1..5d877e829 100644 --- a/tests/boundary/filesystem/testTaskCache.test.ts +++ b/tests/boundary/filesystem/testTaskCache.test.ts @@ -1,6 +1,6 @@ import { execFile } from "node:child_process"; -import { readFile, writeFile } from "node:fs/promises"; -import { join } from "node:path"; +import { cp, readFile, writeFile } from "node:fs/promises"; +import { basename, join } from "node:path"; import { promisify } from "node:util"; import { expect, it } from "vitest"; @@ -78,7 +78,7 @@ it.skipIf(process.platform === "android")( await workflowGit(root, ["init", "--initial-branch=main"]); await workflowGit(root, ["add", "."]); await workflowGit(root, ["commit", "-m", "test: seed cache fixture"]); - const run = () => + const run = (cwd = root) => execute( process.execPath, [ @@ -87,7 +87,7 @@ it.skipIf(process.platform === "android")( "test:run", "--output-logs=errors-only", ], - { cwd: root, env: { ...process.env, TURBO_DAEMON: "false" } }, + { cwd, env: { ...process.env, TURBO_DAEMON: "false" } }, ); await run(); await writeFile(join(root, "README_zh.md"), "wrong command"); @@ -104,5 +104,32 @@ it.skipIf(process.platform === "android")( "prepared\n", ); } + // Provider jobs receive the producer's cache in a fresh checkout, not its + // outputs. Turbo must restore identical inputs and rebuild changed ones. + const consumer = await createTestTempDirectory("rea-cache-consumer-"); + await cp(root, consumer, { + recursive: true, + filter: (path) => + basename(path) !== ".turbo" && + !/^prepared-\d+\.txt$/u.test(basename(path)), + }); + await cp(join(root, ".turbo/cache"), join(consumer, ".turbo/cache"), { + recursive: true, + }); + const restored = await run(consumer); + expect(restored.stdout).toContain(`${dependencies.length} cached`); + for (const index of dependencies.keys()) + expect( + await readFile(join(consumer, `prepared-${index}.txt`), "utf8"), + ).toBe("prepared\n"); + await writeFile( + join(consumer, "artifact-input.txt"), + "changed producer input", + ); + await run(consumer); + for (const index of dependencies.keys()) + expect( + await readFile(join(consumer, `prepared-${index}.txt`), "utf8"), + ).toBe("prepared\nprepared\n"); }, ); diff --git a/tests/boundary/filesystem/thirdPartyInventory.test.ts b/tests/boundary/filesystem/thirdPartyInventory.test.ts new file mode 100644 index 000000000..7e61f883b --- /dev/null +++ b/tests/boundary/filesystem/thirdPartyInventory.test.ts @@ -0,0 +1,117 @@ +import { createHash } from "node:crypto"; +import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +import { expect } from "vitest"; + +import { processTest as test } from "../../support/process/processFixture.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +test("generates locked inventory and rejects stale notice metadata or preserved texts", async ({ + processes, +}) => { + const root = await createTestTempDirectory("rea-notice-records-"); + await mkdir(resolve(root, "scripts/lib"), { recursive: true }); + await mkdir(resolve(root, "licenses")); + for (const file of [ + "scripts/generate-third-party-inventory.mjs", + "scripts/lib/generated-file.mjs", + ]) + await copyFile(resolve(file), resolve(root, file)); + const script = resolve(root, "scripts/generate-third-party-inventory.mjs"); + const runtime = { + version: "1.0.0", + license: "MIT", + resolved: + "https://registry.npmjs.org/fixture-runtime/-/fixture-runtime-1.0.0.tgz", + integrity: "sha512-fixture-integrity", + optional: true, + }; + await writeFile( + resolve(root, "package-lock.json"), + JSON.stringify({ + packages: { + "": { name: "fixture", version: "1.0.0" }, + "node_modules/fixture-runtime": runtime, + "node_modules/fixture-dev": { ...runtime, dev: true, optional: false }, + }, + }), + ); + const generated = await processes.run(process.execPath, [script]); + expect(generated.exitCode, generated.stderr).toBe(0); + const inventory = await readFile( + resolve(root, "licenses/npm-dependencies.txt"), + "utf8", + ); + expect(inventory).toContain("Locked package entries: 2; runtime: 1."); + expect(inventory).toContain( + "fixture-runtime@1.0.0 | runtime, optional | MIT", + ); + expect(inventory).toContain("fixture-dev@1.0.0 | development | MIT"); + const fingerprint = ( + JSON.parse(generated.stdout) as { runtime_dependency_fingerprint: string } + ).runtime_dependency_fingerprint; + const notice = [ + `Runtime dependency fingerprint (SHA-256): ${fingerprint}`, + "", + "===== fixture-runtime@1.0.0 =====", + "Declared license: MIT", + `Archive: ${runtime.resolved}`, + `Integrity: ${runtime.integrity}`, + "", + "Fixture text; this test does not establish real package attribution.", + "", + ].join("\n"); + const noticePath = resolve(root, "licenses/npm-runtime-notices.txt"); + const referencePath = resolve(root, "licenses/reference.txt"); + await writeFile(noticePath, notice); + await writeFile(referencePath, "preserved fixture text\n"); + await writeFile( + resolve(root, "licenses/upstream-sources.json"), + JSON.stringify([ + { + file: "licenses/reference.txt", + sha256: createHash("sha256") + .update("preserved fixture text\n") + .digest("hex"), + }, + ]), + ); + const check = () => processes.run(process.execPath, [script, "--check"]); + const valid = await check(); + expect(valid.exitCode, valid.stderr).toBe(0); + for (const [changed, diagnostic] of [ + [ + notice.replace( + "===== fixture-runtime@1.0.0 =====", + "===== another-package@1.0.0 =====", + ), + "Missing runtime notice", + ], + [ + notice.replace(runtime.integrity, "sha512-different"), + "Runtime notice metadata differs", + ], + [ + notice.replace(fingerprint, "0".repeat(64)), + "Runtime notice fingerprint differs", + ], + [ + notice + notice.slice(notice.indexOf("===== ")), + "Duplicate runtime notice", + ], + ] as const) { + await writeFile(noticePath, changed); + const rejected = await check(); + expect(rejected.exitCode).toBe(1); + expect(rejected.stderr).toContain(diagnostic); + } + await writeFile(noticePath, notice); + await writeFile(referencePath, "changed fixture text\n"); + const tampered = await check(); + expect(tampered.exitCode).toBe(1); + expect(tampered.stderr).toContain("Preserved notice digest differs"); + expect( + await readFile(resolve(root, "licenses/npm-dependencies.txt"), "utf8"), + ).toBe(inventory); +}); diff --git a/tests/boundary/filesystem/webArtifactReadOwnership.test.ts b/tests/boundary/filesystem/webArtifactReadOwnership.test.ts new file mode 100644 index 000000000..0a8791366 --- /dev/null +++ b/tests/boundary/filesystem/webArtifactReadOwnership.test.ts @@ -0,0 +1,96 @@ +import { mkdir, rm, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { expect, it, onTestFinished, vi } from "vitest"; + +const injected = vi.hoisted(() => ({ + sourcePath: undefined as string | undefined, + abortController: undefined as AbortController | undefined, + failClose: false, + closeAttempts: 0, +})); + +vi.mock("node:fs/promises", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + open: async (...args: Parameters) => { + const handle = await actual.open(...args); + if (args[0] !== injected.sourcePath) return handle; + const createReadStream = handle.createReadStream.bind(handle); + handle.createReadStream = (options) => { + injected.abortController?.abort(); + return createReadStream(options); + }; + const close = handle.close.bind(handle); + handle.close = async () => { + injected.closeAttempts += 1; + if (injected.failClose) throw new Error("fixture close refusal"); + await close(); + }; + return handle; + }, + }; +}); + +import { WebModuleTraceService } from "../../../src/application/WebModuleTraceService.js"; +import { LocalWebModuleArtifacts } from "../../../src/browser/modules/WebModuleArtifacts.js"; +import { webModuleArtifactsFixture } from "../../fixtures/webModuleTrace.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +it("retains cancelled source read ownership until service close retries it", async () => { + const root = await createTestTempDirectory("rea-web-artifact-read-owner-"); + onTestFinished(async () => { + injected.sourcePath = undefined; + injected.abortController = undefined; + injected.failClose = false; + injected.closeAttempts = 0; + await rm(root, { recursive: true, force: true }); + }); + const source = 'import "./dep.js";'; + const fixture = webModuleArtifactsFixture(source); + const manifestPath = join(root, "manifest.json"); + const sourcePath = join(root, "files", "modules", "main.js"); + await mkdir(join(root, "files", "modules"), { recursive: true }); + await writeFile(sourcePath, source); + await writeFile(manifestPath, JSON.stringify(fixture.manifest)); + + injected.sourcePath = sourcePath; + injected.failClose = true; + const controller = new AbortController(); + injected.abortController = controller; + const resolver = { + resolve: vi.fn(), + close: vi.fn(async () => undefined), + }; + const service = new WebModuleTraceService( + new LocalWebModuleArtifacts(), + resolver, + ); + const input = { manifest_path: manifestPath, script_index: 0 }; + + const cancelled = await service.trace(input, { signal: controller.signal }); + expect(cancelled.ok).toBe(false); + if (cancelled.ok) throw new Error("Expected cancelled source read"); + expect(cancelled.error.cleanupIncomplete).toBe(true); + expect(cancelled.error.cleanupResources).toContain(sourcePath); + expect(resolver.resolve).not.toHaveBeenCalled(); + + injected.abortController = undefined; + const blocked = await service.trace(input); + expect(blocked.ok).toBe(false); + if (blocked.ok) throw new Error("Expected retained cleanup to block load"); + expect(blocked.error.cleanupIncomplete).toBe(true); + expect(injected.closeAttempts).toBe(2); + + await expect(service.close()).rejects.toThrow( + "Web module trace cleanup failed", + ); + expect(resolver.close).toHaveBeenCalledTimes(1); + expect(injected.closeAttempts).toBe(3); + + injected.failClose = false; + const attemptsBeforeRetry = injected.closeAttempts; + await service.close(); + expect(injected.closeAttempts).toBeGreaterThan(attemptsBeforeRetry); + expect(resolver.close).toHaveBeenCalledTimes(2); +}); diff --git a/tests/boundary/javascript-recovery/wakaruPublicationCancellation.test.ts b/tests/boundary/javascript-recovery/wakaruPublicationCancellation.test.ts new file mode 100644 index 000000000..250e75623 --- /dev/null +++ b/tests/boundary/javascript-recovery/wakaruPublicationCancellation.test.ts @@ -0,0 +1,128 @@ +import { createHash } from "node:crypto"; +import { access, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { Readable } from "node:stream"; +import { expect, it, vi } from "vitest"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +const publicationCancellation = vi.hoisted(() => ({ + controller: undefined as AbortController | undefined, + directorySyncs: 0, +})); + +vi.mock("node:fs/promises", async (importOriginal) => { + const filesystem = await importOriginal(); + return { + ...filesystem, + open: async (...args: Parameters) => { + const handle = await filesystem.open(...args); + if (publicationCancellation.controller !== undefined) { + const stats = await handle.stat(); + if (stats.isDirectory()) { + const sync = handle.sync.bind(handle); + handle.sync = async () => { + await sync(); + publicationCancellation.directorySyncs += 1; + if (publicationCancellation.directorySyncs === 2) + publicationCancellation.controller?.abort(); + }; + } + } + return handle; + }, + }; +}); + +vi.mock( + "../../../src/javascript/recovery/WakaruCommand.js", + async (importOriginal) => { + const actual = + await importOriginal< + typeof import("../../../src/javascript/recovery/WakaruCommand.js") + >(); + return { + ...actual, + resolveWakaruCommand: async () => ({ + command: "/unused/wakaru", + limiter: "/unused/prlimit", + sha256: "a".repeat(64), + bytes: 1, + }), + }; + }, +); + +vi.mock( + "../../../src/javascript/recovery/WakaruExecution.js", + async (importOriginal) => { + const actual = + await importOriginal< + typeof import("../../../src/javascript/recovery/WakaruExecution.js") + >(); + const { createAnalysisExecution } = + await import("../../../src/application/AnalysisProvider.js"); + return { + ...actual, + prepareWakaruExecution: async ( + context: Parameters[0], + ) => { + const source = context.sources[0]; + if (source === undefined) throw new Error("Missing recovery source"); + const bytes = Buffer.from("module.exports = 42;"); + await context.tree.write("module.js", Readable.from([bytes]), { + sha256: createHash("sha256").update(bytes).digest("hex"), + bytes: bytes.byteLength, + }); + return createAnalysisExecution( + { status: "complete" }, + { id: "wakaru", name: "Wakaru", version: "1.14.0" }, + { + subject: { + path: source.path, + sha256: source.sha256, + format: "javascript", + }, + }, + ); + }, + }; + }, +); + +import { AnalysisCancelledError } from "../../../src/domain/analysisErrorCore.js"; +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import { WakaruProvider } from "../../../src/javascript/recovery/WakaruProvider.js"; + +it.skipIf(process.platform === "win32")( + "keeps mid-commit output-tree cancellation typed through the provider", + async () => { + const root = await createTestTempDirectory("rea-wakaru-cancel-"); + const sourcePath = join(root, "source.js"); + const output = join(root, "output"); + await writeFile(sourcePath, "module.exports = 42;"); + const controller = new AbortController(); + publicationCancellation.controller = controller; + publicationCancellation.directorySyncs = 0; + const provider = new WakaruProvider({}); + try { + const result = await provider.recover( + { + path: sourcePath, + output_directory: output, + extraction_mode: "structural", + rewrite_level: "standard", + }, + { signal: controller.signal }, + ); + if (result.ok) throw new Error("Expected publication cancellation"); + expect(result.error).toBeInstanceOf(AnalysisCancelledError); + expect(projectAnalysisError(result.error).code).toBe("cancelled"); + expect(publicationCancellation.directorySyncs).toBe(2); + await expect(access(output)).rejects.toMatchObject({ code: "ENOENT" }); + } finally { + publicationCancellation.controller = undefined; + publicationCancellation.directorySyncs = 0; + await provider.close(); + } + }, +); diff --git a/tests/boundary/javascript/sourceMapRuntimeAvailability.test.ts b/tests/boundary/javascript/sourceMapRuntimeAvailability.test.ts new file mode 100644 index 000000000..753a3bd47 --- /dev/null +++ b/tests/boundary/javascript/sourceMapRuntimeAvailability.test.ts @@ -0,0 +1,35 @@ +import { expect, it } from "vitest"; +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import { runSourceMapCommand } from "../../../src/javascript/sourceMaps/SourceMapCommand.js"; +import { PrivateRuntimeRootUnavailableError } from "../../../src/process/PrivateRuntimeRootUnavailableError.js"; + +it.each([false, true])( + "preserves private-runtime retryable=%s through the source-map operation", + async (retryable) => { + const reason = "Native runtime self-test failed with a sharing violation"; + let launches = 0; + const result = await runSourceMapCommand("{}", "/selected.map", undefined, { + prepareOwnership: async () => {}, + createRuntime: async () => { + throw new PrivateRuntimeRootUnavailableError(reason, { retryable }); + }, + launcher: async () => { + launches += 1; + throw new Error("A refused runtime must not launch a codec"); + }, + }); + expect(launches).toBe(0); + if (result.ok) throw new Error("Unavailable runtime must refuse decoding"); + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "capability_unavailable", + category: retryable ? "unavailable" : "unsupported_provider", + retryable, + details: { + provider_id: "source-map-decoder", + operation: "trace_web_source_location", + reason, + }, + }); + expect(result.error.cleanupIncomplete).toBe(false); + }, +); diff --git a/tests/boundary/mcp/analysisViewMcp.test.ts b/tests/boundary/mcp/analysisViewMcp.test.ts index f23295829..b95aebe57 100644 --- a/tests/boundary/mcp/analysisViewMcp.test.ts +++ b/tests/boundary/mcp/analysisViewMcp.test.ts @@ -39,6 +39,8 @@ import { } from "../../fixtures/analysisView.js"; import { createTestBinarySession } from "../../fixtures/binarySession.js"; import { BINARY_LAYOUT_TEST_PROVIDER } from "../../fixtures/binaryDiagnostics/layout.js"; +import { wasmArtifactFixture } from "../../fixtures/wasm/artifact.js"; +import { evmInterfaceFixture } from "../../fixtures/evm/interface.js"; const connect = async ( binaryLayout?: BinaryLayoutService, @@ -69,6 +71,12 @@ const connect = async ( it("discovers an oversized native dossier by exact metadata and reads its retained view", async () => { const { client, session } = await connect(); + const advertised = (await client.listTools()).tools.find( + (tool) => tool.name === "inspect_analysis_view", + ); + expect(advertised?.description).toContain( + 'Native function Evidence requires kind native: view: {kind: "native", facet: "procedure"}', + ); const provider = { id: "ghidra", name: "Ghidra", version: "12.1.4" }; const profile = createAnalysisProfile(provider, { language: "fixture" }); const parent = createEvidence( @@ -98,6 +106,24 @@ it("discovers an oversized native dossier by exact metadata and reads its retain const retained = session.recordEvidence(record); if (!retained.ok) throw retained.error; } + const unsupportedSummary = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { kind: "retained-evidence", evidence_id: parent.evidence_id }, + view: { kind: "summary" }, + }, + }); + expect(parseMcpToolError(unsupportedSummary).error).toMatchObject({ + code: "invalid_request", + details: { + issues: [ + { + path: ["view"], + message: "analyze_function Evidence requires a native view.", + }, + ], + }, + }); const broad = await client.callTool({ name: "get_evidence_bundle", arguments: {}, @@ -286,6 +312,65 @@ it("reports a tampered inline Evidence ID at its full MCP source path", async () }); }); +it("rejects self-contained WASM and EVM Evidence views when the subject format differs", async () => { + const { client } = await connect(); + const wasm = wasmArtifactFixture(); + const evm = evmInterfaceFixture(); + const cases = [ + { + evidence: createEvidence( + { + path: wasm.artifact.path, + format: "elf", + sha256: wasm.artifact.sha256, + }, + { id: "fixture-wabt", name: "WABT", version: "1" }, + { + operation: "inspect_wasm_artifact", + parameters: { path: wasm.artifact.path }, + result: wasm, + }, + ), + }, + { + evidence: createEvidence( + { + path: evm.artifact.path, + format: "elf", + sha256: evm.artifact.sha256, + }, + { id: "fixture-evm", name: "EVMole", version: "1" }, + { + operation: "inspect_evm_interface", + parameters: { path: evm.artifact.path, encoding: "hex" }, + result: evm, + }, + ), + }, + ] as const; + + for (const { evidence } of cases) { + const response = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { kind: "inline", evidence }, + view: { kind: "summary" }, + }, + }); + expect(parseMcpToolError(response).error).toMatchObject({ + code: "invalid_request", + details: { + issues: [ + expect.objectContaining({ + path: ["source", "subject"], + reason: "invalid_value", + }), + ], + }, + }); + } +}); + it("admits portable captures before SDK Evidence parsing and preserves capture caveats", async () => { const { client } = await connect(); const dense = analysisViewCaptureEvidence(analysisViewObjectDenseCapture()); diff --git a/tests/boundary/mcp/androidPackageSummaryMcp.test.ts b/tests/boundary/mcp/androidPackageSummaryMcp.test.ts new file mode 100644 index 000000000..960886b02 --- /dev/null +++ b/tests/boundary/mcp/androidPackageSummaryMcp.test.ts @@ -0,0 +1,295 @@ +import { unlink } from "node:fs/promises"; +import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; +import { Ajv2020 } from "ajv/dist/2020.js"; +import { expect, it, onTestFinished, vi } from "vitest"; +import { AndroidAnalysisService } from "../../../src/application/android/AndroidAnalysisService.js"; +import { inspectAndroidPackage } from "../../../src/application/android/AndroidPackageInspection.js"; +import { inspectAnalysisView } from "../../../src/application/analysisView/AnalysisViewService.js"; +import { androidResultSchemas } from "../../../src/domain/android/androidAnalysis.js"; +import { + androidPackageSummaryViewResultSchema, + analysisViewResultSchema, +} from "../../../src/domain/analysisView/analysisView.js"; +import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js"; +import type { JsonValue } from "../../../src/domain/jsonValue.js"; +import { createServer } from "../../../src/server/createServer.js"; +import { createApplicationMcpHarness } from "../../fixtures/applicationMcpHarness.js"; +import { createTestBinarySession } from "../../fixtures/binarySession.js"; +import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; +import { + createJadxProtocolFixture, + verifyJadxFixtureCleanup, +} from "../../fixtures/android/jadx.js"; + +it.skipIf(process.platform === "win32")( + "retains complete APK Evidence and reads exact manifest without its source or another engine launch", + async () => { + const { provider, apk, launches } = + await createJadxProtocolFixture("large-manifest"); + const harness = await createApplicationMcpHarness({ + serverOptions: { androidAnalysis: provider }, + }); + onTestFinished(harness.close); + const { client, session } = harness; + const catalog = (await client.listTools()).tools; + const definition = catalog.find( + (tool) => tool.name === "inspect_android_package", + ); + if (definition?.outputSchema === undefined) + throw new Error("Missing APK schema"); + const outputSchema: Record = definition.outputSchema; + const ajv = new Ajv2020({ strict: false, validateFormats: false }); + expect(ajv.validateSchema(definition.inputSchema)).toBe(true); + expect(ajv.validateSchema(outputSchema)).toBe(true); + expect( + ajv.validate(definition.inputSchema, { path: apk, detail: "summary" }), + ).toBe(true); + expect( + ajv.validate( + catalog.find((tool) => tool.name === "inspect_android_class")! + .inputSchema, + { + path: apk, + class_name: "fixture.Target", + detail: "summary", + }, + ), + ).toBe(false); + const reply = await client.callTool({ + name: "inspect_android_package", + arguments: { path: apk, detail: "summary" }, + }); + expect(reply.isError).not.toBe(true); + expect( + ajv.validate(outputSchema, reply.structuredContent), + JSON.stringify(ajv.errors), + ).toBe(true); + const receipt = parseEvidence(reply.structuredContent); + const view = androidPackageSummaryViewResultSchema.parse( + receipt.normalized_result, + ); + const parent = session.evidenceById(view.parent_evidence_id); + if (parent === undefined) + throw new Error("Complete package Evidence not retained"); + const report = androidResultSchemas.inspect_android_package.parse( + parent.normalized_result, + ); + expect(parent.operation).toBe("inspect_android_package"); + expect(parent.parameters).toEqual({ path: apk }); + expect(view.artifact.sha256).toBe(parent.subject?.digest.sha256); + expect(view.artifact.sha256).not.toBe(report.engine.artifact_sha256); + expect(receipt.evidence_id).not.toBe(parent.evidence_id); + expect(receipt.evidence_links).toEqual([parent.evidence_id]); + const { manifest, ...declarations } = report; + expect(view.summary).toMatchObject(declarations); + expect(view.summary.manifest).toEqual({ + status: manifest.status, + reported_total_bytes: manifest.reported_total_bytes, + text_code_units: manifest.text.length, + text_included: false, + }); + expect(receipt.raw_result).toBeNull(); + expect(parent.raw_result).not.toBeNull(); + for (const detail of [undefined, "complete"]) { + const full = parseEvidence( + ( + await client.callTool({ + name: "inspect_android_package", + arguments: { + path: apk, + ...(detail === undefined ? {} : { detail }), + }, + }) + ).structuredContent, + ); + expect(full.operation).toBe("inspect_android_package"); + expect(full.normalized_result).toEqual(parent.normalized_result); + expect(full.parameters).toEqual(parent.parameters); + expect(full.raw_result).not.toBeNull(); + } + const before = JSON.stringify(parent); + await unlink(apk); + let text = ""; + let offset = 0; + do { + const paged = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { + kind: "retained-evidence", + evidence_id: parent.evidence_id, + }, + view: { kind: "android", facet: "manifest", offset, limit: 700000 }, + }, + }); + expect(paged.isError).not.toBe(true); + const page = analysisViewResultSchema.parse( + parseEvidence(paged.structuredContent).normalized_result, + ); + if (page.kind !== "android") throw new Error("Unexpected manifest page"); + text += page.item.text; + expect(page.item.source_status).toBe(manifest.status); + expect(page.item.reported_total_bytes).toBe( + manifest.reported_total_bytes, + ); + offset = page.coverage.next_offset ?? manifest.text.length; + } while (offset < manifest.text.length); + expect(text).toBe(manifest.text); + const portable = inspectAnalysisView({ + source: { kind: "inline", evidence: parseEvidence(JSON.parse(before)) }, + view: { kind: "summary" }, + }); + if (!portable.ok) throw portable.error; + expect(portable.value.normalized_result).toEqual(view); + expect(JSON.stringify(session.evidenceById(parent.evidence_id))).toBe( + before, + ); + expect( + session + .exportEvidenceBundle() + .records.find((record) => record.evidence_id === parent.evidence_id), + ).toEqual(parent); + expect(launches).toHaveLength(1); + await harness.close(); + await verifyJadxFixtureCleanup(launches); + }, + 30000, +); + +it("preserves partial/unknown declarations and Unicode text while rejecting missing APK identity and malformed source", () => { + const report = { + engine: { + name: "jadx", + version: null, + artifact_sha256: "b".repeat(64), + source_revision: null, + worker_count: 1, + heap_limit_mib: null, + }, + package_name: null, + version_name: null, + version_code: null, + min_sdk: null, + target_sdk: null, + permissions: [], + manifest: { status: "partial", text: "a😀b", reported_total_bytes: null }, + class_count: 0, + resource_count: 0, + signature_verification: "not_performed", + }; + const evidence = (result: JsonValue = report, hasSubject = true) => + createEvidence( + hasSubject + ? { path: "/original.apk", sha256: "a".repeat(64), format: "apk" } + : undefined, + { id: "jadx", name: "JADX", version: "0.7.1" }, + { + operation: "inspect_android_package", + parameters: {}, + result, + limitations: ["Original limit"], + }, + ); + const parent = evidence(); + const source = { kind: "inline", evidence: parent }; + const summary = inspectAnalysisView({ source, view: { kind: "summary" } }); + if (!summary.ok) throw summary.error; + const overview = androidPackageSummaryViewResultSchema.parse( + summary.value.normalized_result, + ); + expect(overview.summary.package_name).toBeNull(); + expect(overview.summary.manifest.status).toBe("partial"); + expect(overview.limitations).toEqual(parent.limitations); + const page = inspectAnalysisView({ + source, + view: { kind: "android", facet: "manifest", offset: 0, limit: 4 }, + }); + if (!page.ok) throw page.error; + const result = analysisViewResultSchema.parse(page.value.normalized_result); + expect(result).toMatchObject({ + kind: "android", + item: { + text: "a😀b", + source_status: "partial", + reported_total_bytes: null, + }, + coverage: { exhausted: true }, + }); + expect(result.unknowns.join(" ")).toContain("partial"); + for (const offset of [2]) + expect( + inspectAnalysisView({ + source, + view: { kind: "android", facet: "manifest", offset, limit: 2 }, + }), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" } }); + for (const invalid of [ + evidence(report, false), + evidence({ ...report, class_count: -1 }), + ]) + expect( + inspectAnalysisView({ + source: { kind: "inline", evidence: invalid }, + view: { kind: "summary" }, + }), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" } }); +}); + +it("rejects unavailable retention, invalid selectors and cancellation before provider execution", async () => { + const execute = vi.fn(); + const provider = { + execute, + close: async () => {}, + inspectAvailability: vi.fn(), + }; + const service = new AndroidAnalysisService(provider); + const retention = { recordEvidence: undefined, evidenceById: undefined }; + expect( + await inspectAndroidPackage( + service, + { path: "/missing.apk", detail: "summary" }, + retention, + ), + ).toMatchObject({ + ok: false, + error: { _tag: "AnalysisCapabilityUnavailableError" }, + }); + expect( + await inspectAndroidPackage( + service, + { path: "/missing.apk", detail: "other" }, + retention, + ), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" } }); + expect( + await inspectAndroidPackage( + service, + { path: "/missing.apk", detail: "summary" }, + retention, + { signal: AbortSignal.abort() }, + ), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisCancelledError" } }); + expect(execute).not.toHaveBeenCalled(); + const session = createTestBinarySession(() => { + throw new Error("Unexpected deep provider"); + }); + const server = createServer( + { kind: "fixed", analysis: session }, + { androidAnalysis: provider }, + ); + const client = new Client({ name: "android-fixed-summary", version: "1" }); + onTestFinished(async () => { + await client.close(); + await server.close(); + await session.close(); + }); + const [a, b] = InMemoryTransport.createLinkedPair(); + await server.connect(b); + await client.connect(a); + const reply = await client.callTool({ + name: "inspect_android_package", + arguments: { path: "/missing.apk", detail: "summary" }, + }); + expect(parseMcpToolError(reply).error.code).toBe("capability_unavailable"); + expect(execute).not.toHaveBeenCalled(); +}); diff --git a/tests/boundary/mcp/applicationEvidenceMcp.test.ts b/tests/boundary/mcp/applicationEvidenceMcp.test.ts index 16dfc142c..ba71b7921 100644 --- a/tests/boundary/mcp/applicationEvidenceMcp.test.ts +++ b/tests/boundary/mcp/applicationEvidenceMcp.test.ts @@ -2,6 +2,7 @@ import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; import type { Client } from "@modelcontextprotocol/client"; import { describe, expect, it } from "vitest"; import { Ajv2020 } from "ajv/dist/2020.js"; +import type { AnySchema } from "ajv"; import type { BinarySession } from "../../../src/application/binary/BinarySession.js"; import { @@ -10,12 +11,143 @@ import { SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE, } from "../../../src/contracts/javascript/javascriptApplicationWorkflowExamples.js"; import { createEvidence } from "../../../src/domain/evidence.js"; +import { javascriptApplicationAnalysisResultSchema } from "../../../src/domain/javascript/javascriptApplicationAnalysis.js"; +import { + createJavaScriptApplicationGraph, + createJavaScriptApplicationNode, +} from "../../../src/domain/javascript/javascriptApplicationGraph.js"; +import { createJavaScriptSemanticGraph } from "../../../src/domain/javascript/javascriptSemanticGraph.js"; +import { + artifactEvidence, + sourceMapReference, +} from "../../../src/domain/javascript/javascriptApplicationGraph.fixture.js"; import { createApplicationMcpHarness, type ApplicationMcpHarness, } from "../../fixtures/applicationMcpHarness.js"; import { createHistoricalSourceGraph } from "../../../src/domain/referenceSourceGraph.js"; +async function runUnicodeSourceMapComparison( + harness: ApplicationMcpHarness, +): Promise { + const baseApplication = SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.application; + const subject = baseApplication.subject; + if (subject === null) throw new Error("Application Evidence has no subject"); + const baseResult = javascriptApplicationAnalysisResultSchema.parse( + baseApplication.normalized_result, + ); + const baseGraph = baseResult.graph; + const decomposedSource = "cafe\u0301.ts"; + const unicodeSourceNode = createJavaScriptApplicationNode({ + kind: "source-module", + identity: { + strategy: "source-map-original", + source_root: "../src/", + stability: "source-map-exact", + source_map_sha256: "1".repeat(64), + original_source: decomposedSource, + source_sha256: "3".repeat(64), + }, + observations: [ + { + label: "decomposed source-map spelling", + source_map_reference: sourceMapReference( + decomposedSource, + "../src/", + "dist/main.js.map", + ), + properties: { content_available: true, content_sha256: "3".repeat(64) }, + evidence: artifactEvidence("1".repeat(64), "dist/main.js.map"), + }, + ], + }); + const applicationGraph = createJavaScriptApplicationGraph({ + schema: "JavaScriptApplicationGraph", + root_node_ids: [...baseGraph.root_node_ids, unicodeSourceNode.node_id], + nodes: [...baseGraph.nodes, unicodeSourceNode], + edges: baseGraph.edges, + coverage: baseGraph.coverage, + limitations: baseGraph.limitations, + }); + const semantic = baseResult.semantic_graph; + const { graph_id: _semanticGraphId, ...semanticInput } = semantic; + const semanticGraph = createJavaScriptSemanticGraph({ + ...semanticInput, + application_graph_id: applicationGraph.graph_id, + }); + const unicodeApplication = createEvidence( + { + path: baseResult.input_path, + sha256: subject.digest.sha256, + format: subject.format, + }, + baseApplication.provider, + { + predicateType: baseApplication.predicate_type, + operation: baseApplication.operation, + parameters: baseApplication.parameters, + result: { + ...baseResult, + graph: applicationGraph, + semantic_graph: semanticGraph, + }, + confidence: baseApplication.confidence, + authority: baseApplication.authority, + limitations: baseApplication.limitations, + evidenceLinks: baseApplication.evidence_links, + }, + ); + const historicalUnicodePath = "src/caf\u00e9.ts"; + const unicodeReference = createHistoricalSourceGraph({ + ...SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.reference, + root_sha256: undefined, + entries: SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.reference.entries.map( + (entry) => + entry.path === "src/main.ts" + ? { ...entry, path: historicalUnicodePath } + : entry, + ), + }); + const reply = await harness.client.callTool({ + name: "compare_source_to_bundle", + arguments: { reference: unicodeReference, application: unicodeApplication }, + }); + expect(reply.isError).not.toBe(true); + expect(reply.structuredContent).toMatchObject({ + normalized_result: { + items: [ + { + source_path: historicalUnicodePath, + status: "unknown", + current_node_ids: [], + candidates: [ + expect.objectContaining({ + confidence: "low", + signals: expect.arrayContaining([ + expect.objectContaining({ + kind: "unicode-equivalent-path", + source_value: historicalUnicodePath, + current_values: ["src/cafe\u0301.ts"], + }), + ]), + }), + ], + }, + ], + }, + }); + const advertised = (await harness.client.listTools()).tools.find( + ({ name }) => name === "compare_source_to_bundle", + ); + if (advertised?.outputSchema === undefined) + throw new Error("Comparison tool output schema is missing"); + const ajv = new Ajv2020({ strict: false, validateFormats: false }); + const outputSchema = advertised.outputSchema as AnySchema; + expect(ajv.validateSchema(outputSchema)).toBe(true); + const validateOutput = ajv.compile(outputSchema); + expect(validateOutput(reply.structuredContent)).toBe(true); +} + async function runInlineWorkflowScenarios( harness: ApplicationMcpHarness, ): Promise { @@ -92,6 +224,8 @@ async function runInlineWorkflowScenarios( }, }); + await runUnicodeSourceMapComparison(harness); + const referenceWithExclusion = createHistoricalSourceGraph({ ...SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.reference, root_sha256: undefined, diff --git a/tests/boundary/mcp/dartAotSummaryMcp.test.ts b/tests/boundary/mcp/dartAotSummaryMcp.test.ts new file mode 100644 index 000000000..be6a970d3 --- /dev/null +++ b/tests/boundary/mcp/dartAotSummaryMcp.test.ts @@ -0,0 +1,285 @@ +import { unlink } from "node:fs/promises"; +import { Ajv2020 } from "ajv/dist/2020.js"; +import { expect, it, onTestFinished, vi } from "vitest"; +import { FlutterBuildAnalysisService } from "../../../src/application/flutter/FlutterBuildAnalysisService.js"; +import { inspectDartAot } from "../../../src/application/flutter/DartAotInspection.js"; +import { inspectAnalysisView } from "../../../src/application/analysisView/AnalysisViewService.js"; +import { createFlutterBuildAnalysisProvider } from "../../../src/composition/flutter.js"; +import { + analysisViewResultSchema, + dartAotSummaryViewResultSchema, +} from "../../../src/domain/analysisView/analysisView.js"; +import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js"; +import { flutterResultSchemas } from "../../../src/domain/flutter/flutterBuildAnalysis.js"; +import type { JsonValue } from "../../../src/domain/jsonValue.js"; +import { aotFixtureImage } from "../../../src/flutter/FlutterBuild.fixture.js"; +import { createFlutterApk } from "../../fixtures/flutterApk.js"; +import { createApplicationMcpHarness } from "../../fixtures/applicationMcpHarness.js"; + +it("honors explicit ABI and old full requests, validates SDK schemas and reuses complete Evidence after APK removal", async () => { + const path = await createFlutterApk("views.apk", [ + { path: "lib/arm64-v8a/libapp.so", bytes: aotFixtureImage() }, + { path: "lib/x86_64/libapp.so", bytes: aotFixtureImage("b".repeat(32)) }, + ]); + const provider = createFlutterBuildAnalysisProvider(); + const execute = vi.spyOn(provider, "execute"); + const harness = await createApplicationMcpHarness({ + serverOptions: { flutterAnalysis: provider }, + }); + onTestFinished(harness.close); + const { client, session } = harness; + const catalog = (await client.listTools()).tools; + const definition = catalog.find((tool) => tool.name === "inspect_dart_aot"); + if (definition?.outputSchema === undefined) + throw new Error("Missing AOT output schema"); + const outputSchema: Record = definition.outputSchema; + const ajv = new Ajv2020({ strict: false, validateFormats: false }); + expect(ajv.validateSchema(definition.inputSchema)).toBe(true); + expect(ajv.validateSchema(outputSchema)).toBe(true); + expect( + ajv.validate( + catalog.find((tool) => tool.name === "identify_flutter_build")! + .inputSchema, + { path, detail: "summary" }, + ), + ).toBe(false); + const reply = await client.callTool({ + name: "inspect_dart_aot", + arguments: { path, abi: "x86_64", detail: "summary" }, + }); + expect(reply.isError).not.toBe(true); + expect( + ajv.validate(outputSchema, reply.structuredContent), + JSON.stringify(ajv.errors), + ).toBe(true); + const receipt = parseEvidence(reply.structuredContent); + const view = dartAotSummaryViewResultSchema.parse(receipt.normalized_result); + const parent = session.evidenceById(view.parent_evidence_id); + if (parent === undefined) + throw new Error("Complete AOT source was not retained"); + const report = flutterResultSchemas.inspect_dart_aot.parse( + parent.normalized_result, + ); + expect(report.abi).toBe("x86_64"); + expect(report.libapp.snapshot_hash).toBe("b".repeat(32)); + expect(parent.parameters).toEqual({ path, abi: "x86_64" }); + expect(execute).toHaveBeenLastCalledWith( + { operation: "inspect_dart_aot", input: { path, abi: "x86_64" } }, + expect.anything(), + ); + expect(view.summary.libapp).toEqual(report.libapp); + expect(view.summary.target).toEqual(report.target); + expect(view.summary.coverage).toBe(report.coverage); + expect(receipt.evidence_id).not.toBe(parent.evidence_id); + expect(receipt.evidence_links).toEqual([parent.evidence_id]); + for (const detail of [undefined, "complete"]) { + const complete = parseEvidence( + ( + await client.callTool({ + name: "inspect_dart_aot", + arguments: { + path, + abi: "x86_64", + ...(detail === undefined ? {} : { detail }), + }, + }) + ).structuredContent, + ); + expect(complete.operation).toBe("inspect_dart_aot"); + expect(complete.normalized_result).toEqual(parent.normalized_result); + expect(complete.parameters).toEqual(parent.parameters); + } + const preferred = parseEvidence( + (await client.callTool({ name: "inspect_dart_aot", arguments: { path } })) + .structuredContent, + ); + expect( + flutterResultSchemas.inspect_dart_aot.parse(preferred.normalized_result) + .abi, + ).toBe("arm64-v8a"); + const original = JSON.stringify(parent); + await unlink(path); + const calls = execute.mock.calls.length; + for (const collection of [ + "package_uris", + "dart_uris", + "class_like_tokens", + ] as const) { + const strings: string[] = []; + let offset = 0; + do { + const reply = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { + kind: "retained-evidence", + evidence_id: parent.evidence_id, + }, + view: { kind: "dart-aot", collection, offset, limit: 1 }, + }, + }); + expect(reply.isError).not.toBe(true); + const page = analysisViewResultSchema.parse( + parseEvidence(reply.structuredContent).normalized_result, + ); + if (page.kind !== "dart-aot") throw new Error("Wrong pool page kind"); + strings.push(...page.items); + expect(page.libapp).toEqual(report.libapp); + expect(page.source_coverage).toBe(report.coverage); + expect(page.string_pool.coverage).toBe(report.string_pool.coverage); + offset = + page.coverage.next_offset ?? report.string_pool[collection].length; + } while (offset < report.string_pool[collection].length); + expect(strings).toEqual(report.string_pool[collection]); + } + expect(execute).toHaveBeenCalledTimes(calls); + expect(JSON.stringify(session.evidenceById(parent.evidence_id))).toBe( + original, + ); + expect( + session + .exportEvidenceBundle() + .records.find((record) => record.evidence_id === parent.evidence_id), + ).toEqual(parent); + const portable = inspectAnalysisView({ + source: { kind: "inline", evidence: parent }, + view: { kind: "summary" }, + }); + if (!portable.ok) throw portable.error; + expect(portable.value.normalized_result).toEqual(view); +}, 30000); + +it("preserves null snapshot facts and pool lower bounds after exhaustion, rejecting malformed and conflicting identities", () => { + const report = { + target: { path: "/source.apk", bytes: 10, sha256: "a".repeat(64) }, + abi: "arm64-v8a", + libapp: { + coverage: "partial", + bytes: 1, + sha256: "b".repeat(64), + snapshot_hash: null, + snapshot_hash_candidates: [], + snapshot_hash_sources: 0, + sections: [], + }, + string_pool: { + coverage: "partial", + package_uris: ["package:opaque/a.dart"], + package_uri_count_at_least: 1000, + dart_uris: [], + dart_uri_count_at_least: 0, + class_like_tokens: ["incidental"], + class_like_token_count_at_least: 4000, + printable_run_count: 12, + }, + coverage: "partial", + }; + const evidence = ( + result: JsonValue = report, + sha: string | null = "a".repeat(64), + ) => + createEvidence( + sha === null + ? undefined + : { path: "/source.apk", sha256: sha, format: "apk" }, + { id: "flutter", name: "Flutter", version: null }, + { + operation: "inspect_dart_aot", + parameters: {}, + result, + limitations: ["Original uncertainty"], + }, + ); + for (const parent of [evidence(), evidence(report, null)]) { + const summary = inspectAnalysisView({ + source: { kind: "inline", evidence: parent }, + view: { kind: "summary" }, + }); + if (!summary.ok) throw summary.error; + const result = dartAotSummaryViewResultSchema.parse( + summary.value.normalized_result, + ); + expect(result.summary.libapp.snapshot_hash).toBeNull(); + expect(result.summary.string_pool.package_uri_count_at_least).toBe(1000); + expect(result.summary.string_pool.returned_counts.package_uris).toBe(1); + expect(result.limitations).toEqual(parent.limitations); + const page = inspectAnalysisView({ + source: { kind: "inline", evidence: parent }, + view: { + kind: "dart-aot", + collection: "package_uris", + offset: 0, + limit: 10, + }, + }); + if (!page.ok) throw page.error; + expect(page.value.normalized_result).toMatchObject({ + kind: "dart-aot", + items: report.string_pool.package_uris, + source_coverage: "partial", + string_pool: { coverage: "partial", package_uri_count_at_least: 1000 }, + coverage: { total: 1, exhausted: true }, + }); + } + expect( + inspectAnalysisView({ + source: { kind: "inline", evidence: evidence(report, "c".repeat(64)) }, + view: { kind: "summary" }, + }), + ).toMatchObject({ ok: false, error: { _tag: "EvidenceIntegrityError" } }); + expect( + inspectAnalysisView({ + source: { + kind: "inline", + evidence: evidence({ + ...report, + string_pool: { + ...report.string_pool, + package_uri_count_at_least: -1, + }, + }), + }, + view: { kind: "summary" }, + }), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" } }); + expect( + inspectAnalysisView({ + source: { kind: "inline", evidence: evidence() }, + view: { kind: "android", facet: "manifest", offset: 0, limit: 1 }, + }), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" } }); +}); + +it("rejects unavailable retention, invalid delivery and cancellation before producer work", async () => { + const provider = createFlutterBuildAnalysisProvider(); + onTestFinished(() => provider.close()); + const execute = vi.spyOn(provider, "execute"); + const service = new FlutterBuildAnalysisService(provider); + const retention = { recordEvidence: undefined, evidenceById: undefined }; + expect( + await inspectDartAot( + service, + { path: "/missing.apk", abi: "x86_64", detail: "summary" }, + retention, + ), + ).toMatchObject({ + ok: false, + error: { _tag: "AnalysisCapabilityUnavailableError" }, + }); + expect( + await inspectDartAot( + service, + { path: "/missing.apk", detail: "other" }, + retention, + ), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" } }); + expect( + await inspectDartAot( + service, + { path: "/missing.apk", detail: "summary" }, + retention, + { signal: AbortSignal.abort() }, + ), + ).toMatchObject({ ok: false, error: { _tag: "AnalysisCancelledError" } }); + expect(execute).not.toHaveBeenCalled(); +}); diff --git a/tests/boundary/mcp/enhancedTools.04-uses-complete-inventories-inline.test.ts b/tests/boundary/mcp/enhancedTools.04-uses-complete-inventories-inline.test.ts index 8e3a39969..e452d70c3 100644 --- a/tests/boundary/mcp/enhancedTools.04-uses-complete-inventories-inline.test.ts +++ b/tests/boundary/mcp/enhancedTools.04-uses-complete-inventories-inline.test.ts @@ -144,14 +144,26 @@ describe("enhanced MCP tools", () => { ); expect(result).toEqual({ document: "fixture", + image_base: "0x1000", segments: [ - { name: "__TEXT", start: "0x1000", end: "0x1800", length: 2048 }, - { name: "__DATA", start: "0x1800", end: "0x2000", length: 2048 }, + { + name: "__TEXT", + start: "0x1000", + end: "0x1800", + length: 2048, + image_base: "0x1000", + }, + { + name: "__DATA", + start: "0x1800", + end: "0x2000", + length: 2048, + image_base: "0x1000", + }, ], segment_count: 2, procedure_count: 2, string_count: 700, - image_base: "0x1000", }); }); diff --git a/tests/boundary/mcp/evidenceBundleInline.test.ts b/tests/boundary/mcp/evidenceBundleInline.test.ts index adb95ef8f..ae07a1be5 100644 --- a/tests/boundary/mcp/evidenceBundleInline.test.ts +++ b/tests/boundary/mcp/evidenceBundleInline.test.ts @@ -1,10 +1,20 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; + import { ok as resultOk } from "../../../src/domain/result.js"; import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; import { expect, it } from "vitest"; import { createTestBinarySession } from "../../fixtures/binarySession.js"; import { observed } from "../../fixtures/analysisExecution.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; +import { createAnalysisProfile } from "../../../src/domain/analysisProfile.js"; import { createEvidence } from "../../../src/domain/evidence.js"; +import { ANALYSIS_SNAPSHOT_TARGET } from "../../../src/domain/analysisSnapshot.fixture.js"; +import { jsonValueSchema } from "../../../src/domain/jsonValue.js"; +import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCaptureExample.js"; +import { PROCESS_PROVIDER } from "../../../src/domain/process/processEvidenceProvider.js"; import { createServer } from "../../../src/server/createServer.js"; it("returns the complete session Evidence bundle in the tool result", async () => { @@ -44,3 +54,251 @@ it("returns the complete session Evidence bundle in the tool result", async () = await Promise.allSettled([client.close(), server.close(), session.close()]); } }); + +it("rejects bundle field stripping at MCP import without changing retained evidence", async () => { + const root = await createTestTempDirectory("rea-evidence-bundle-mcp-"); + const sourceSession = createBundleSourceSession(); + const targetSession = createTestBinarySession(() => ({ + execute: () => Promise.resolve(observed(null)), + close: () => Promise.resolve(resultOk(null)), + })); + const source = await connectEvidenceMcp("bundle-source", sourceSession); + const target = await connectEvidenceMcp("bundle-target", targetSession); + const { client: sourceClient } = source; + const { client: targetClient } = target; + const bundlePath = join(root, "exported.json"); + const targetExportPath = join(root, "round-trip.json"); + + try { + const { sourceJson, records, evidenceIndex } = await exportFixtureBundle( + sourceClient, + bundlePath, + ); + const initial = structured( + await targetClient.callTool({ + name: "get_evidence_bundle", + arguments: {}, + }), + ).result; + for (const [label, path] of unsupportedBundleFields(evidenceIndex)) { + const candidate = structuredClone(sourceJson); + setPath(candidate, path, "unsupported-metadata"); + const malformedPath = join(root, `${label.replaceAll(" ", "-")}.json`); + await writeFile(malformedPath, JSON.stringify(candidate)); + const rejected = await targetClient.callTool({ + name: "import_evidence_bundle", + arguments: { path: malformedPath }, + }); + expect(parseMcpToolError(rejected), label).toMatchObject({ + error: { code: "evidence_integrity_mismatch" }, + }); + expect( + structured( + await targetClient.callTool({ + name: "get_evidence_bundle", + arguments: {}, + }), + ).result, + label, + ).toEqual(initial); + } + + const imported = await targetClient.callTool({ + name: "import_evidence_bundle", + arguments: { path: bundlePath }, + }); + if (imported.isError === true) + throw new Error(JSON.stringify(parseMcpToolError(imported))); + await targetClient.callTool({ + name: "export_evidence_bundle", + arguments: { path: targetExportPath }, + }); + expect(JSON.parse(await readFile(targetExportPath, "utf8"))).toEqual( + sourceJson, + ); + const observedRecord = records[evidenceIndex]!; + expect(observedRecord.parameters).toEqual({ caller: { note: "preserve" } }); + expect(observedRecord.normalized_result).toEqual({ + producer: { extension: "preserve" }, + }); + expect(object(observedRecord.analysis_profile).parameters).toEqual({ + loader: { mode: "full" }, + }); + } finally { + await Promise.allSettled([ + sourceClient.close(), + source.server.close(), + sourceSession.close(), + targetClient.close(), + target.server.close(), + targetSession.close(), + ]); + } +}); + +const createBundleSourceSession = () => { + const provider = { id: "fixture", name: "Fixture", version: "1" }; + const evidence = createEvidence(ANALYSIS_SNAPSHOT_TARGET, provider, { + operation: "observe", + parameters: { caller: { note: "preserve" } }, + result: { producer: { extension: "preserve" } }, + analysisProfile: createAnalysisProfile(provider, { + loader: { mode: "full" }, + }), + environment: { + id: "fixture-linux", + platform: "linux", + architecture: "x86_64", + isolation: "process", + }, + locations: [{ kind: "address", address: "0x1000" }], + }); + const session = createTestBinarySession(() => ({ + execute: () => Promise.resolve(observed(null)), + close: () => Promise.resolve(resultOk(null)), + })); + expect(session.recordEvidence(evidence).ok).toBe(true); + for (const extra of [ + createEvidence(ANALYSIS_SNAPSHOT_TARGET, provider, { + operation: "controlled_replay", + parameters: {}, + result: { completed: true }, + authority: "controlled-replay", + }), + createEvidence(undefined, PROCESS_PROVIDER, { + predicateType: "rea.process-capture", + operation: "capture_process_scenario", + parameters: {}, + result: jsonValueSchema.parse(EMPTY_PROCESS_CAPTURE_EXAMPLE), + confidence: "observed", + authority: "controlled-replay", + }), + ]) + expect(session.recordEvidence(extra).ok).toBe(true); + return session; +}; + +const exportFixtureBundle = async ( + client: Client, + path: string, +): Promise<{ + readonly sourceJson: unknown; + readonly records: Record[]; + readonly evidenceIndex: number; +}> => { + const unknown = await client.callTool({ + name: "record_unknown", + arguments: { + question: "Does this remain unknown?", + severity: "medium", + domain: "bundle-format", + required_authority: null, + required_confidence: "derived", + required_environment: null, + recommended_probes: [{ operation: "observe", rationale: "Inspect it." }], + relationships: [], + }, + }); + expect(unknown.isError).not.toBe(true); + const exported = await client.callTool({ + name: "export_evidence_bundle", + arguments: { path }, + }); + expect(exported.isError).not.toBe(true); + const sourceJson = JSON.parse(await readFile(path, "utf8")) as unknown; + const records = array(object(sourceJson).records).map(object); + const evidenceIndex = records.findIndex( + (record) => record.operation === "observe", + ); + expect(evidenceIndex).toBeGreaterThanOrEqual(0); + return { sourceJson, records, evidenceIndex }; +}; + +const unsupportedBundleFields = ( + evidenceIndex: number, +): readonly [string, readonly (string | number)[]][] => [ + ["bundle envelope", ["schema_version"]], + ["record provider", ["records", evidenceIndex, "provider", "future_field"]], + ["provider manifest", ["providers", 0, "future_field"]], + ["record subject", ["records", evidenceIndex, "subject", "future_field"]], + [ + "subject digest", + ["records", evidenceIndex, "subject", "digest", "future_field"], + ], + ["artifact manifest", ["artifacts", 0, "future_field"]], + [ + "record environment", + ["records", evidenceIndex, "environment", "future_field"], + ], + ["environment manifest", ["environments", 0, "future_field"]], + [ + "source location", + ["records", evidenceIndex, "locations", 0, "future_field"], + ], + ["scenario manifest", ["scenarios", 0, "future_field"]], + ["capture manifest", ["captures", 0, "future_field"]], + [ + "analysis profile", + ["records", evidenceIndex, "analysis_profile", "future_field"], + ], + [ + "profile provider", + ["records", evidenceIndex, "analysis_profile", "provider", "future_field"], + ], + ["unknown revision", ["unknowns", 0, "future_field"]], + ["unknown probe", ["unknowns", 0, "recommended_probes", 0, "future_field"]], +]; + +const connectEvidenceMcp = async ( + name: string, + session: ReturnType, +) => { + const server = createServer({ kind: "session", session }); + const client = new Client({ name, version: "1" }); + const [clientTransport, serverTransport] = + InMemoryTransport.createLinkedPair(); + await server.connect(serverTransport); + await client.connect(clientTransport); + return { client, server }; +}; + +const object = (value: unknown): Record => { + if (typeof value !== "object" || value === null || Array.isArray(value)) + throw new Error("Expected object in exported Evidence bundle"); + return value as Record; +}; + +const array = (value: unknown): unknown[] => { + if (!Array.isArray(value)) + throw new Error("Expected array in Evidence bundle"); + return value; +}; + +const setPath = ( + root: unknown, + path: readonly (string | number)[], + value: unknown, +): void => { + const [last, ...parents] = [...path].reverse(); + if (last === undefined) throw new Error("Expected a nonempty bundle path"); + const target = parents + .reverse() + .reduce( + (current, segment) => + typeof segment === "number" + ? array(current)[segment] + : object(current)[segment], + root, + ); + object(target)[String(last)] = value; +}; + +const structured = (result: Awaited>) => { + if (result.isError === true) throw parseMcpToolError(result); + if ( + typeof result.structuredContent !== "object" || + result.structuredContent === null + ) + throw new Error("Missing structured MCP result"); + return result.structuredContent as Record; +}; diff --git a/tests/boundary/mcp/evidenceImportLifecycle.test.ts b/tests/boundary/mcp/evidenceImportLifecycle.test.ts new file mode 100644 index 000000000..f0371ef89 --- /dev/null +++ b/tests/boundary/mcp/evidenceImportLifecycle.test.ts @@ -0,0 +1,155 @@ +import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; +import { writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { expect, it, onTestFinished, vi } from "vitest"; + +import { createEvidence } from "../../../src/domain/evidence.js"; +import { createEvidenceBundle } from "../../../src/domain/evidenceBundle.js"; +import { OwnedFileHandle } from "../../../src/filesystem/OwnedFileHandle.js"; +import { createServer } from "../../../src/server/createServer.js"; +import { + createDeferred, + createTestBinarySession, +} from "../../fixtures/binarySession.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +const connectImportSession = async () => { + const root = await createTestTempDirectory("rea-mcp-import-lifecycle-"); + const session = createTestBinarySession(() => { + throw new Error("Evidence import must not start a binary provider"); + }); + const server = createServer({ kind: "session", session }); + const client = new Client({ + name: "evidence-import-lifecycle", + version: "1", + }); + const readCompleted = createDeferred(); + const releaseRead = createDeferred(); + const originalFileClose = OwnedFileHandle.prototype.close; + vi.spyOn(OwnedFileHandle.prototype, "close").mockImplementationOnce( + async function (this: OwnedFileHandle) { + await originalFileClose.call(this); + readCompleted.resolve(); + await releaseRead.promise; + }, + ); + const closeStarted = createDeferred(); + const originalSessionClose = session.close.bind(session); + const events: string[] = []; + vi.spyOn(session, "close").mockImplementation((...args) => { + const closing = originalSessionClose(...args); + closeStarted.resolve(); + return closing.then((result) => { + events.push("close"); + return result; + }); + }); + const originalImport = session.importEvidenceBundle.bind(session); + vi.spyOn(session, "importEvidenceBundle").mockImplementation((bundle) => { + const imported = originalImport(bundle); + events.push("import"); + return imported; + }); + onTestFinished(async () => { + releaseRead.resolve(); + vi.restoreAllMocks(); + await client.close(); + await server.close(); + await session.close(); + }); + const [clientTransport, serverTransport] = + InMemoryTransport.createLinkedPair(); + const laterImportDispatched = createDeferred(); + let importsDispatched = 0; + const send = clientTransport.send.bind(clientTransport); + vi.spyOn(clientTransport, "send").mockImplementation( + async (message, ...args) => { + await send(message, ...args); + if ( + "method" in message && + message.method === "tools/call" && + message.params?.name === "import_evidence_bundle" + ) { + importsDispatched += 1; + if (importsDispatched === 2) laterImportDispatched.resolve(); + } + }, + ); + await server.connect(serverTransport); + await client.connect(clientTransport); + const importBundle = async (operation: string) => { + const record = createEvidence( + undefined, + { id: "fixture", name: "Fixture", version: "1" }, + { operation, parameters: {}, result: { retained: operation } }, + ); + const path = join(root, `${operation}.json`); + await writeFile(path, JSON.stringify(createEvidenceBundle([record]))); + return client.callTool({ + name: "import_evidence_bundle", + arguments: { path }, + }); + }; + return { + client, + session, + events, + importBundle, + readCompleted: readCompleted.promise, + closeStarted: closeStarted.promise, + laterImportDispatched: laterImportDispatched.promise, + releaseRead: () => releaseRead.resolve(), + }; +}; + +it("drains a file import before close_binary clears the session", async () => { + const fixture = await connectImportSession(); + const importing = fixture.importBundle("before_close"); + await fixture.readCompleted; + const closing = fixture.client.callTool({ + name: "close_binary", + arguments: {}, + }); + await fixture.closeStarted; + await fixture.client.ping(); + fixture.releaseRead(); + const [imported, closed] = await Promise.all([importing, closing]); + + expect(imported.isError, JSON.stringify(imported)).not.toBe(true); + expect(imported.structuredContent).toMatchObject({ + result: { imported: 1, unknowns_added: 0, total: 1 }, + }); + expect(closed.isError, JSON.stringify(closed)).not.toBe(true); + expect(fixture.events).toEqual(["import", "close"]); + expect(fixture.session.exportEvidenceBundle().records).toEqual([]); + await fixture.client.ping(); +}); + +it("admits a later import after close_binary without retaining the earlier bundle", async () => { + const fixture = await connectImportSession(); + const earlier = fixture.importBundle("before_close"); + await fixture.readCompleted; + const closing = fixture.client.callTool({ + name: "close_binary", + arguments: {}, + }); + await fixture.closeStarted; + const later = fixture.importBundle("after_close"); + await fixture.laterImportDispatched; + await fixture.client.ping(); + fixture.releaseRead(); + const results = await Promise.all([earlier, closing, later]); + + for (const result of results) + expect(result.isError, JSON.stringify(result)).not.toBe(true); + expect(results[2]?.structuredContent).toMatchObject({ + result: { imported: 1, unknowns_added: 0, total: 1 }, + }); + expect(fixture.events).toEqual(["import", "close", "import"]); + expect( + fixture.session + .exportEvidenceBundle() + .records.map((record) => record.operation), + ).toEqual(["after_close"]); + await fixture.client.ping(); +}); diff --git a/tests/boundary/mcp/evmInterfaceMcp.test.ts b/tests/boundary/mcp/evmInterfaceMcp.test.ts index 704af92c5..823a4d3cf 100644 --- a/tests/boundary/mcp/evmInterfaceMcp.test.ts +++ b/tests/boundary/mcp/evmInterfaceMcp.test.ts @@ -28,8 +28,11 @@ import { it("advertises exact valid schemas and records inline EVM interface evidence without a binary target", async () => { const value = evmInterfaceFixture(); + const inspect = vi.fn(() => + Promise.resolve(ok(evmInterfaceExecution(value))), + ); const service = new EvmInterfaceService({ - inspect: () => Promise.resolve(ok(evmInterfaceExecution(value))), + inspect, }); const session = createTestBinarySession(() => { throw new Error("deep provider must not start"); @@ -71,6 +74,7 @@ it("advertises exact valid schemas and records inline EVM interface evidence wit expect(() => registerEvmTools(server, service, silentLogger)).toThrow( /inspect_evm_interface.*already registered/, ); + expect(inspect).not.toHaveBeenCalled(); expect( (await client.listTools()).tools.filter( (tool) => tool.name === "inspect_evm_interface", @@ -103,6 +107,30 @@ it("advertises exact valid schemas and records inline EVM interface evidence wit ).toBe(true); }); +it("rejects an EVM provider response with a non-file subject before recording Evidence", async () => { + const value = evmInterfaceFixture(); + const execution = evmInterfaceExecution(value); + const malformed = { + ...execution, + subject: { ...execution.subject, format: "elf" }, + } as unknown as typeof execution; + const harness = await createApplicationMcpHarness({ + serverOptions: { + evmInterface: new EvmInterfaceService({ + inspect: () => Promise.resolve(ok(malformed)), + }), + }, + }); + onTestFinished(harness.close); + const before = harness.session.exportEvidenceBundle().records.length; + const response = await harness.client.callTool({ + name: "inspect_evm_interface", + arguments: { path: value.artifact.path, encoding: "hex" }, + }); + expect(parseMcpToolError(response).error.code).toBe("unreadable_output"); + expect(harness.session.exportEvidenceBundle().records).toHaveLength(before); +}); + it.each(["unavailable", "incompatible-output"])( "preserves a healthy WASM peer and explicit EVM failure: %s", async (scenario) => { diff --git a/tests/boundary/mcp/ghidraMcpHarness.ts b/tests/boundary/mcp/ghidraMcpHarness.ts index 7e2c3ae73..ad3565992 100644 --- a/tests/boundary/mcp/ghidraMcpHarness.ts +++ b/tests/boundary/mcp/ghidraMcpHarness.ts @@ -95,7 +95,7 @@ export const sessionEvidence = (session: BinarySession, value: unknown) => { const installationHost = (): GhidraInstallationHost => ({ platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/tests/boundary/mcp/ghidraReopen.test.ts b/tests/boundary/mcp/ghidraReopen.test.ts index bdac57233..6a90f0118 100644 --- a/tests/boundary/mcp/ghidraReopen.test.ts +++ b/tests/boundary/mcp/ghidraReopen.test.ts @@ -99,7 +99,7 @@ class FixtureLauncher implements GhidraLauncher { const installationHost: GhidraInstallationHost = { platform: "linux", architecture: "x64", - readText: () => "application.version=12.1.4\n", + readText: () => "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.11", diff --git a/tests/boundary/mcp/nativeAddressContextMcp.test.ts b/tests/boundary/mcp/nativeAddressContextMcp.test.ts new file mode 100644 index 000000000..5b855fc26 --- /dev/null +++ b/tests/boundary/mcp/nativeAddressContextMcp.test.ts @@ -0,0 +1,121 @@ +import { afterEach, expect, it } from "vitest"; +import { Ajv2020 } from "ajv/dist/2020.js"; +import type { AnySchemaObject } from "ajv"; +import { + closeEnhancedToolResources, + connect, + jsonResult, +} from "./enhancedToolsHarness.js"; +import { observed as ok } from "../../fixtures/analysisExecution.js"; +import type { SegmentSummary } from "../../../src/domain/hopperValues.js"; + +afterEach(closeEnhancedToolResources); + +const segment = { + name: ".text", + start: "0x101000", + end: "0x101100", + readable: true, + writable: false, + executable: true, + image_base: "0x100000", + address_space: "ram", +}; +const overviewClient = (segments: SegmentSummary[]) => + connect({ + execute: (name) => { + switch (name) { + case "current_document": + return Promise.resolve(ok("fixture")); + case "list_documents": + return Promise.resolve(ok(["fixture"])); + case "list_segments": + return Promise.resolve(ok(segments)); + case "list_procedures": + return Promise.resolve(ok([{ address: "0x101013", value: "entry" }])); + case "list_strings": + return Promise.resolve(ok([])); + default: + throw new Error(`Unexpected operation: ${name}`); + } + }, + }); + +it("preserves observed coordinates and main's optional-string output contract after SDK conversion", async () => { + const client = await overviewClient([segment]); + const schema = (await client.listTools()).tools.find( + ({ name }) => name === "binary_overview", + )?.outputSchema; + if (schema === undefined) throw new Error("Missing overview output schema"); + const validate = new Ajv2020({ strict: false }).compile( + schema as AnySchemaObject, + ); + const response = await client.callTool({ + name: "binary_overview", + arguments: {}, + }); + expect(validate(response.structuredContent)).toBe(true); + expect(jsonResult(response)).toMatchObject({ + image_base: "0x100000", + segments: [ + { start: "0x101000", image_base: "0x100000", address_space: "ram" }, + ], + }); + const absent = JSON.parse(JSON.stringify(response.structuredContent)); + delete absent.normalized_result.image_base; + expect(validate(absent)).toBe(true); + absent.normalized_result.image_base = null; + expect(validate(absent)).toBe(false); +}); + +it("omits unreported bases without inventing zero and preserves explicit zero", async () => { + const { image_base: _base, ...unreported } = segment; + const client = await overviewClient([unreported]); + expect( + jsonResult( + await client.callTool({ name: "binary_overview", arguments: {} }), + ), + ).not.toHaveProperty("image_base"); + const zero = await overviewClient([{ ...segment, image_base: "0x0" }]); + expect( + jsonResult(await zero.callTool({ name: "binary_overview", arguments: {} })), + ).toMatchObject({ image_base: "0x0" }); +}); + +it("keeps a partially reported base unknown while retaining the reported segment observation", async () => { + const { image_base: _base, ...unreported } = segment; + const client = await overviewClient([ + segment, + { ...unreported, name: ".data" }, + ]); + const result = jsonResult( + await client.callTool({ name: "binary_overview", arguments: {} }), + ); + expect(result).not.toHaveProperty("image_base"); + expect(result).toMatchObject({ + segments: [{ image_base: "0x100000" }, { name: ".data" }], + }); +}); + +it("retains all conflicting observations after repeated early bases without selecting one", async () => { + const { address_space: _space, ...unreported } = segment; + const client = await overviewClient([ + ...Array.from({ length: 40 }, () => unreported), + { + ...segment, + name: ".data", + start: "other%20space:0x201000", + end: "other%20space:0x201100", + image_base: "0x200000", + address_space: "other space", + }, + ]); + const result = jsonResult( + await client.callTool({ name: "binary_overview", arguments: {} }), + ); + expect(result).not.toHaveProperty("image_base"); + expect(result).toHaveProperty("segments.length", 41); + expect(result).toHaveProperty("segments.40.image_base", "0x200000"); + expect(result).toHaveProperty("segments.40.address_space", "other space"); + expect(result).not.toHaveProperty("segments.0.address_space"); +}); diff --git a/tests/boundary/mcp/nativeMachoSummaryMcp.test.ts b/tests/boundary/mcp/nativeMachoSummaryMcp.test.ts new file mode 100644 index 000000000..e492263fa --- /dev/null +++ b/tests/boundary/mcp/nativeMachoSummaryMcp.test.ts @@ -0,0 +1,216 @@ +import { silentLogger } from "../../../src/logger.js"; +import { copyFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; + +import { describe, expect } from "vitest"; +import { z } from "zod"; + +import { createBinarySession } from "../../../src/composition/binary.js"; +import { parseConfig } from "../../../src/config/parseConfig.js"; +import { inspectMachoSchema } from "../../../src/domain/native/nativeInspection.js"; +import { createServer } from "../../../src/server/createServer.js"; +import { thinMach } from "../../../src/domain/binaryTarget.fixture.js"; +import { createTestBinarySession } from "../../fixtures/binarySession.js"; +import { observed } from "../../fixtures/analysisExecution.js"; +import { ok } from "../../../src/domain/result.js"; +import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { mcpTest } from "../../support/mcp/mcpFixture.js"; + +const evidenceOf = (schema: Schema) => + z.object({ + evidence_id: z.string(), + parameters: z.record(z.string(), z.unknown()), + normalized_result: schema, + }); +const countSchema = z.object({ + returned: z.number(), + total: z.number().nullable(), + exhaustive: z.boolean(), +}); +const summarySchema = z.object({ + kind: z.literal("summary"), + parent_evidence_id: z.string(), + summary: z.object({ + uuid: z.string().nullable(), + collections: z.record(z.string(), countSchema), + provenance_count: z.number(), + }), +}); +const pageSchema = z.object({ + kind: z.literal("macho"), + item: z.array(z.unknown()), + coverage: z.object({ next_offset: z.number().nullable() }), +}); + +describe.skipIf(process.platform !== "darwin")( + "Mach-O summary delivery through MCP", + () => { + mcpTest( + "retains complete inspect_macho Evidence and pages its exact rows", + async ({ mcp, onTestFinished }) => { + const target = join( + await createTestTempDirectory("rea-macho-summary-mcp-"), + "ls", + ); + await copyFile("/bin/ls", target); + const configured = parseConfig({ REA_ANALYSIS_PROVIDER: "auto" }); + if (!configured.ok) throw configured.error; + const session = createBinarySession( + configured.value, + silentLogger, + process.env, + ); + onTestFinished(async () => { + await session.close(); + }); + const client = await mcp.connect( + createServer({ kind: "session", session }), + ); + const opened = await client.callTool({ + name: "open_binary", + arguments: { path: target }, + }); + expect(opened.isError, JSON.stringify(opened.content)).not.toBe(true); + + const complete = await client.callTool({ + name: "inspect_macho", + arguments: {}, + }); + expect(complete.isError, JSON.stringify(complete.content)).not.toBe( + true, + ); + const full = evidenceOf(inspectMachoSchema).parse( + complete.structuredContent, + ); + // Omitted detail keeps the default Evidence parameters unchanged. + expect(full.parameters).toEqual({}); + + const summarized = await client.callTool({ + name: "inspect_macho", + arguments: { detail: "summary" }, + }); + expect(summarized.isError, JSON.stringify(summarized.content)).not.toBe( + true, + ); + const summary = evidenceOf(summarySchema).parse( + summarized.structuredContent, + ).normalized_result; + // Delivery detail never reaches the tools or the source Evidence ID. + expect(summary.parent_evidence_id).toBe(full.evidence_id); + const report = full.normalized_result; + expect(summary.summary.uuid).toBe(report.uuid); + expect(summary.summary.provenance_count).toBe(report.provenance.length); + for (const name of ["imports", "exports", "dependencies"] as const) + expect(summary.summary.collections[name]).toEqual({ + returned: report[name].items.length, + total: report[name].total, + exhaustive: report[name].exhaustive, + }); + expect(JSON.stringify(summarized.structuredContent)).not.toContain( + report.imports.items[0]?.name ?? "_", + ); + + // Every facet must reassemble the unparsed complete rows exactly. + const raw = z + .object({ normalized_result: z.record(z.string(), z.unknown()) }) + .parse(complete.structuredContent).normalized_result; + const facets = [ + "entrypoints", + "architectures", + "build_metadata", + "load_commands", + "dependencies", + "imports", + "exports", + "segments", + "provenance", + ] as const; + for (const facet of facets) { + const rows: unknown[] = []; + let offset: number | null = 0; + while (offset !== null) { + const paged = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { + kind: "retained-evidence", + evidence_id: summary.parent_evidence_id, + }, + view: { kind: "macho", facet, offset, limit: 16 }, + }, + }); + expect(paged.isError, JSON.stringify(paged.content)).not.toBe(true); + const page = evidenceOf(pageSchema).parse( + paged.structuredContent, + ).normalized_result; + rows.push(...page.item); + offset = page.coverage.next_offset; + } + expect(rows, facet).toEqual( + facet === "provenance" + ? raw.provenance + : z.object({ items: z.array(z.unknown()) }).parse(raw[facet]) + .items, + ); + } + + const wrongKind = await client.callTool({ + name: "inspect_analysis_view", + arguments: { + source: { + kind: "retained-evidence", + evidence_id: summary.parent_evidence_id, + }, + view: { kind: "wasm", facet: "exports" }, + }, + }); + expect(wrongKind.isError).toBe(true); + expect(JSON.stringify(wrongKind.content)).toContain( + "Mach-O inspection supports summary and macho views.", + ); + }, + ); + }, +); + +mcpTest( + "refuses summary delivery before analysis when the server retains no Evidence", + async ({ mcp, onTestFinished }) => { + const target = join( + await createTestTempDirectory("rea-summary-preflight-"), + "tool", + ); + await writeFile(target, thinMach(0xfeedfacf, 0x0100000c)); + const executed: string[] = []; + const session = createTestBinarySession(() => ({ + execute: (operation) => { + executed.push(operation); + return Promise.resolve(observed(null)); + }, + close: () => Promise.resolve(ok(null)), + })); + onTestFinished(async () => { + await session.close(); + }); + const opened = await session.open(target); + if (!opened.ok) throw opened.error; + const client = await mcp.connect( + createServer({ kind: "fixed", analysis: session }), + ); + const refused = []; + for (const name of ["inspect_macho", "inspect_artifact"]) + refused.push( + await client.callTool({ name, arguments: { detail: "summary" } }), + ); + // Neither analysis ran only to be discarded by the delivery refusal. + expect(executed.filter((operation) => operation !== "health")).toEqual([]); + for (const result of refused) + expect(parseMcpToolError(result)).toMatchObject({ + error: { + code: "capability_unavailable", + message: expect.stringContaining("does not retain Evidence"), + }, + }); + }, +); diff --git a/tests/boundary/mcp/packetCaptureMcp.test.ts b/tests/boundary/mcp/packetCaptureMcp.test.ts index e11b60d3e..a5acf1925 100644 --- a/tests/boundary/mcp/packetCaptureMcp.test.ts +++ b/tests/boundary/mcp/packetCaptureMcp.test.ts @@ -8,42 +8,53 @@ import { Ajv2020 } from "ajv/dist/2020.js"; import { createApplicationMcpHarness } from "../../fixtures/applicationMcpHarness.js"; import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; -it("advertises valid target-free packet capture schemas and actionable missing-tool diagnostics", async () => { - const harness = await createApplicationMcpHarness({ - serverOptions: { environment: {} }, - }); - onTestFinished(harness.close); - const tool = (await harness.client.listTools()).tools.find( - ({ name }) => name === "inspect_packet_capture", - ); - if (tool?.outputSchema === undefined) throw new Error("Capture tool missing"); - const ajv = new Ajv2020({ strict: false, validateFormats: false }); - const inputSchema: Record = tool.inputSchema; - const outputSchema: Record = tool.outputSchema; - expect(ajv.validateSchema(inputSchema)).toBe(true); - expect(ajv.validateSchema(outputSchema)).toBe(true); - const input = { - path: - process.platform === "win32" ? "C:\\recording.pcap" : "/recording.pcap", - fields: ["ip.addr"], - }; - expect(ajv.validate(inputSchema, input)).toBe(true); - expect(ajv.validate(inputSchema, { ...input, interface: "lo0" })).toBe(false); - const result = await harness.client.callTool({ - name: tool.name, - arguments: input, - }); - expect(parseMcpToolError(result)).toMatchObject({ - error: { - code: "capability_unavailable", - details: { - operation: tool.name, - reason: expect.stringContaining("REA_TSHARK_COMMAND"), +it.each(["inspect_packet_capture", "inspect_packet_fields"])( + "advertises valid target-free schemas and missing-tool diagnostics: %s", + async (name) => { + const harness = await createApplicationMcpHarness({ + serverOptions: { environment: {} }, + }); + onTestFinished(harness.close); + const tool = (await harness.client.listTools()).tools.find( + (tool) => tool.name === name, + ); + if (tool?.outputSchema === undefined) + throw new Error("Capture tool missing"); + const ajv = new Ajv2020({ strict: false, validateFormats: false }); + const inputSchema: Record = tool.inputSchema; + const outputSchema: Record = tool.outputSchema; + expect(ajv.validateSchema(inputSchema)).toBe(true); + expect(ajv.validateSchema(outputSchema)).toBe(true); + const input = + name === "inspect_packet_fields" + ? { query: "usb" } + : { + path: + process.platform === "win32" + ? "C:\\recording.pcap" + : "/recording.pcap", + fields: ["ip.addr"], + }; + expect(ajv.validate(inputSchema, input)).toBe(true); + expect(ajv.validate(inputSchema, { ...input, interface: "lo0" })).toBe( + false, + ); + const result = await harness.client.callTool({ + name: tool.name, + arguments: input, + }); + expect(parseMcpToolError(result)).toMatchObject({ + error: { + code: "capability_unavailable", + details: { + operation: tool.name, + reason: expect.stringContaining("REA_TSHARK_COMMAND"), + }, }, - }, - }); - await harness.client.ping(); -}); + }); + await harness.client.ping(); + }, +); it.each(["cancelled", "cleanup"])( "retains completed Evidence after %s failure", @@ -78,6 +89,9 @@ it.each(["cancelled", "cleanup"])( }, ); const packetCapture = new PacketCaptureService({ + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, inspect: async () => err(failure), close: async () => {}, }); @@ -120,6 +134,9 @@ it.each(["cancelled", "cleanup"])( it("rejects oversized selector expansion through the MCP boundary before invoking the provider", async () => { let calls = 0; const packetCapture = new PacketCaptureService({ + inspectFields: async () => { + throw new Error("Unexpected field discovery call"); + }, inspect: async () => { calls++; return err(new AnalysisCancelledError("inspect_packet_capture")); diff --git a/tests/boundary/mcp/pcapMcp.test.ts b/tests/boundary/mcp/pcapMcp.test.ts new file mode 100644 index 000000000..d3a6d203d --- /dev/null +++ b/tests/boundary/mcp/pcapMcp.test.ts @@ -0,0 +1,118 @@ +import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; +import { expect, it, onTestFinished } from "vitest"; + +import type { PcapAnalysisPort } from "../../../src/application/pcap/PcapAnalysisPort.js"; +import { createAnalysisExecution } from "../../../src/application/AnalysisProvider.js"; +import { assertAdvertisedMcpContracts } from "./mcpContractHarness.js"; +import { parseEvidence } from "../../../src/domain/evidence.js"; +import { ok } from "../../../src/domain/result.js"; +import { createServer } from "../../../src/server/createServer.js"; +import { createTestBinarySession } from "../../fixtures/binarySession.js"; + +const identity = { id: "pcap", name: "Packet capture analysis", version: null }; + +const clientIdentity = { + tshark_command: "/usr/bin/tshark", + tshark_source: "path", + tshark_version: "TShark (Wireshark) 4.6.6", + capinfos_command: "/usr/bin/capinfos", + capinfos_source: "path", + capinfos_version: "Capinfos (Wireshark) 4.6.6", +}; + +it("advertises exact valid pcap schemas and records inline evidence through MCP", async () => { + const provider: PcapAnalysisPort = { + async inspectAvailability() { + return { status: "available", code: null, reason: null, diagnostics: {} }; + }, + async close() {}, + async execute(request) { + if (request.operation === "inspect_pcap_client") + return ok( + createAnalysisExecution({ client: clientIdentity }, identity), + ); + return ok( + createAnalysisExecution( + { + client: clientIdentity, + target: { + path: "/captures/session.pcap", + bytes: 23279, + sha256: "a".repeat(64), + }, + file_type: "Wireshark/tcpdump/... - pcap", + encapsulation: "Linux cooked-mode capture v2", + packet_count: 50, + capture_start: "2026-10-11 14:13:40.608505", + capture_end: "2026-10-11 14:13:40.981978", + capture_duration_seconds: 0.373473, + snapshot_length: 262144, + endpoints: [ + { address: "192.168.1.100", port: null, packet_count: 30 }, + { address: "8.8.8.8", port: 53, packet_count: 5 }, + ], + endpoint_count: 2, + dns_queries: [ + { + query: "example.com", + response_addresses: ["93.184.216.34"], + response_address_count: 1, + }, + ], + dns_query_count: 1, + tls_sni_values: ["example.com"], + tls_sni_count: 1, + protocol_distribution: [ + { protocol: "ip:tcp:tls", packet_count: 25 }, + { protocol: "ip:udp:dns", packet_count: 5 }, + ], + protocol_count: 2, + http_request_uris: ["http://example.com/api"], + http_request_uri_count: 1, + http_uri_redaction_count: 0, + unattributed_dns_addresses: [], + unattributed_dns_address_count: 0, + unattributed_dns_packet_count: 0, + coverage: "complete", + }, + identity, + ), + ); + }, + }; + const session = createTestBinarySession(() => { + throw new Error("deep provider must not start"); + }); + const server = createServer( + { kind: "session", session }, + { pcapAnalysis: provider }, + ); + onTestFinished(() => server.close()); + const [clientTransport, serverTransport] = + InMemoryTransport.createLinkedPair(); + await server.connect(serverTransport); + const client = new Client({ name: "pcap-boundary", version: "0.0.0" }); + onTestFinished(() => client.close()); + await client.connect(clientTransport); + + const { tools } = await client.listTools(); + assertAdvertisedMcpContracts( + ["inspect_pcap_client", "inspect_pcap_capture"], + tools, + ); + + const inspected = await client.callTool({ + name: "inspect_pcap_capture", + arguments: { path: "/captures/session.pcap" }, + }); + expect(inspected.isError).not.toBe(true); + const text = (inspected.content as { readonly text?: string }[]) + .map((part) => part.text ?? "") + .join(""); + const evidence = parseEvidence(JSON.parse(text)); + expect(evidence.normalized_result).toMatchObject({ + packet_count: 50, + tls_sni_values: ["example.com"], + coverage: "complete", + }); +}); diff --git a/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts b/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts index 69fdc3944..bda4672de 100644 --- a/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts +++ b/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts @@ -252,6 +252,56 @@ it("reports CLI trace specification issues like the MCP trace_spec input", async }); }); +it("rejects a deep trace cycle as an input error through CLI and MCP", async () => { + const events = Array.from({ length: 6000 }, (_, index) => ({ + id: `e${String(index)}`, + source: "lifecycle", + exact: { marker: index }, + })); + const trace = { + events, + language: { + kind: "partial_order", + happens_before: events.map((event, index) => ({ + before: event.id, + after: events[(index + 1) % events.length]!.id, + })), + not_before: events.map((event, index) => ({ + event: event.id, + anchor: events[(index + 1) % events.length]!.id, + })), + unordered_groups: [{ events: events.map(({ id }) => id) }], + }, + }; + const issue = { + path: ["trace_spec", "language"], + message: "happens-before graph must be acyclic", + }; + const capture = captureEvidence("left"); + const root = await createTestTempDirectory("rea-process-trace-cycle-"); + const capturePath = join(root, "capture.json"); + const specPath = join(root, "spec.json"); + await writeFile(capturePath, JSON.stringify(capture)); + await writeFile(specPath, JSON.stringify(trace)); + expect( + await compareProcessEvidenceFiles(capturePath, capturePath, specPath), + ).toMatchObject({ + code: "invalid_request", + details: { issues: [issue] }, + }); + + const client = await connect(); + const response = await client.callTool({ + name: "compare_process_captures", + arguments: { left: capture, right: capture, trace_spec: trace }, + }); + expect(response.isError).toBe(true); + expect(response.content).toEqual([ + { type: "text", text: expect.stringContaining(issue.message) }, + ]); + await client.ping(); +}); + it("names the side and constraint when Evidence is not a usable capture", async () => { const client = await connect(); const capture = captureEvidence("right"); diff --git a/tests/boundary/mcp/processEvidenceIdentityMcp.test.ts b/tests/boundary/mcp/processEvidenceIdentityMcp.test.ts index fb20dd79b..993f1df69 100644 --- a/tests/boundary/mcp/processEvidenceIdentityMcp.test.ts +++ b/tests/boundary/mcp/processEvidenceIdentityMcp.test.ts @@ -309,7 +309,9 @@ it("separately rejects a tampered digest before admission to any consumer or ses }; const digestMismatch = /semantic identifier does not match/u; expect(() => parseEvidence(tampered)).toThrow(digestMismatch); - expect(() => findChangedBehavior([tampered])).toThrow(digestMismatch); + expect(() => findChangedBehavior({ comparisons: [tampered] })).toThrow( + digestMismatch, + ); expect(() => correlateStaticAndRuntime(correlationInput(tampered))).toThrow( digestMismatch, ); @@ -336,6 +338,19 @@ it("separately rejects a tampered digest before admission to any consumer or ses } }); +it("maps malformed changed-behavior Evidence to an invalid request before closure lookup", async () => { + const { client, comparison } = await connectedComparison(); + const malformed = { ...comparison, evidence_links: undefined } as unknown; + const response = await client.callTool({ + name: "find_changed_behavior", + arguments: { comparisons: [malformed] }, + }); + expect(response.isError).toBe(true); + expect(parseMcpToolError(response)).toMatchObject({ + error: { code: "invalid_request" }, + }); +}); + it("keeps withheld ownership unknown through CLI and MCP comparison", async () => { const { client, right } = await connectedComparison(); const left = captureEvidence("left", { diff --git a/tests/boundary/mcp/processTraceAdaptersParity.test.ts b/tests/boundary/mcp/processTraceAdaptersParity.test.ts index cb7c1439c..d8c9b6173 100644 --- a/tests/boundary/mcp/processTraceAdaptersParity.test.ts +++ b/tests/boundary/mcp/processTraceAdaptersParity.test.ts @@ -9,76 +9,16 @@ import { createTestBinarySession } from "../../fixtures/binarySession.js"; import type { AnalysisClient } from "../../../src/application/AnalysisProvider.js"; import { compareProcessEvidenceFiles } from "../../../src/application/process/ProcessCli.js"; import { PROCESS_PROVIDER } from "../../../src/domain/process/processEvidenceProvider.js"; -import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCaptureExample.js"; +import { processTraceCaptureFixture } from "../../../src/domain/process/processCapture.fixture.js"; import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js"; import { jsonValueSchema } from "../../../src/domain/jsonValue.js"; -import type { ProcessTraceSpecification } from "../../../src/domain/process/processTraceSpecification.js"; import { createServer } from "../../../src/server/createServer.js"; import { observed as ok } from "../../fixtures/analysisExecution.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; const resources: Array<{ close(): Promise }> = []; const temporaryRoots: string[] = []; -const beforeCheckpoint = { - name: "before", - at_ms: 0, - files: [], - effects: [], - truncated: false, -}; -const afterCheckpoint = { - name: "after_settlement", - at_ms: 50, - files: [], - effects: [], - truncated: false, -}; -const capture = { - ...EMPTY_PROCESS_CAPTURE_EXAMPLE, - event_journal: [ - { capture_order: 0, collection: "filesystem_checkpoints", index: 0 }, - { capture_order: 1, collection: "lifecycle", index: 0 }, - { capture_order: 2, collection: "lifecycle", index: 1 }, - { capture_order: 3, collection: "filesystem_checkpoints", index: 1 }, - ], -} as const; -const traceSpecification: ProcessTraceSpecification = { - events: [ - { - id: "before", - source: "filesystem", - exact: beforeCheckpoint, - cardinality: { kind: "required" }, - }, - { - id: "exit", - source: "lifecycle", - exact: { event: "exit", ...capture.exit }, - cardinality: { kind: "required" }, - }, - { - id: "settlement", - source: "lifecycle", - exact: { event: "settlement", ...capture.settlement }, - cardinality: { kind: "required" }, - }, - { - id: "after", - source: "filesystem", - exact: afterCheckpoint, - cardinality: { kind: "required" }, - }, - ], - language: { - kind: "finite_traces", - variants: [ - { - id: "normal", - trace: ["before", "exit", "settlement", "after"], - }, - ], - }, -}; +const { capture, traceSpecification } = processTraceCaptureFixture(); const captureEvidence = (side: "left" | "right") => createEvidence(undefined, PROCESS_PROVIDER, { diff --git a/tests/boundary/mcp/reconstructionCoverageMcp.test.ts b/tests/boundary/mcp/reconstructionCoverageMcp.test.ts index cb3605d14..1e167b8b0 100644 --- a/tests/boundary/mcp/reconstructionCoverageMcp.test.ts +++ b/tests/boundary/mcp/reconstructionCoverageMcp.test.ts @@ -3,7 +3,10 @@ import { ok as resultOk } from "../../../src/domain/result.js"; import { Client, InMemoryTransport } from "@modelcontextprotocol/client"; import { describe, expect, it } from "vitest"; -import { completeReconstructionCoverageData } from "../../../src/domain/reconstructionCoverage.fixture.js"; +import { + completeReconstructionCoverageData, + reconstructionCoverageEvidenceId, +} from "../../../src/domain/reconstructionCoverage.fixture.js"; import { createReconstructionCoverageData } from "../../../src/domain/reconstructionCoverage.js"; import { createTestBinarySession } from "../../fixtures/binarySession.js"; import { createServer } from "../../../src/server/createServer.js"; @@ -36,6 +39,42 @@ describe("reconstruction coverage MCP", () => { boundary_id: boundaryId, summary: { reasons: 0 }, }); + const coverage = currentFixtureCoverage(boundaryId); + const latest = coverage.verifier_results[0]; + if (latest === undefined) + throw new Error("Expected fixture verifier result"); + const ambiguous = await client.callTool({ + name: "evaluate_reconstruction_coverage", + arguments: { + coverage: createReconstructionCoverageData({ + ...coverage, + verifier_results: [ + latest, + { + ...latest, + status: "fail", + evidence_ids: [reconstructionCoverageEvidenceId("1")], + }, + ], + }), + boundary_id: boundaryId, + }, + }); + expect(ambiguous.isError).not.toBe(true); + expect(ambiguous.structuredContent).toMatchObject({ + status: "unknown", + boundary_id: boundaryId, + reasons: [ + expect.objectContaining({ + code: "verifier-result-ambiguous", + subject_id: "claim.cli.help", + }), + ], + evidence_ids: expect.arrayContaining([ + reconstructionCoverageEvidenceId("3"), + reconstructionCoverageEvidenceId("1"), + ]), + }); const unknown = await client.callTool({ name: "evaluate_reconstruction_coverage", arguments: { diff --git a/tests/boundary/mcp/serverLifecycleMcp.test.ts b/tests/boundary/mcp/serverLifecycleMcp.test.ts index c841e08ed..cdec09a3e 100644 --- a/tests/boundary/mcp/serverLifecycleMcp.test.ts +++ b/tests/boundary/mcp/serverLifecycleMcp.test.ts @@ -34,6 +34,9 @@ import { } from "../../support/workspace/workspaceFixture.js"; import { z } from "zod"; import { createDeferred } from "../../fixtures/binarySession.js"; +import { GoBinaryService } from "../../../src/application/go/GoBinaryService.js"; +import { WebNetworkCaptureService } from "../../../src/application/WebNetworkCaptureService.js"; +import { AnalysisUnsupportedTargetError } from "../../../src/domain/analysisErrorCore.js"; const resources: Array<{ close(): Promise }> = []; @@ -334,6 +337,68 @@ it("awaits SQLite cleanup and retries its retained owner after failed server shu expect(attempts).toBe(2); }); +it("closes the bound Go and web-capture services and retries failed shutdown", async () => { + let goCalls = 0; + let goCloseAttempts = 0; + let captureCloseAttempts = 0; + let cleanupAllowed = false; + const goBinary = new GoBinaryService({ + identity: { id: "go-fixture", name: "Go fixture", version: "1" }, + inspect: async ({ path }) => { + goCalls += 1; + return err( + new AnalysisUnsupportedTargetError( + "inspect_go_binary", + path, + "fixture rejection", + ), + ); + }, + close: async () => { + goCloseAttempts += 1; + if (!cleanupAllowed) throw new Error("Go cleanup refused"); + }, + }); + const webNetworkCapture = new WebNetworkCaptureService({ + inspect: async () => { + throw new Error("No capture inspection requested"); + }, + close: async () => { + captureCloseAttempts += 1; + if (!cleanupAllowed) throw new Error("Capture cleanup refused"); + }, + }); + const server = createServer( + { kind: "fixed", analysis: { execute: async () => ok(null) } }, + { goBinary, webNetworkCapture }, + ); + const client = new Client({ name: "bound-service-lifecycle", version: "1" }); + const [clientTransport, serverTransport] = + InMemoryTransport.createLinkedPair(); + resources.push(client, server); + try { + await server.connect(serverTransport); + await client.connect(clientTransport); + const result = await client.callTool({ + name: "inspect_go_binary", + arguments: { path: "/tmp/go-fixture" }, + }); + expect(result.isError).toBe(true); + expect(goCalls).toBe(1); + + await expect(server.close()).rejects.toBeInstanceOf(AggregateError); + expect(goCloseAttempts).toBe(1); + expect(captureCloseAttempts).toBe(1); + + cleanupAllowed = true; + await server.close(); + expect(goCloseAttempts).toBe(2); + expect(captureCloseAttempts).toBe(2); + } finally { + cleanupAllowed = true; + } +}); + afterEach(async () => { await Promise.all( resources.splice(0).map(async (resource) => resource.close()), diff --git a/tests/boundary/mcp/serverUnknownsMcp.test.ts b/tests/boundary/mcp/serverUnknownsMcp.test.ts index 0a27324ec..e39ce2aec 100644 --- a/tests/boundary/mcp/serverUnknownsMcp.test.ts +++ b/tests/boundary/mcp/serverUnknownsMcp.test.ts @@ -281,7 +281,7 @@ it("pages filtered unknown heads through the public MCP contract", async () => { supporting_evidence_ids: [], contradicting_evidence_ids: [], }); - expect(result.ok).toBe(true); + if (!result.ok) throw result.error; } const defaultPage = structured( @@ -372,12 +372,11 @@ it("pages filtered unknown heads through the public MCP contract", async () => { .result as typeof defaultPage; expect(first).toMatchObject({ total: 3, offset: 0, next_offset: 2 }); expect(first.items).toHaveLength(2); - const second = structured( - await client.callTool({ - ...request, - arguments: { ...request.arguments, offset: first.next_offset ?? 0 }, - }), - ).result as typeof defaultPage; + const secondResponse = await client.callTool({ + ...request, + arguments: { ...request.arguments, offset: first.next_offset ?? 0 }, + }); + const second = structured(secondResponse).result as typeof defaultPage; expect(second).toMatchObject({ total: 3, offset: 2, next_offset: null }); expect(second.items).toHaveLength(1); expect( @@ -389,7 +388,7 @@ it("pages filtered unknown heads through the public MCP contract", async () => { ); expect( toolContract("list_unknowns").outputSchema.safeParse( - (await client.callTool(request)).structuredContent, + secondResponse.structuredContent, ).success, ).toBe(true); diff --git a/tests/boundary/mcp/serverWorkflowMcp.test.ts b/tests/boundary/mcp/serverWorkflowMcp.test.ts index c72fca5cb..f25027b2a 100644 --- a/tests/boundary/mcp/serverWorkflowMcp.test.ts +++ b/tests/boundary/mcp/serverWorkflowMcp.test.ts @@ -122,11 +122,18 @@ it("advertises the complete currently available inventory with a session", async const listed = await client.listTools(); const names = listed.tools.map((t) => t.name); + const sessionTool = listed.tools.find( + ({ name }) => name === "binary_session", + ); + if (sessionTool === undefined) + throw new Error("Missing advertised binary_session tool"); + // Validate this reply with its current advertised schema. The SDK otherwise + // builds output validators for the entire catalog on the first cached call. const status = structured( - await client.callTool({ - name: "binary_session", - arguments: {}, - }), + await client.callTool( + { name: "binary_session", arguments: {} }, + { toolDefinition: sessionTool }, + ), ); const inventory = expandToolAvailability( toolContract("binary_session").outputSchema.parse(status).result diff --git a/tests/boundary/mcp/signalRecordingMcp.test.ts b/tests/boundary/mcp/signalRecordingMcp.test.ts index ecabfd8e5..edd74a2bf 100644 --- a/tests/boundary/mcp/signalRecordingMcp.test.ts +++ b/tests/boundary/mcp/signalRecordingMcp.test.ts @@ -8,41 +8,51 @@ import { Ajv2020 } from "ajv/dist/2020.js"; import { createApplicationMcpHarness } from "../../fixtures/applicationMcpHarness.js"; import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; -it("advertises valid target-free signal decoding schemas and actionable missing-tool diagnostics", async () => { - const harness = await createApplicationMcpHarness({ - serverOptions: { environment: {} }, - }); - onTestFinished(harness.close); - const tool = (await harness.client.listTools()).tools.find( - ({ name }) => name === "decode_signal_recording", - ); - if (tool?.outputSchema === undefined) throw new Error("Signal tool missing"); - const ajv = new Ajv2020({ strict: false, validateFormats: false }); - const inputSchema: Record = tool.inputSchema; - const outputSchema: Record = tool.outputSchema; - expect(ajv.validateSchema(inputSchema)).toBe(true); - expect(ajv.validateSchema(outputSchema)).toBe(true); - const input = { - path: process.platform === "win32" ? "C:\\recording.vcd" : "/recording.vcd", - decoders: "uart", - }; - expect(ajv.validate(inputSchema, input)).toBe(true); - expect(ajv.validate(inputSchema, { ...input, driver: "demo" })).toBe(false); - const result = await harness.client.callTool({ - name: tool.name, - arguments: input, - }); - expect(parseMcpToolError(result)).toMatchObject({ - error: { - code: "capability_unavailable", - details: { - operation: tool.name, - reason: expect.stringContaining("REA_SIGROK_COMMAND"), +it.each(["decode_signal_recording", "inspect_signal_decoders"])( + "advertises valid target-free schemas and missing-tool diagnostics: %s", + async (name) => { + const harness = await createApplicationMcpHarness({ + serverOptions: { environment: {} }, + }); + onTestFinished(harness.close); + const tool = (await harness.client.listTools()).tools.find( + (tool) => tool.name === name, + ); + if (tool?.outputSchema === undefined) + throw new Error("Signal tool missing"); + const ajv = new Ajv2020({ strict: false, validateFormats: false }); + const inputSchema: Record = tool.inputSchema; + const outputSchema: Record = tool.outputSchema; + expect(ajv.validateSchema(inputSchema)).toBe(true); + expect(ajv.validateSchema(outputSchema)).toBe(true); + const input = + name === "inspect_signal_decoders" + ? { query: "uart" } + : { + path: + process.platform === "win32" + ? "C:\\recording.vcd" + : "/recording.vcd", + decoders: "uart", + }; + expect(ajv.validate(inputSchema, input)).toBe(true); + expect(ajv.validate(inputSchema, { ...input, driver: "demo" })).toBe(false); + const result = await harness.client.callTool({ + name: tool.name, + arguments: input, + }); + expect(parseMcpToolError(result)).toMatchObject({ + error: { + code: "capability_unavailable", + details: { + operation: tool.name, + reason: expect.stringContaining("REA_SIGROK_COMMAND"), + }, }, - }, - }); - await harness.client.ping(); -}); + }); + await harness.client.ping(); + }, +); it.each(["cancelled", "cleanup"])( "retains completed Evidence after %s failure", @@ -77,6 +87,9 @@ it.each(["cancelled", "cleanup"])( }, ); const signalRecording = new SignalRecordingService({ + inspectDecoders: async () => { + throw new Error("Unexpected discovery call"); + }, decode: async () => err(failure), close: async () => {}, }); diff --git a/tests/boundary/mcp/wasmArtifactMcp.test.ts b/tests/boundary/mcp/wasmArtifactMcp.test.ts index 49c7ad762..003a37cba 100644 --- a/tests/boundary/mcp/wasmArtifactMcp.test.ts +++ b/tests/boundary/mcp/wasmArtifactMcp.test.ts @@ -213,6 +213,31 @@ it("advertises exact valid schemas and records inline WASM interface evidence wi expect(close).toHaveBeenCalled(); }); +it("rejects a WASM provider response with a non-file subject before recording Evidence", async () => { + const value = wasmArtifactFixture(); + const execution = wasmArtifactExecution(value); + const malformed = { + ...execution, + subject: { ...execution.subject, format: "elf" }, + } as unknown as typeof execution; + const harness = await createApplicationMcpHarness({ + serverOptions: { + wasmArtifact: new WasmArtifactService({ + close: () => Promise.resolve(), + inspect: () => Promise.resolve(ok(malformed)), + }), + }, + }); + onTestFinished(harness.close); + const before = harness.session.exportEvidenceBundle().records.length; + const response = await harness.client.callTool({ + name: "inspect_wasm_artifact", + arguments: { path: value.artifact.path }, + }); + expect(parseMcpToolError(response).error.code).toBe("unreadable_output"); + expect(harness.session.exportEvidenceBundle().records).toHaveLength(before); +}); + it("reads an oversized completed WASM result through its reported retained reference", async () => { const text = "(module)\n" + ";;😀\n" + " ".repeat(6 * 1024 * 1024); const value = { diff --git a/tests/boundary/native/PwndbgCoreContext.test.ts b/tests/boundary/native/PwndbgCoreContext.test.ts index e8f007a9b..d38b01ac3 100644 --- a/tests/boundary/native/PwndbgCoreContext.test.ts +++ b/tests/boundary/native/PwndbgCoreContext.test.ts @@ -2,6 +2,7 @@ import { access } from "node:fs/promises"; import { join } from "node:path"; import { expect, it, onTestFinished } from "vitest"; import { AnalysisCancelledError } from "../../../src/domain/analysisErrorCore.js"; +import { ArtifactResourceScope } from "../../../src/artifacts/ArtifactResourceScope.js"; import { createTestWorkspace, removeTestWorkspace, @@ -40,6 +41,7 @@ it.each(["pre-aborted", "aborted-during-probe"] as const)( REA_PWNDBG_VENV_PATH: join(workspace.root, "missing-venv"), }, rootPath: workspace.root, + resources: new ArtifactResourceScope(), diagnostics, options: { signal: controller.signal }, probePath, diff --git a/tests/boundary/native/pwntoolsArtifactCleanup.test.ts b/tests/boundary/native/pwntoolsArtifactCleanup.test.ts new file mode 100644 index 000000000..82760cfd2 --- /dev/null +++ b/tests/boundary/native/pwntoolsArtifactCleanup.test.ts @@ -0,0 +1,147 @@ +import { mkdtemp, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { expect, it, vi } from "vitest"; +import { z } from "zod"; + +const closeState = vi.hoisted(() => ({ + fail: false, + failOnce: false, + opened: 0, + closes: 0, +})); + +vi.mock("node:fs/promises", async (importOriginal) => { + const fs = await importOriginal(); + return { + ...fs, + open: async (...args: Parameters) => { + const handle = await fs.open(...args); + closeState.opened++; + const close = handle.close.bind(handle); + handle.close = async () => { + closeState.closes++; + if (closeState.fail || closeState.failOnce) { + closeState.failOnce = false; + throw new Error("injected stable artifact close failure"); + } + return close(); + }; + return handle; + }, + }; +}); + +import { PwntoolsDecoder } from "../../../src/native/pwntools/PwntoolsDecoder.js"; +import { PWNTOOLS_PROVIDER_IDENTITY } from "../../../src/native/pwntools/PwntoolsRelease.js"; +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; + +const makeDecoder = () => + new PwntoolsDecoder( + { + identity: PWNTOOLS_PROVIDER_IDENTITY, + operation: "test_pwntools_artifact_read", + bridge: new URL("file:///unused-bridge.py"), + payloadSchema: z.string(), + project: () => { + throw new Error("input read should fail before decoder launch"); + }, + }, + { REA_PWNTOOLS_PYTHON: process.execPath }, + undefined, + async () => { + throw new Error("runtime should not be created for failed input read"); + }, + ); + +const emulateSupportedHost = async ( + run: () => Promise, +): Promise => { + const platform = Object.getOwnPropertyDescriptor(process, "platform"); + const arch = Object.getOwnPropertyDescriptor(process, "arch"); + Object.defineProperty(process, "platform", { ...platform, value: "linux" }); + Object.defineProperty(process, "arch", { ...arch, value: "x64" }); + try { + await run(); + } finally { + if (platform !== undefined) + Object.defineProperty(process, "platform", platform); + if (arch !== undefined) Object.defineProperty(process, "arch", arch); + } +}; + +it("reports the read failure without stale incomplete-cleanup state when close retry succeeds", async () => + emulateSupportedHost(async () => { + const root = await mkdtemp(join(tmpdir(), "rea-pwntools-close-retry-")); + const path = join(root, "selected.bin"); + await writeFile(path, "selected evidence"); + closeState.fail = false; + closeState.failOnce = true; + closeState.opened = 0; + closeState.closes = 0; + const decoder = makeDecoder(); + try { + const result = await decoder.inspect({ path }); + expect(result.ok).toBe(false); + if (result.ok) throw new Error("Injected close failure was not returned"); + expect(result.error.cleanupIncomplete).toBe(false); + expect(projectAnalysisError(result.error).code).not.toBe( + "cleanup_incomplete", + ); + expect(result.error.cause).toMatchObject({ + cleanup: { + resources: [path], + reason: expect.stringContaining( + "injected stable artifact close failure", + ), + }, + }); + expect(closeState.closes).toBeGreaterThanOrEqual(2); + } finally { + closeState.fail = false; + closeState.failOnce = false; + await decoder.close(); + await rm(root, { recursive: true, force: true }); + } + })); + +it("retains a persistent failed input descriptor and refuses the next acquisition", async () => + emulateSupportedHost(async () => { + const root = await mkdtemp(join(tmpdir(), "rea-pwntools-held-close-")); + const path = join(root, "selected.bin"); + await writeFile(path, "selected evidence"); + closeState.fail = true; + closeState.failOnce = false; + closeState.opened = 0; + closeState.closes = 0; + const decoder = makeDecoder(); + try { + const first = await decoder.inspect({ path }); + expect(first.ok).toBe(false); + if (first.ok) + throw new Error("Persistent close failure was not returned"); + expect(projectAnalysisError(first.error).code).toBe("cleanup_incomplete"); + const openedAfterFailure = closeState.opened; + + const retry = await decoder.inspect({ path }); + expect(retry.ok).toBe(false); + if (retry.ok) throw new Error("Retained descriptor was not retried"); + expect(projectAnalysisError(retry.error).code).toBe("cleanup_incomplete"); + expect(closeState.opened).toBe(openedAfterFailure); + + await expect(decoder.close()).rejects.toMatchObject({ + cleanupIncomplete: true, + }); + closeState.fail = false; + await decoder.close(); + } finally { + closeState.fail = false; + closeState.failOnce = false; + try { + await decoder.close(); + } catch { + // The test already asserts persistent cleanup failure before releasing it. + } + await rm(root, { recursive: true, force: true }); + } + })); diff --git a/tests/boundary/pcap/pcapCommand.test.ts b/tests/boundary/pcap/pcapCommand.test.ts new file mode 100644 index 000000000..cda8dbf77 --- /dev/null +++ b/tests/boundary/pcap/pcapCommand.test.ts @@ -0,0 +1,53 @@ +import { setTimeout as delay } from "node:timers/promises"; +import { expect, it, onTestFinished, vi } from "vitest"; +import { runPcapCommand } from "../../../src/pcap/PcapCommand.js"; +import * as ownership from "../../../src/process/ProcessOwnershipObservation.js"; + +it("does not spend the tool execution deadline preparing native ownership", async () => { + const original = ownership.prepareProcessOwnershipInspection; + let entered!: () => void; + let release!: () => void; + const preparing = new Promise((resolve) => { + entered = resolve; + }); + const gate = new Promise((resolve) => { + release = resolve; + }); + let first = true; + const prepare = vi + .spyOn(ownership, "prepareProcessOwnershipInspection") + .mockImplementation(async (signal) => { + await original(signal); + if (first) { + first = false; + entered(); + await gate; + } + }); + onTestFinished(() => { + prepare.mockRestore(); + release(); + }); + const pending = runPcapCommand({ + operation: "inspect_pcap_client", + command: process.execPath, + arguments: ["--version"], + limits: { timeoutMs: 1000, maxOutputBytes: 1024 }, + environment: {}, + signal: undefined, + retain: (owner) => { + onTestFinished(async () => { + expect((await owner.stop()).status).not.toBe("incomplete"); + }); + }, + }).then( + (value) => ({ ok: true as const, value }), + (error: unknown) => ({ ok: false as const, error }), + ); + await preparing; + await delay(1100); + release(); + const result = await pending; + if (!result.ok) throw result.error; + expect(result.value.stdout.trim()).toBe(process.version); +}); diff --git a/tests/boundary/pcap/pcapProvider.test.ts b/tests/boundary/pcap/pcapProvider.test.ts new file mode 100644 index 000000000..fcb299ade --- /dev/null +++ b/tests/boundary/pcap/pcapProvider.test.ts @@ -0,0 +1,533 @@ +import { createHash } from "node:crypto"; +import { watch } from "node:fs"; +import { chmod, readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { expect, onTestFinished, test, vi } from "vitest"; + +import { PcapProvider } from "../../../src/pcap/PcapProvider.js"; +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import { + pcapResultSchemas, + type PcapRequest, +} from "../../../src/domain/pcap/pcapAnalysis.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { holdFirstFileRead } from "../../support/holdFirstFileRead.js"; +import { PrivateRuntimeRoot } from "../../../src/process/PrivateRuntimeRoot.js"; + +const it = test.skipIf(process.platform !== "linux"); + +const CAPINFOS_OUTPUT = [ + "File name: /work/capture.pcap", + "File type: Wireshark/tcpdump/... - pcap", + "File encapsulation: Ethernet", + "Packet size limit: file hdr: 262144 bytes", + "Number of packets: 3", + "Capture duration: 0.123 seconds", +].join("\n"); + +const TSHARK_JSON = JSON.stringify([ + { + _source: { + layers: { + "frame.number": ["1"], + "frame.protocols": ["eth:ethertype:ip:udp:dns"], + "ip.src": ["192.168.1.100"], + "ip.dst": ["8.8.8.8"], + "dns.qry.name": ["api.example.com"], + "dns.flags.response": ["1"], + "dns.a": ["93.184.216.34"], + }, + }, + }, + { + _source: { + layers: { + "frame.number": ["2"], + "frame.protocols": ["eth:ethertype:ip:tcp:tls"], + "ip.src": ["192.168.1.100"], + "ip.dst": ["93.184.216.34"], + "tls.handshake.extensions_server_name": ["api.example.com"], + }, + }, + }, + { + _source: { + layers: { + "frame.number": ["3"], + "frame.protocols": ["eth:ethertype:ip:tcp:http"], + "ip.src": ["192.168.1.100"], + "ip.dst": ["93.184.216.34"], + "http.request.full_uri": ["http://api.example.com/v1/data"], + }, + }, + }, +]); + +const writeStubTools = async ( + root: string, + options: { readonly failCapinfos?: boolean } = {}, +): Promise<{ tshark: string; capinfos: string }> => { + const tshark = join(root, "tshark"); + const capinfos = join(root, "capinfos"); + await writeFile( + tshark, + `#!/bin/sh +if [ "$1" = "--version" ]; then printf 'TShark (Wireshark) 4.6.6-stub\\n'; exit 0; fi +[ "$1" = "-n" ] && [ "$2" = "-r" ] && [ "$4" = "-T" ] && [ "$5" = "json" ] || exit 2 +printf '%s' '${TSHARK_JSON.replace(/'/gu, "'\\''")}' +exit 0 +`, + { mode: 0o755 }, + ); + await writeFile( + capinfos, + `#!/bin/sh +if [ "$1" = "--version" ]; then printf 'Capinfos (Wireshark) 4.6.6-stub\\n'; exit 0; fi +[ "$1" = "-M" ] && [ "$2" = "--" ] && [ "$#" = "3" ] || exit 2 +if [ "${String(options.failCapinfos === true)}" = "true" ]; then + printf 'capinfos: The file is not a capture file' >&2; exit 1 +fi +printf '%s\\n' '${CAPINFOS_OUTPUT.replace(/'/gu, "'\\''")}' +exit 0 +`, + { mode: 0o755 }, + ); + await chmod(tshark, 0o755); + await chmod(capinfos, 0o755); + return { tshark, capinfos }; +}; + +const providerWith = async (options: { failCapinfos?: boolean } = {}) => { + const root = await createTestTempDirectory("rea-pcap-"); + const { tshark, capinfos } = await writeStubTools(root, options); + const provider = new PcapProvider({ + environment: { REA_TSHARK_COMMAND: tshark, REA_CAPINFOS_COMMAND: capinfos }, + }); + onTestFinished(() => provider.close()); + return { + provider, + root, + }; +}; + +const evidenceResult = async ( + provider: PcapProvider, + request: PcapRequest, +): Promise> => { + const result = await provider.execute(request); + if (!result.ok) throw new Error(result.error.message); + return pcapResultSchemas[request.operation].parse(result.value.result); +}; + +const captureFixture = async (root: string): Promise => { + const path = join(root, "capture.pcap"); + await writeFile(path, Buffer.from("pcap-fixture-bytes")); + return path; +}; + +it("inspects both tools without reading a capture", async () => { + const { provider } = await providerWith(); + const result = await evidenceResult(provider, { + operation: "inspect_pcap_client", + input: {}, + }); + expect(result.client).toMatchObject({ + tshark_source: "environment", + tshark_version: "TShark (Wireshark) 4.6.6-stub", + capinfos_source: "environment", + capinfos_version: "Capinfos (Wireshark) 4.6.6-stub", + }); +}); + +it("inspects a capture with endpoints, DNS, TLS SNI, and HTTP", async () => { + const { provider, root } = await providerWith(); + const path = await captureFixture(root); + const result = await evidenceResult(provider, { + operation: "inspect_pcap_capture", + input: { path }, + }); + expect(result.target).toMatchObject({ + path, + bytes: 18, + sha256: createHash("sha256").update("pcap-fixture-bytes").digest("hex"), + }); + expect(result.file_type).toBe("Wireshark/tcpdump/... - pcap"); + expect(result.packet_count).toBe(3); + expect(result.endpoints).toEqual( + expect.arrayContaining([ + { address: "192.168.1.100", port: null, packet_count: 3 }, + { address: "8.8.8.8", port: null, packet_count: 1 }, + ]), + ); + expect(result.dns_queries).toEqual([ + { + query: "api.example.com", + response_addresses: ["93.184.216.34"], + response_address_count: 1, + }, + ]); + expect(result.tls_sni_values).toEqual(["api.example.com"]); + expect(result.http_request_uris).toEqual(["http://api.example.com/v1/data"]); + expect(result.coverage).toBe("complete"); +}); + +it("reports a non-capture file as unsupported", async () => { + const { provider, root } = await providerWith({ failCapinfos: true }); + const failPath = join(root, "fail.pcap"); + await writeFile(failPath, "not a capture file"); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path: failPath }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "unsupported_target", + }); +}); + +it("reports a missing tshark binary as a capability gap", async () => { + const provider = new PcapProvider({ + environment: { REA_TSHARK_COMMAND: "/nonexistent/tshark" }, + }); + expect(await provider.inspectAvailability()).toMatchObject({ + status: "unavailable", + code: "executable_missing", + }); +}); + +it("rejects a capture that is not a readable file", async () => { + const { provider } = await providerWith(); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path: "/nonexistent/capture.pcap" }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "invalid_request", + }); +}); + +it("cancels before spawning anything", async () => { + const { provider, root } = await providerWith(); + await writeFile(join(root, "spawned"), ""); + const controller = new AbortController(); + controller.abort(); + const result = await provider.execute( + { + operation: "inspect_pcap_capture", + input: { path: "/some/capture.pcap" }, + }, + { signal: controller.signal }, + ); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "cancelled", + }); +}); + +it("reports relative configuration and missing capinfos as capability gaps", async () => { + const root = await createTestTempDirectory("rea-pcap-config-"); + const { tshark } = await writeStubTools(root); + for (const environment of [ + { REA_TSHARK_COMMAND: "relative/tshark" }, + { + REA_TSHARK_COMMAND: tshark, + REA_CAPINFOS_COMMAND: join(root, "missing-capinfos"), + }, + ]) { + const provider = new PcapProvider({ environment }); + onTestFinished(() => provider.close()); + expect((await provider.inspectAvailability()).status).toBe("unavailable"); + const result = await provider.execute({ + operation: "inspect_pcap_client", + input: {}, + }); + if (result.ok) throw new Error("expected unavailable tools"); + const projected = projectAnalysisError(result.error); + expect(projected.code).toBe("capability_unavailable"); + expect(projected.message).toContain( + "Supply Wireshark 4.x tshark and capinfos", + ); + } +}); + +it("names the prlimit selection when the Linux limiter is unusable", async () => { + const root = await createTestTempDirectory("rea-pcap-prlimit-"); + const tools = await writeStubTools(root); + const provider = new PcapProvider({ + environment: { + REA_TSHARK_COMMAND: tools.tshark, + REA_CAPINFOS_COMMAND: tools.capinfos, + REA_TSHARK_PRLIMIT_COMMAND: "relative/prlimit", + }, + }); + onTestFinished(() => provider.close()); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path: "/not-opened/capture.pcap" }, + }); + if (result.ok) throw new Error("expected an unusable limiter"); + const projected = projectAnalysisError(result.error); + expect(projected.code).toBe("capability_unavailable"); + expect(projected.message).toContain( + "(REA_TSHARK_PRLIMIT_COMMAND must be absolute.) Check that REA_TSHARK_PRLIMIT_COMMAND", + ); +}); + +const nodeTool = async ( + root: string, + name: string, + body: string, +): Promise => { + const path = join(root, name); + await writeFile( + path, + `#!/usr/bin/env -S ${process.execPath} --jitless --max-old-space-size=64\nconst fs = require('node:fs'); const crypto = require('node:crypto');\n${body}\n`, + { mode: 0o755 }, + ); + return path; +}; +const versionProbe = + "if (process.argv[2] === '--version') { console.log((process.argv[1].includes('capinfos') ? 'Capinfos' : 'TShark') + ' (Wireshark) 4.6.6-test'); process.exit(0); }"; + +it("refuses observations whose owned snapshot changed during dissection", async () => { + const root = await createTestTempDirectory("rea-pcap-mutated-"); + const { capinfos } = await writeStubTools(root); + const path = await captureFixture(root); + const before = await readFile(path); + const tshark = await nodeTool( + root, + "tshark.cjs", + `${versionProbe} +const selected = process.argv[process.argv.indexOf('-r') + 1]; +fs.chmodSync(selected, 0o600); fs.writeFileSync(selected, 'changed private snapshot'); +console.log(${JSON.stringify(TSHARK_JSON)});`, + ); + const provider = new PcapProvider({ + environment: { REA_TSHARK_COMMAND: tshark, REA_CAPINFOS_COMMAND: capinfos }, + }); + onTestFinished(() => provider.close()); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path }, + }); + expect(result.ok).toBe(false); + if (!result.ok) + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "artifact_changed", + }); + expect(await readFile(path)).toEqual(before); +}); + +it("binds both tools to the snapshot when the original capture changes", async () => { + const root = await createTestTempDirectory("rea-pcap-identity-"); + const path = join(root, "caller capture.pcap"); + await writeFile(path, "192.0.2.1"); + const capinfos = await nodeTool( + root, + "capinfos.cjs", + `${versionProbe} +const selected = process.argv.at(-1); const bytes = fs.readFileSync(selected); +console.log('File type: pcap\\nFile encapsulation: Raw IP\\nNumber of packets: 1\\nSHA256: ' + crypto.createHash('sha256').update(bytes).digest('hex')); +fs.writeFileSync(${JSON.stringify(path)}, '192.0.2.2');`, + ); + const tshark = await nodeTool( + root, + "tshark.cjs", + `${versionProbe} +const selected = process.argv[process.argv.indexOf('-r') + 1]; +console.log(JSON.stringify([{_source:{layers:{'frame.number':['1'],'frame.protocols':['ip'],'ip.src':[fs.readFileSync(selected,'utf8')]}}}]));`, + ); + const provider = new PcapProvider({ + environment: { REA_TSHARK_COMMAND: tshark, REA_CAPINFOS_COMMAND: capinfos }, + }); + onTestFinished(() => provider.close()); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path }, + }); + if (!result.ok) throw result.error; + const value = pcapResultSchemas.inspect_pcap_capture.parse( + result.value.result, + ); + expect(value.target.sha256).toBe( + createHash("sha256").update("192.0.2.1").digest("hex"), + ); + expect(value.endpoints).toEqual([ + { address: "192.0.2.1", port: null, packet_count: 1 }, + ]); + expect(await readFile(path, "utf8")).toBe("192.0.2.2"); +}); + +it.each(["probe", "capinfos", "tshark"] as const)( + "preserves in-flight %s cancellation and cleans up", + async (phase) => { + const root = await createTestTempDirectory("rea-pcap-cancel-"); + const marker = join(root, "ready"); + const slow = await nodeTool( + root, + `slow-${phase}.cjs`, + `${phase !== "probe" ? versionProbe : ""} +fs.writeFileSync(${JSON.stringify(marker)}, 'ready'); setInterval(() => {}, 1000);`, + ); + const { capinfos, tshark } = await writeStubTools(root); + const path = await captureFixture(root); + const provider = new PcapProvider({ + environment: { + REA_TSHARK_COMMAND: phase === "capinfos" ? tshark : slow, + REA_CAPINFOS_COMMAND: phase === "capinfos" ? slow : capinfos, + }, + }); + onTestFinished(() => provider.close()); + const controller = new AbortController(); + let watcher: ReturnType | undefined; + let timer: ReturnType | undefined; + const ready = new Promise((resolve, reject) => { + watcher = watch(root, (_event, name) => { + if (name === "ready") resolve(); + }); + timer = setTimeout(() => { + controller.abort(); + reject(new Error("tool did not start")); + }, 5000); + }); + try { + const pending = provider.execute( + { operation: "inspect_pcap_capture", input: { path } }, + { signal: controller.signal }, + ); + await ready; + controller.abort(new Error("caller cancellation")); + const result = await pending; + if (result.ok) throw new Error("expected cancellation"); + expect(projectAnalysisError(result.error).code).toBe("cancelled"); + await provider.close(); + } finally { + watcher?.close(); + clearTimeout(timer); + } + }, +); + +it.each(["change", "cancel"] as const)( + "preserves %s during snapshot acquisition", + async (action) => { + const { provider, root } = await providerWith(); + const path = await captureFixture(root); + const controller = new AbortController(); + const held = await holdFirstFileRead(path); + onTestFinished(() => { + vi.restoreAllMocks(); + }); + const pending = provider.execute( + { operation: "inspect_pcap_capture", input: { path } }, + { signal: controller.signal }, + ); + try { + await held.firstRead; + if (action === "cancel") controller.abort(); + else await writeFile(path, "changed source bytes"); + } finally { + held.release(); + } + const result = await pending; + if (result.ok) throw new Error("expected interrupted acquisition"); + expect(result.error._tag).toBe( + action === "cancel" + ? "AnalysisCancelledError" + : "AnalysisArtifactChangedError", + ); + }, +); + +it("admits one capture and drains it before close releases resources", async () => { + const { provider, root } = await providerWith(); + const path = await captureFixture(root); + const held = await holdFirstFileRead(path); + onTestFinished(() => { + vi.restoreAllMocks(); + }); + const pending = provider.execute({ + operation: "inspect_pcap_capture", + input: { path }, + }); + let closing: Promise | undefined; + try { + await held.firstRead; + const concurrent = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path }, + }); + expect(concurrent.ok).toBe(false); + if (!concurrent.ok) + expect(projectAnalysisError(concurrent.error)).toMatchObject({ + code: "resource_constraint", + details: { resource: "capacity" }, + }); + let closed = false; + closing = provider.close().then(() => { + closed = true; + }); + await Promise.resolve(); + expect(closed).toBe(false); + } finally { + held.release(); + } + expect((await pending).ok).toBe(true); + await closing; + const afterClose = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path }, + }); + expect(afterClose.ok).toBe(false); +}); + +it.each([false, true])( + "retains failed snapshot cleanup after an analysis failure=%s", + async (failCapinfos) => { + const { provider, root } = await providerWith({ failCapinfos }); + const path = await captureFixture(root); + let retained: PrivateRuntimeRoot | undefined; + const spy = vi + .spyOn(PrivateRuntimeRoot.prototype, "close") + .mockImplementation(function (this: PrivateRuntimeRoot) { + retained = this; + return Promise.reject(new Error("controlled cleanup failure")); + }); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path }, + }); + try { + expect(result.ok).toBe(false); + if (result.ok) throw new Error("Cleanup failure cannot return success"); + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "cleanup_incomplete", + }); + if (failCapinfos) + expect(projectAnalysisError(result.error)).toMatchObject({ + details: { + diagnostics: { primary_error: { code: "unsupported_target" } }, + }, + }); + else + expect(result.error.partialObservation).toMatchObject({ + operation: "inspect_pcap_capture", + normalized_result: { packet_count: 3 }, + }); + expect(retained).toBeDefined(); + await expect(provider.close()).rejects.toMatchObject({ + cleanupIncomplete: true, + }); + } finally { + spy.mockRestore(); + } + await provider.close(); + await expect( + readFile(join(retained!.path, "capture.pcap")), + ).rejects.toMatchObject({ code: "ENOENT" }); + }, +); diff --git a/tests/boundary/pcap/pcapProviderCrossPlatform.test.ts b/tests/boundary/pcap/pcapProviderCrossPlatform.test.ts new file mode 100644 index 000000000..c19e682fe --- /dev/null +++ b/tests/boundary/pcap/pcapProviderCrossPlatform.test.ts @@ -0,0 +1,153 @@ +/** + * Cross-platform pcap provider tests. + * + * POSIX hosts run the #!/bin/sh fixtures; + * Windows runs the .cmd stubs from tests/fixtures/pcap/. Both validate + * the same provider contract surface: tool probing, capture inspection, + * refusal paths, and cancellation before spawn. + */ +import { createHash } from "node:crypto"; +import { writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { expect, it, onTestFinished } from "vitest"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +import { PcapProvider } from "../../../src/pcap/PcapProvider.js"; +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import type { PcapRequest } from "../../../src/domain/pcap/pcapAnalysis.js"; + +const isWindows = process.platform === "win32"; +const hasNativeBound = process.platform === "linux" || isWindows; +const stubDir = join(import.meta.dirname, "../../fixtures/pcap"); +const tsharkStub = isWindows + ? join(stubDir, "tshark-stub.cmd") + : join(stubDir, "tshark-stub.sh"); +const capinfosStub = isWindows + ? join(stubDir, "capinfos-stub.cmd") + : join(stubDir, "capinfos-stub.sh"); + +const providerOver = (): PcapProvider => { + const provider = new PcapProvider({ + environment: { + REA_TSHARK_COMMAND: tsharkStub, + REA_CAPINFOS_COMMAND: capinfosStub, + }, + }); + onTestFinished(() => provider.close()); + return provider; +}; + +const evidenceResult = async ( + provider: PcapProvider, + request: PcapRequest, +): Promise> => { + const result = await provider.execute(request); + if (!result.ok) throw new Error(result.error.message); + return result.value.result as Record; +}; + +it("inspects both tools through cross-platform stubs", async () => { + const result = await evidenceResult(providerOver(), { + operation: "inspect_pcap_client", + input: {}, + }); + expect(result.client).toMatchObject({ + tshark_source: "environment", + tshark_version: expect.stringContaining("4.6.6") as unknown, + capinfos_source: "environment", + capinfos_version: expect.stringContaining("4.6.6") as unknown, + }); +}); + +it.runIf(hasNativeBound)( + "inspects a capture with metadata, endpoints, DNS, and protocol facts", + async () => { + const root = await createTestTempDirectory("rea-pcap-x-"); + const capturePath = join(root, "capture.pcap"); + const captureBytes = "cross-platform-pcap-fixture"; + await writeFile(capturePath, captureBytes); + + const result = await evidenceResult(providerOver(), { + operation: "inspect_pcap_capture", + input: { path: capturePath }, + }); + + expect(result.target).toMatchObject({ + path: capturePath, + bytes: captureBytes.length, + sha256: createHash("sha256").update(captureBytes).digest("hex"), + }); + expect(result.file_type).toContain("pcap"); + expect(result.packet_count).toBe(3); + expect((result.endpoints as unknown[]).length).toBeGreaterThan(0); + expect((result.protocol_distribution as unknown[]).length).toBeGreaterThan( + 0, + ); + expect(result.coverage).toBe("complete"); + }, +); + +// Hosts without a native bound refuse before touching the path; that order +// is pinned by the unsupported-boundary test below. +it.runIf(hasNativeBound)( + "rejects a path that is not a readable file", + async () => { + const result = await providerOver().execute({ + operation: "inspect_pcap_capture", + input: { path: "/nonexistent/definitely-missing.pcap" }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "invalid_request", + }); + }, +); + +it("reports a missing binary as a capability gap", async () => { + const provider = new PcapProvider({ + environment: { REA_TSHARK_COMMAND: "/nonexistent/tshark" }, + }); + expect(await provider.inspectAvailability()).toMatchObject({ + status: "unavailable", + code: "executable_missing", + }); +}); + +it("cancels before spawning anything", async () => { + const controller = new AbortController(); + controller.abort(); + const result = await providerOver().execute( + { operation: "inspect_pcap_capture", input: { path: "/any/capture.pcap" } }, + { signal: controller.signal }, + ); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(projectAnalysisError(result.error)).toMatchObject({ + code: "cancelled", + }); +}); + +it.runIf(!hasNativeBound)( + "reports an unsupported native memory boundary before reading the capture", + async () => { + const provider = providerOver(); + expect(await provider.inspectAvailability()).toMatchObject({ + status: "unavailable", + code: "unsupported_host", + }); + const result = await provider.execute({ + operation: "inspect_pcap_capture", + input: { path: "/not-opened/capture.pcap" }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + const projected = projectAnalysisError(result.error); + expect(projected.code).toBe("capability_unavailable"); + // The refusal concerns this host, so it must not suggest another target. + expect(projected.message).toContain( + "Linux with util-linux prlimit, or Windows with owned Job Objects", + ); + expect(projected.remediation.action).toBe(projected.message); + }, +); diff --git a/tests/boundary/pcap/pcapRetainedView.test.ts b/tests/boundary/pcap/pcapRetainedView.test.ts new file mode 100644 index 000000000..a3f890a37 --- /dev/null +++ b/tests/boundary/pcap/pcapRetainedView.test.ts @@ -0,0 +1,196 @@ +import { createHash } from "node:crypto"; +import { readFile, rm, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { execFile } from "node:child_process"; +import { promisify } from "node:util"; +import { expect, it } from "vitest"; +import { parseEvidence } from "../../../src/domain/evidence.js"; +import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; + +const quote = (value: string) => `'${value.replaceAll("'", "'\\''")}'`; + +const createPcapToolFixture = async (root: string) => { + const path = join(root, "caller capture.pcap"); + const bytes = Buffer.from("recording fixture bytes"); + const sha = createHash("sha256").update(bytes).digest("hex"); + await writeFile(path, bytes); + const tshark = join(root, "tshark"); + const capinfos = join(root, "capinfos"); + const marker = join(root, "reads"); + const frames = Array.from({ length: 132 }, (_, index) => ({ + _source: { + layers: { + "frame.number": [String(index + 1)], + "frame.protocols": ["ip:udp:dns"], + "ip.src": ["192.0.2.1"], + "ip.dst": ["192.0.2.2"], + "dns.qry.name": ["many.example"], + "dns.flags.response": ["True"], + "dns.a": [`198.51.100.${index}`], + "tls.handshake.extensions_server_name": [`host${index}.example`], + "http.request.full_uri": [ + "http://user:password@example.invalid/p?q=keep", + ], + }, + }, + })); + await writeFile( + tshark, + `#!/bin/sh\nif [ "$1" = "--version" ]; then printf 'TShark (Wireshark) 4.6.6-emulated\\n'; exit 0; fi\nprintf 'read\\n' >> ${quote(marker)}\nprintf '%s' ${quote(JSON.stringify(frames))}\nprintf 'retained warning' >&2\n`, + { mode: 0o755 }, + ); + await writeFile( + capinfos, + `#!/bin/sh\nif [ "$1" = "--version" ]; then printf 'Capinfos (Wireshark) 4.6.6-emulated\\n'; exit 0; fi\nprintf '%s\\n' ${quote(`File type: pcap\nFile encapsulation: Ethernet\nNumber of packets: 132\nSHA256: ${sha}`)}\n`, + { mode: 0o755 }, + ); + const environment = { + REA_TSHARK_COMMAND: tshark, + REA_CAPINFOS_COMMAND: capinfos, + }; + return { path, marker, environment }; +}; + +// Native tools are emulated here; this proves the production CLI/MCP boundary, +// retention and paging, not Wireshark's real dissector semantics. +it.runIf(process.platform === "linux")( + "retains every fact and pages late DNS/SNI rows after source deletion without another tool launch", + async () => { + const root = await createTestTempDirectory("rea-pcap-view-"); + const { path, marker, environment } = await createPcapToolFixture(root); + const complete = await promisify(execFile)( + process.execPath, + [ + join(import.meta.dirname, "../../../scripts/rea.mjs"), + "inspect-pcap-capture", + path, + "--json", + ], + { env: { ...process.env, ...environment } }, + ); + const parent = parseEvidence(JSON.parse(complete.stdout)); + expect(parent.normalized_result).toMatchObject({ + tls_sni_count: 132, + tls_sni_values: expect.arrayContaining(["host131.example"]), + dns_queries: [{ query: "many.example", response_address_count: 132 }], + }); + expect(JSON.stringify(parent)).not.toContain("user:password"); + const { call } = await connectLocalToolsMcp(environment); + const response = await call("inspect_pcap_capture", { + path, + detail: "summary", + }); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + const summary = parseEvidence(response.structuredContent).normalized_result; + expect(summary).toMatchObject({ + parent_evidence_id: parent.evidence_id, + summary: { + tls_sni_count: 132, + dns_query_count: 1, + retained_counts: { tls_sni_values: 132 }, + diagnostics_code_units: { tshark: 16, capinfos: 0 }, + }, + }); + expect(JSON.stringify(summary)).not.toContain("host131.example"); + await rm(path); + const source = { + kind: "retained-evidence", + evidence_id: parent.evidence_id, + }; + const before = await readFile(marker, "utf8"); + const cases = [ + [ + { kind: "pcap", facet: "endpoints", limit: 1 }, + { items: [{ address: "192.0.2.1", packet_count: 132 }] }, + ], + [ + { kind: "pcap", facet: "dns-queries", limit: 1 }, + { + items: [ + { query: "many.example", retained_response_address_count: 132 }, + ], + }, + ], + [ + { + kind: "pcap", + facet: "dns-addresses", + query: "many.example", + offset: 130, + limit: 2, + }, + { items: ["198.51.100.130", "198.51.100.131"] }, + ], + [ + { kind: "pcap", facet: "tls-sni", offset: 130, limit: 2 }, + { items: ["host130.example", "host131.example"] }, + ], + [ + { kind: "pcap", facet: "protocols" }, + { items: [{ protocol: "ip:udp:dns", packet_count: 132 }] }, + ], + [ + { kind: "pcap", facet: "http-uris" }, + { items: ["http://example.invalid/p?q=keep"] }, + ], + [{ kind: "pcap", facet: "unattributed-addresses" }, { items: [] }], + [ + { + kind: "pcap", + facet: "diagnostics", + stream: "tshark", + offset: 9, + limit: 7, + }, + { text: "warning", status: "retained" }, + ], + ] as const; + for (const [view, expected] of cases) { + const response = await call("inspect_analysis_view", { source, view }); + expect(response.isError, JSON.stringify(response)).not.toBe(true); + expect( + parseEvidence(response.structuredContent).normalized_result, + ).toMatchObject({ page: expected, source_coverage: "complete" }); + } + const workflow = join(root, "portable.json"); + const view = { + kind: "pcap", + facet: "dns-addresses", + query: "many.example", + offset: 130, + limit: 2, + }; + await writeFile( + workflow, + JSON.stringify({ source: { kind: "inline", evidence: parent }, view }), + ); + const portable = await promisify(execFile)(process.execPath, [ + join(import.meta.dirname, "../../../scripts/rea.mjs"), + "inspect-analysis-view", + workflow, + "--json", + ]); + const retained = parseEvidence( + (await call("inspect_analysis_view", { source, view })).structuredContent, + ); + expect( + parseEvidence(JSON.parse(portable.stdout)).normalized_result, + ).toEqual(retained.normalized_result); + expect(await readFile(marker, "utf8")).toBe(before); + expect( + parseMcpToolError( + await call("inspect_analysis_view", { + source, + view: { + kind: "pcap", + facet: "dns-addresses", + query: "missing.example", + }, + }), + ), + ).toMatchObject({ error: { code: "invalid_request" } }); + }, + 60_000, +); diff --git a/tests/boundary/process/darwinProcessRunTokenReader.test.ts b/tests/boundary/process/darwinProcessRunTokenReader.test.ts index bfdb047f2..9f377440c 100644 --- a/tests/boundary/process/darwinProcessRunTokenReader.test.ts +++ b/tests/boundary/process/darwinProcessRunTokenReader.test.ts @@ -26,6 +26,7 @@ import { import { createDarwinProcessRunTokenReader, DarwinProcessOwnershipInspectionError, + SWIFTC_INTERRUPT, } from "../../../src/process/DarwinProcessRunTokenReader.js"; import { execFileOutput } from "../../../src/process/ExecFileOutput.js"; import { @@ -1110,16 +1111,8 @@ it.skipIf(!onDarwin)( try { await execFileOutput( "/usr/bin/xcrun", - [ - "swiftc", - "-module-cache-path", - join(root, "modules"), - core, - fixture, - "-o", - executable, - ], - { timeout: 60_000 }, + ["swiftc", core, fixture, "-o", executable], + { timeout: 120_000, stopSignal: SWIFTC_INTERRUPT }, ); const { stdout } = await execFileAsync(executable, [], { encoding: "utf8", @@ -1179,6 +1172,7 @@ it.skipIf(!onDarwin)( await rm(root, { recursive: true, force: true }); } }, + 150_000, ); it.skipIf(!onDarwin)( @@ -1203,16 +1197,8 @@ it.skipIf(!onDarwin)( try { await execFileOutput( "/usr/bin/xcrun", - [ - "swiftc", - "-module-cache-path", - join(root, "modules"), - core, - fixture, - "-o", - executable, - ], - { timeout: 60_000 }, + ["swiftc", core, fixture, "-o", executable], + { timeout: 120_000, stopSignal: SWIFTC_INTERRUPT }, ); const { stdout } = await execFileAsync(executable, [], { encoding: "utf8", @@ -1226,6 +1212,7 @@ it.skipIf(!onDarwin)( await rm(root, { recursive: true, force: true }); } }, + 150_000, ); it.skipIf(!onDarwin)( diff --git a/tests/boundary/process/javascriptSourceModes.test.ts b/tests/boundary/process/javascriptSourceModes.test.ts new file mode 100644 index 000000000..64c15a2d8 --- /dev/null +++ b/tests/boundary/process/javascriptSourceModes.test.ts @@ -0,0 +1,39 @@ +import { expect } from "vitest"; + +import { parseJavaScriptSource } from "../../../src/domain/javascript/javascriptSourceParser.js"; +import { processTest } from "../../support/process/processFixture.js"; + +for (const source of [ + "return;", + "void new.target;", + "var await = 1; return;", + "with ({ value: 1 }) { void value; } void new.target;", +]) { + processTest( + `accepts Node CommonJS syntax while retaining module errors: ${source}`, + async ({ processes }) => { + const commonjs = await processes.run( + process.execPath, + ["--check", "--input-type=commonjs"], + { input: source, timeoutMs: 5_000 }, + ); + expect(commonjs.exitCode).toBe(0); + const module = await processes.run( + process.execPath, + ["--check", "--input-type=module"], + { input: source, timeoutMs: 5_000 }, + ); + expect(module.exitCode).not.toBe(0); + + const parsed = parseJavaScriptSource(source, "main.cjs"); + expect(parsed).not.toBeNull(); + expect(parsed?.errors).toEqual([]); + expect( + parseJavaScriptSource(source, "main.mjs")?.errors.length, + ).toBeGreaterThan(0); + expect( + parseJavaScriptSource(source, "main.mts")?.errors.length, + ).toBeGreaterThan(0); + }, + ); +} diff --git a/tests/boundary/process/processCaptureLifecycle.test.ts b/tests/boundary/process/processCaptureLifecycle.test.ts index dcba0510f..c3dc21542 100644 --- a/tests/boundary/process/processCaptureLifecycle.test.ts +++ b/tests/boundary/process/processCaptureLifecycle.test.ts @@ -4,7 +4,7 @@ import { access, readFile, rm, symlink, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; -import { expect } from "vitest"; +import { expect, vi } from "vitest"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { itWithCaptureCapability } from "./processCaptureCapability.js"; @@ -123,6 +123,93 @@ const terminateFixtureProcess = async (pid: number): Promise => { await waitForProcessExit(pid); }; +itWithCaptureCapability( + "keeps the process deadline bounded when the wall clock moves backward", + async () => { + const wallStart = Date.now(); + let wallReads = 0; + const now = vi.spyOn(Date, "now").mockImplementation(() => { + wallReads += 1; + return wallReads === 1 ? wallStart : wallStart - 60_000 + wallReads; + }); + const controller = new AbortController(); + const fallback = setTimeout(() => controller.abort(), 1_500); + try { + const result = await captureProcessScenario( + parseProcessScenario({ + executable: process.execPath, + arguments: [processFixture, "hang"], + working_directory: dirname(processFixture), + timeout_ms: 100, + idle_timeout_ms: 5_000, + }), + controller.signal, + ); + expect(result.ok).toBe(true); + if (!result.ok) throw result.error; + expect(result.value.exit.reason).toBe("timeout"); + } finally { + clearTimeout(fallback); + now.mockRestore(); + } + }, + 10_000, +); + +itWithCaptureCapability( + "preserves reversed wall-clock observations and monotonic frames across capture", + async () => { + vi.useFakeTimers({ toFake: ["Date"] }); + vi.setSystemTime(new Date("2026-01-02T00:00:00.000Z")); + try { + const result = await captureProcessScenario( + parseProcessScenario({ + executable: process.execPath, + arguments: [processFixture, "partial"], + working_directory: dirname(processFixture), + settle_ms: 0, + timeout_ms: 5_000, + idle_timeout_ms: 5_000, + }), + undefined, + process.platform, + process.env, + undefined, + undefined, + { + async report(update) { + if (update.phase === "running") + vi.setSystemTime(new Date("2026-01-01T00:00:00.000Z")); + }, + }, + ); + expect(result.ok).toBe(true); + if (!result.ok) throw result.error; + expect(result.value.frames.length).toBeGreaterThan(0); + expect(Date.parse(result.value.manifest.completed_at)).toBeLessThan( + Date.parse(result.value.manifest.started_at), + ); + expect(result.value.limitations).toContain( + "Wall-clock completion time precedes start time; elapsed capture timing is recorded separately and remains monotonic.", + ); + expect( + result.value.frames.map(({ at_ms }) => at_ms), + "capture-relative frame times stay ordered and nonnegative", + ).toEqual( + [...result.value.frames.map(({ at_ms }) => at_ms)].sort( + (left, right) => left - right, + ), + ); + expect(result.value.frames.every(({ at_ms }) => at_ms >= 0)).toBe(true); + expect(result.value.exit.reason).toBe("exited"); + expect(result.value.settlement.elapsed_ms).toBeGreaterThan(0); + } finally { + vi.useRealTimers(); + } + }, + 10_000, +); + itWithCaptureCapability( "cleans detached run-token children omitted by sampling and preserves an unowned neighbor", async () => { diff --git a/tests/boundary/process/processCaptureNormalization.test.ts b/tests/boundary/process/processCaptureNormalization.test.ts index 965dc2af5..2837ccf40 100644 --- a/tests/boundary/process/processCaptureNormalization.test.ts +++ b/tests/boundary/process/processCaptureNormalization.test.ts @@ -1,4 +1,4 @@ -import { readFile } from "node:fs/promises"; +import { mkdir, readFile, symlink } from "node:fs/promises"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; import { expect, it } from "vitest"; @@ -202,3 +202,61 @@ itWithLinuxCaptureCapability.each([false, true])( }, 20_000, ); + +itWithCaptureCapability( + "preserves selected nested path identities in actual PTY Evidence", + async () => { + const root = await createTestTempDirectory("rea-process-nested-paths-"); + const executable = join(root, "selected-node"); + const observed = join(root, "data"); + await symlink(process.execPath, executable); + await mkdir(observed); + const original = `${executable}\n${observed}/result\n${root}/log`; + const scenario = parseProcessScenario({ + executable, + working_directory: root, + filesystem_observation_paths: [observed], + arguments: ["-e", `process.stdout.write(${JSON.stringify(original)})`], + normalization: { paths: true, pids: false, ports: false, patterns: [] }, + settle_ms: 100, + }); + const result = await captureProcessScenario(scenario); + if (!result.ok) throw result.error; + const capture = parseProcessCapture( + createProcessCaptureEvidence(scenario, result.value).normalized_result, + ); + expect(capture.frames.map(({ data }) => data).join("")).toBe( + "\r\n/result\r\n/log", + ); + expect( + capture.frames.map(({ raw_data, data }) => raw_data ?? data).join(""), + ).toBe(original.replaceAll("\n", "\r\n")); + expect(capture.manifest.comparison_contract).toHaveProperty( + "path_normalization_version", + "longest-original-paths-v1", + ); + const legacyContract = { ...capture.manifest.comparison_contract }; + delete legacyContract.path_normalization_version; + const legacy = parseProcessCapture({ + ...capture, + manifest: { + ...capture.manifest, + comparison_contract: legacyContract, + comparison_contract_sha256: digestProcessCommitment(legacyContract), + }, + }); + expect(() => compareProcessCaptures(legacy, capture)).toThrow( + expect.objectContaining({ + issues: [ + expect.objectContaining({ expected: ["path_normalization_version"] }), + ], + }), + ); + expect(capture.exit).toMatchObject({ code: 0, reason: "exited" }); + expect(capture.cleanup).toMatchObject({ + owned_process_group: "verified", + temporary_root: "removed", + }); + }, + 20_000, +); diff --git a/tests/boundary/process/sourceMapUncHosts.test.ts b/tests/boundary/process/sourceMapUncHosts.test.ts index 293a3f71a..99953509f 100644 --- a/tests/boundary/process/sourceMapUncHosts.test.ts +++ b/tests/boundary/process/sourceMapUncHosts.test.ts @@ -73,9 +73,9 @@ processTest.for(cases)( [ "--input-type=module", "--eval", - `import { resolveJavaScriptSourceMapReference } from "./dist/domain/javascript/javascriptSourceMapPaths.js"; + `import { resolveJavaScriptSourceMapReferences } from "./dist/domain/javascript/javascriptSourceMapPaths.js"; const [source, root] = JSON.parse(process.argv[1]); - console.log(JSON.stringify(resolveJavaScriptSourceMapReference(source, root, "maps/main.js.map")));`, + console.log(JSON.stringify(resolveJavaScriptSourceMapReferences([source], root, "maps/main.js.map")[0]));`, JSON.stringify([scenario.source, sourceRoot]), ], { timeoutMs: 10_000 }, diff --git a/tests/boundary/providers/artifactReadCleanupRetry.test.ts b/tests/boundary/providers/artifactReadCleanupRetry.test.ts new file mode 100644 index 000000000..ebaba673a --- /dev/null +++ b/tests/boundary/providers/artifactReadCleanupRetry.test.ts @@ -0,0 +1,100 @@ +import type { FileHandle } from "node:fs/promises"; +import { mkdtemp, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { expect, it, vi } from "vitest"; + +const cleanupState = vi.hoisted(() => ({ + failFirstClose: false, + abortController: undefined as AbortController | undefined, + firstHandle: undefined as FileHandle | undefined, + firstHandleCloseAttempts: 0, +})); + +vi.mock("node:fs/promises", async (importOriginal) => { + const fs = await importOriginal(); + return { + ...fs, + open: async (...args: Parameters) => { + const handle = await fs.open(...args); + const close = handle.close.bind(handle); + if (cleanupState.abortController !== undefined) + setImmediate(() => { + cleanupState.abortController?.abort(); + cleanupState.abortController = undefined; + }); + handle.close = async () => { + if (handle === cleanupState.firstHandle) + cleanupState.firstHandleCloseAttempts += 1; + else if (cleanupState.firstHandle === undefined) + cleanupState.firstHandle = handle; + if ( + cleanupState.failFirstClose && + handle === cleanupState.firstHandle + ) { + cleanupState.failFirstClose = false; + throw new Error("injected descriptor close failure"); + } + return close(); + }; + return handle; + }, + }; +}); + +import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; +import { GoBinaryProvider } from "../../../src/go/GoBinaryProvider.js"; +import { PeResourcesProvider } from "../../../src/native/pe/PeResourcesProvider.js"; +import { createGoBinaryFixture } from "../../fixtures/go/image.js"; +import { peResourceFixture } from "../../../src/native/pe/PeResources.fixture.js"; + +it.each(["go", "pe"] as const)( + "%s provider retains a failed descriptor close and retries that owner before the next read", + async (kind) => { + const root = await mkdtemp(join(tmpdir(), "rea-read-cleanup-")); + const path = join(root, kind === "go" ? "program.elf" : "program.exe"); + const bytes = + kind === "go" ? createGoBinaryFixture().bytes : peResourceFixture().bytes; + await writeFile(path, bytes); + const provider = + kind === "go" ? new GoBinaryProvider() : new PeResourcesProvider(); + cleanupState.failFirstClose = true; + const controller = new AbortController(); + cleanupState.abortController = controller; + cleanupState.firstHandle = undefined; + cleanupState.firstHandleCloseAttempts = 0; + try { + const input = { + path, + max_file_bytes: 8 * 1024 * 1024, + max_entries: 4096, + }; + const first = await provider.inspect(input, { + signal: controller.signal, + }); + expect(first.ok).toBe(false); + if (first.ok) throw new Error("Injected close failure was not returned"); + expect(projectAnalysisError(first.error)).toMatchObject({ + code: "cleanup_incomplete", + details: { diagnostics: { primary_error: { code: "cancelled" } } }, + }); + expect(first.error.cause).toBeInstanceOf(AggregateError); + if (!(first.error.cause instanceof AggregateError)) + throw first.error.cause; + expect(first.error.cause.errors[1]).toMatchObject({ + cleanupResources: [path], + }); + + const retry = await provider.inspect(input); + expect(retry.ok).toBe(true); + expect(cleanupState.firstHandleCloseAttempts).toBe(2); + } finally { + await provider.close(); + cleanupState.failFirstClose = false; + cleanupState.abortController = undefined; + cleanupState.firstHandle = undefined; + cleanupState.firstHandleCloseAttempts = 0; + await rm(root, { recursive: true, force: true }); + } + }, +); diff --git a/tests/boundary/providers/ghidra/ghidraJavaLaunch.test.ts b/tests/boundary/providers/ghidra/ghidraJavaLaunch.test.ts index dc4be5ef2..56fec2151 100644 --- a/tests/boundary/providers/ghidra/ghidraJavaLaunch.test.ts +++ b/tests/boundary/providers/ghidra/ghidraJavaLaunch.test.ts @@ -286,7 +286,8 @@ describe.skipIf(process.platform === "win32")( { platform: process.platform, architecture: process.arch, - readText: () => "application.version=12.1.4\n", + readText: () => + "application.version=12.1.4\napplication.java.min=21\n", executable: () => true, probeJava: () => ({ version: "21.0.12", diff --git a/tests/boundary/providers/hopper/bridgeLauncher.test.ts b/tests/boundary/providers/hopper/bridgeLauncher.test.ts index 722a25bed..542858a0d 100644 --- a/tests/boundary/providers/hopper/bridgeLauncher.test.ts +++ b/tests/boundary/providers/hopper/bridgeLauncher.test.ts @@ -84,6 +84,7 @@ describe("Hopper bridge launcher selection", () => { "private", "/usr/bin/python3", "/rea/hopper-demo-x11.py", + "--owner-stdin", "--strategy", "user-mount-namespace", "--mount-private-x11", @@ -117,6 +118,7 @@ describe("Hopper bridge launcher selection", () => { command: "/usr/bin/python3", args: [ "/rea/hopper-demo-x11.py", + "--owner-stdin", "--strategy", "direct", "--hopper", @@ -202,3 +204,59 @@ it("launches Hopper helpers with the caller-selected environment without restori await launched.value.releaseLease?.(); } }); + +it.skipIf(process.platform !== "linux")( + "gives the demo helper a live owner stream through Node's actual stdio transport", + async () => { + const directory = await createTestTempDirectory("rea-hopper-owner-stdio-"); + const launcher = new HopperApplicationLauncher( + { + ...options(process.execPath), + launchMode: "verified_linux_demo", + demoHelperPath: fileURLToPath( + new URL("../../../fixtures/hopperLifetimeLaunch.py", import.meta.url), + ), + }, + { + selectPrivateDisplay: async () => ({ + ok: true, + strategy: "direct", + diagnostic: { + component: "hopper_private_display", + operation: "probe", + status: "ready", + failure_code: null, + reason: "ready", + socket_directory: "/tmp/.X11-unix", + socket_directory_mode: "1777", + mount_read_only: false, + effective_socket_directory_mode: "1777", + effective_mount_read_only: false, + wsl: false, + strategy: "direct", + fallback_reason: null, + xvfb_stderr_bytes: 0, + }, + }), + }, + ); + const launched = await launcher.launch({ + directory, + socketPath: join(directory, "bridge.sock"), + token: "fixture-token", + runId: randomUUID(), + }); + if (!launched.ok) throw launched.error; + const supervisor = new ProviderProcessSupervisor(launched.value); + try { + expect(await supervisor.waitForOutputClose(5_000)).toBe(true); + expect(supervisor.snapshot().exitCode).toBe(0); + expect(JSON.parse(supervisor.snapshot().stdout.text)).toEqual({ + owner_alive: true, + }); + } finally { + await supervisor.stop(); + await launched.value.releaseLease?.(); + } + }, +); diff --git a/tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts b/tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts index f2c99980f..c5fd45c96 100644 --- a/tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts +++ b/tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts @@ -31,6 +31,9 @@ const dialogDetectionFixturePath = fileURLToPath( const cleanupTimeoutFixturePath = fileURLToPath( new URL("../../../fixtures/hopperCleanupTimeout.py", import.meta.url), ); +const ownerLifetimeFixturePath = fileURLToPath( + new URL("../../../fixtures/hopperOwnerLifetime.py", import.meta.url), +); type DiagnosticOverrides = Partial< Omit @@ -107,6 +110,23 @@ describe("Hopper demo dialog detection", () => { }); describe("Hopper process cleanup", () => { + it.skipIf(process.platform !== "linux").each(["startup", "ready"])( + "reaps only its own children when the owner pipe closes during %s", + (phase) => { + const result = spawnSync( + "/usr/bin/python3", + [ownerLifetimeFixturePath, helperPath, phase], + { encoding: "utf8", timeout: 10_000 }, + ); + expect(result.status, result.stderr).toBe(0); + expect(JSON.parse(result.stdout)).toEqual({ + phase, + children_cleaned: true, + sentinel_alive: true, + }); + }, + ); + it.skipIf(process.platform !== "linux")( "kills a child that ignores SIGTERM after the bounded timeout", () => { diff --git a/tests/boundary/providers/ida/verifierObservations.test.ts b/tests/boundary/providers/ida/verifierObservations.test.ts new file mode 100644 index 000000000..56376174d --- /dev/null +++ b/tests/boundary/providers/ida/verifierObservations.test.ts @@ -0,0 +1,271 @@ +import { randomUUID } from "node:crypto"; +import { readFile, rm, writeFile } from "node:fs/promises"; +import { createServer } from "node:http"; +import { join } from "node:path"; +import { expect, it } from "vitest"; +import { z } from "zod"; +import { + jsonValueSchema, + type JsonValue, +} from "../../../../src/domain/jsonValue.js"; +import { nativeTools } from "../../../../src/ida/IdaNativeProtocol.js"; +import { + OwnedCommandFailure, + runOwnedCommand, +} from "../../../../src/process/OwnedCommand.js"; +import { createIdaTarget } from "../../../fixtures/idaMcp.js"; + +const requestSchema = z.object({ + id: z.union([z.string(), z.number()]).optional(), + method: z.string(), + params: z + .object({ + protocolVersion: z.string().optional(), + name: z.string().optional(), + arguments: z.record(z.string(), jsonValueSchema).optional(), + }) + .passthrough() + .optional(), +}); + +const fn = (address: string) => ({ + addr: address, + name: address === "0x1000" ? "main" : "helper", + size: "0x20", +}); +const observation = ( + name: string, + args: Readonly>, + scenario: { readonly empty: readonly string[]; readonly omitMore: boolean }, +): JsonValue => { + switch (name) { + case "lookup_funcs": + return z + .array(z.string()) + .parse(args.queries) + .map((query) => ({ + query, + fn: fn( + query === "helper" || query === "0x2000" ? "0x2000" : "0x1000", + ), + error: null, + })); + case "list_funcs": + return [ + { + data: scenario.empty.includes(name) ? [] : [fn("0x1000")], + next_offset: null, + }, + ]; + case "find_regex": + return { + matches: scenario.empty.includes(name) + ? [] + : [{ addr: "0x3000", string: "a.b" }], + cursor: { done: true }, + }; + case "decompile": { + const addr = z.string().parse(args.addr); + return { + addr, + ok: true, + pseudocode: + addr === "0x1000" + ? "int main(void) { return 42; }" + : "int helper(void) { return 55; }", + lines: 1, + }; + } + case "disasm": + return { + asm: { + name: "main", + start_ea: "0x1000", + lines: "main (.text @ 0x1000):\n1000 ret", + }, + cursor: { done: true }, + }; + case "callees": + return [ + { + callees: [], + error: null, + ...(scenario.omitMore ? {} : { more: false }), + }, + ]; + case "xrefs_to": + return [ + { + xrefs: scenario.empty.includes(name) + ? [] + : [{ addr: "0x1004", type: "code", fn: null }], + more: false, + error: null, + }, + ]; + default: + throw new Error(`Unexpected fixture operation ${name}`); + } +}; + +const fixture = async (empty: readonly string[], omitMore: boolean) => { + const { root, target } = await createIdaTarget(); + const server = createServer(async (request, response) => { + try { + let body = ""; + for await (const chunk of request) body += String(chunk); + const input = requestSchema.parse(JSON.parse(body)); + if (input.id === undefined) { + response.writeHead(202).end(); + return; + } + const result = + input.method === "initialize" + ? { + protocolVersion: input.params?.protocolVersion, + capabilities: { tools: {}, resources: {} }, + serverInfo: { name: "native-verifier-fixture", version: "1" }, + } + : input.method === "tools/list" + ? { + tools: nativeTools.map((name) => ({ + name, + inputSchema: { type: "object" }, + })), + } + : input.method === "resources/read" + ? { + contents: [ + { + uri: "ida://idb/metadata", + mimeType: "application/json", + text: JSON.stringify({ + path: `${target.path}.i64`, + sha256: target.sha256, + base: "0x1000", + module: "target.elf", + }), + }, + ], + } + : { + content: [ + { + type: "text", + text: JSON.stringify( + observation( + z.string().parse(input.params?.name), + input.params?.arguments ?? {}, + { empty, omitMore }, + ), + ), + }, + ], + }; + response + .writeHead(200, { "Content-Type": "application/json" }) + .end(JSON.stringify({ jsonrpc: "2.0", id: input.id, result })); + } catch { + response.writeHead(500).end(); + } + }); + await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); + const address = server.address(); + if (address === null || typeof address === "string") + throw new Error("No fixture address"); + const config = join(root, "native.json"); + await writeFile( + config, + JSON.stringify({ + url: `http://127.0.0.1:${address.port}/mcp`, + protocol: "native", + timeoutMs: 30000, + }), + ); + return { + root, + target, + config, + close: async (removeWorkspace: boolean) => { + server.closeAllConnections(); + await new Promise((resolve, reject) => + server.close((error) => + error === undefined ? resolve() : reject(error), + ), + ); + if (removeWorkspace) await rm(root, { recursive: true, force: true }); + }, + }; +}; + +it.each([ + { empty: [], omitMore: false, oracles: true, passed: true }, + { empty: ["list_funcs"], omitMore: false, oracles: true, passed: false }, + { empty: ["find_regex"], omitMore: false, oracles: true, passed: false }, + { empty: ["xrefs_to"], omitMore: false, oracles: true, passed: false }, + { empty: [], omitMore: true, oracles: true, passed: false }, + { + empty: ["find_regex", "xrefs_to"], + omitMore: false, + oracles: false, + passed: true, + }, +])( + "checks real-verifier values for $empty / omitted more=$omitMore / oracles=$oracles", + async ({ empty, omitMore, oracles, passed }) => { + const upstream = await fixture(empty, omitMore); + let cleanupConfirmed = false; + try { + const reportPath = join(upstream.root, "report.json"); + const result = await runOwnedCommand( + { + command: process.execPath, + arguments: [ + "scripts/verify-real-ida.mjs", + "--target", + upstream.target.path, + "--procedure", + "main", + "--second-procedure", + "helper", + "--second-marker", + "55", + "--report", + reportPath, + ...(oracles + ? ["--expected-string", "a.b", "--expected-xref", "0x1004"] + : []), + ], + runId: `rea-ida-verifier-${randomUUID()}`, + cwd: process.cwd(), + env: { + REA_IDA_MCP_CONFIG: upstream.config, + NODE_OPTIONS: "--max-old-space-size=1024", + }, + }, + { timeoutMs: 90000, diagnosticBytes: 16384, acceptNonZeroExit: true }, + ); + cleanupConfirmed = true; + const report = z + .object({ passed: z.boolean(), unverified: z.array(z.string()) }) + .parse(JSON.parse(await readFile(reportPath, "utf8"))); + expect(report.passed, result.stdout.text + result.stderr.text).toBe( + passed, + ); + expect(result.exitCode).toBe(passed ? 0 : 1); + if (!oracles) + expect(report.unverified).toEqual([ + "String inventory/search correctness: no independent expected literal supplied.", + "Xref correctness: no independent expected source address supplied.", + ]); + else expect(report.unverified).toEqual([]); + } catch (cause) { + if (cause instanceof OwnedCommandFailure && cause.cleanupFailure === null) + cleanupConfirmed = true; + throw cause; + } finally { + await upstream.close(cleanupConfirmed); + } + }, + 120000, +); diff --git a/tests/boundary/providers/managed/managedMemberComparisonFromMetadata.test.ts b/tests/boundary/providers/managed/managedMemberComparisonFromMetadata.test.ts index 7f4408811..56014fbd4 100644 --- a/tests/boundary/providers/managed/managedMemberComparisonFromMetadata.test.ts +++ b/tests/boundary/providers/managed/managedMemberComparisonFromMetadata.test.ts @@ -116,6 +116,66 @@ describe("managed member comparison", () => { }); }); +describe("managed member comparison floating-point constants", () => { + it.each([ + { + opcode: "ldc.r4", + positive: "22000000002a", + negative: "22000000802a", + type: 0x0c, + }, + { + opcode: "ldc.r8", + positive: "2300000000000000002a", + negative: "2300000000000000802a", + type: 0x0d, + }, + ])( + "detects a change from positive to negative zero in $opcode", + ({ opcode, positive, negative, type }) => { + const observe = (hex: string, path: string) => { + const il = Buffer.from(hex, "hex"); + return inspect( + buildManagedPeFixture({ + methodSignature: Buffer.from([0x00, 0x00, type]), + ilBody: Buffer.concat([Buffer.from([(il.length << 2) | 2]), il]), + }), + path, + ); + }; + const left = observe(positive, "/tmp/positive-zero.dll"); + const right = observe(negative, "/tmp/negative-zero.dll"); + const comparison = compareManagedMembers(left, right); + + expect(comparison.methods[0]).toMatchObject({ + status: "changed", + match: { status: "matched", basis: "exact-signature" }, + dimensions: ["cil"], + }); + for (const [observation, operand] of [ + [left, "0"], + [right, "-0"], + ] as const) { + expect(observation.result.methods[0]?.body).toMatchObject({ + status: "present", + anchors: [ + { il_offset: 0, opcode, operand_kind: "constant", operand }, + ], + }); + } + expect(left.result.methods[0]?.body.normalized_il_sha256).not.toBe( + right.result.methods[0]?.body.normalized_il_sha256, + ); + const repeated = observe(negative, "/tmp/negative-zero-copy.dll"); + expect(compareManagedMembers(right, repeated).methods[0]).toMatchObject({ + status: "unchanged", + match: { status: "matched", basis: "exact-il-signature" }, + dimensions: [], + }); + }, + ); +}); + describe("managed member comparison uncertainty", () => { it("does not infer a structural method match from undecoded signature fields", () => { const left = inspect( diff --git a/tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts b/tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts index d42762601..0bcf12bb2 100644 --- a/tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts +++ b/tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts @@ -3,7 +3,7 @@ import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises"; import { join } from "node:path"; import { createPackage, createPackageWithOptions } from "@electron/asar"; -import { expect, it } from "vitest"; +import { expect, it, vi } from "vitest"; import { ArtifactProvider } from "../../../../src/artifacts/ArtifactProvider.js"; import { @@ -13,6 +13,7 @@ import { import { artifactExtractionResultSchema } from "../../../../src/domain/artifactGraph.js"; import { projectAnalysisError } from "../../../../src/domain/analysisErrorProjection.js"; import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js"; +import { DirectoryArtifactReader } from "../../../../src/artifacts/DirectoryArtifactReader.js"; it.each(["file", "directory"] as const)( "rolls back when an inventoried %s disappears before extraction", @@ -61,6 +62,42 @@ it("still refuses a regular file added after inventory and rolls back", async () await expect(access(output)).rejects.toThrow(); }); +it("rolls back when cancellation arrives while closing the materialization reader", async () => { + const root = await createTestTempDirectory("rea-extract-cancel-close-"); + const source = join(root, "source"); + await mkdir(source); + await writeFile(join(source, "payload.txt"), "complete payload\n"); + const snapshot = await scanArtifactInventory(source); + const output = join(root, "output"); + const controller = new AbortController(); + const close = DirectoryArtifactReader.prototype.close; + const closeSpy = vi + .spyOn(DirectoryArtifactReader.prototype, "close") + .mockImplementation(async function (this: DirectoryArtifactReader) { + controller.abort(); + await close.call(this); + }); + try { + await expect( + materializeArtifactInventory( + { + inputPath: source, + inputFormat: "asar", + outputRoot: output, + environment: process.env, + integrityPolicy: "fail", + }, + source, + snapshot, + controller.signal, + ), + ).rejects.toMatchObject({ reason: "cancelled" }); + await expect(access(output)).rejects.toThrow(); + } finally { + closeSpy.mockRestore(); + } +}); + it("preserves every equal-content occurrence and copies a nested ASAR as its containing file", async () => { const root = await createTestTempDirectory("rea-extract-nested-"); const source = join(root, "source"); diff --git a/tests/boundary/providers/native/artifactProvider.extractionFormat.test.ts b/tests/boundary/providers/native/artifactProvider.extractionFormat.test.ts index 81b3cce52..e4accd098 100644 --- a/tests/boundary/providers/native/artifactProvider.extractionFormat.test.ts +++ b/tests/boundary/providers/native/artifactProvider.extractionFormat.test.ts @@ -3,10 +3,12 @@ import { join } from "node:path"; import { describe, expect, it } from "vitest"; +import { writeOrderedZip } from "../../../fixtures/artifactEntryOrder.js"; import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js"; import { ArtifactProvider } from "../../../../src/artifacts/ArtifactProvider.js"; import { artifactExtractionExecutionSchema } from "../../../../src/contracts/artifactToolContracts.js"; +import { artifactExtractionResultSchema } from "../../../../src/domain/artifactGraph.js"; import type { BinaryTarget } from "../../../../src/domain/binaryTargetTypes.js"; describe("artifact extraction format support", () => { @@ -42,6 +44,33 @@ describe("artifact extraction format support", () => { }); await expect(access(output)).rejects.toThrow(); }); + + it.each(["zip", "hap", "hsp", "app-pack"] as const)( + "extracts the ZIP-backed %s package family that inventory already supports", + async (format) => { + const root = await createTestTempDirectory("rea-extract-zip-family-"); + const archive = join( + root, + `Payload.${format === "app-pack" ? "app" : format}`, + ); + await writeOrderedZip(archive, ["payload.txt"]); + const result = await new ArtifactProvider(process.env) + .createClient(archiveTarget(archive, format)) + .execute( + "extract_artifact", + artifactExtractionExecutionSchema.parse({ + output_root: join(root, "output"), + }), + ); + if (!result.ok) throw result.error; + const extracted = artifactExtractionResultSchema.parse( + result.value.result, + ); + expect( + extracted.artifacts.map(({ relative_path }) => relative_path), + ).toEqual(["payload.txt"]); + }, + ); }); const archiveTarget = ( diff --git a/tests/boundary/providers/native/machoSliceReader.test.ts b/tests/boundary/providers/native/machoSliceReader.test.ts index f67b48388..5891eaf53 100644 --- a/tests/boundary/providers/native/machoSliceReader.test.ts +++ b/tests/boundary/providers/native/machoSliceReader.test.ts @@ -3,6 +3,8 @@ import { readFile } from "node:fs/promises"; import { describe, expect, it, onTestFinished } from "vitest"; import { MachOSliceArtifactReader } from "../../../../src/artifacts/MachOSliceArtifactReader.js"; +import { XcrunCommandRunner } from "../../../../src/native/CommandRunner.js"; +import { DarwinProcessOwnershipInspectionError } from "../../../../src/process/DarwinProcessRunTokenReader.js"; /** * Read a 32-bit FAT table directly. The host's /bin/ls changes between macOS @@ -20,6 +22,26 @@ const fatSlices = async ( }; describe("Mach-O slice reader with system lipo", () => { + it("names the process ownership helper prerequisite when lipo cannot be supervised", async () => { + const prerequisite = + "Direct Darwin helper compilation requires absolute REA_DARWIN_SWIFTC_PATH and SDKROOT paths."; + const reader = new MachOSliceArtifactReader( + process.execPath, + {}, + new XcrunCommandRunner({}, undefined, () => + Promise.reject(new DarwinProcessOwnershipInspectionError(prerequisite)), + ), + ); + onTestFinished(() => reader.close()); + const enumerate = async () => { + for await (const _entry of reader.entries()) continue; + }; + await expect(enumerate()).rejects.toMatchObject({ + reason: "unavailable", + message: `lipo could not enumerate universal Mach-O slices: ${prerequisite}`, + }); + }); + it.skipIf(process.platform !== "darwin")( "checks real /bin/ls slice ranges against its FAT table", async () => { diff --git a/tests/boundary/providers/native/nativeCommandTermination.test.ts b/tests/boundary/providers/native/nativeCommandTermination.test.ts index 233ebe85e..5d23e6b22 100644 --- a/tests/boundary/providers/native/nativeCommandTermination.test.ts +++ b/tests/boundary/providers/native/nativeCommandTermination.test.ts @@ -8,6 +8,7 @@ import { type NativeCommandLauncher, } from "../../../../src/native/CommandRunner.js"; import { ok } from "../../../../src/domain/result.js"; +import { DarwinProcessOwnershipInspectionError } from "../../../../src/process/DarwinProcessRunTokenReader.js"; afterEach(() => vi.unstubAllEnvs()); @@ -210,3 +211,23 @@ it.skipIf(process.platform === "win32")( if (!killed.ok) expect(killed.error.reason).toBe("nonzero-exit"); }, ); + +it("keeps the ownership helper prerequisite when xcrun cannot be supervised", async () => { + const inspection = new DarwinProcessOwnershipInspectionError( + "macOS process ownership inspection requires the Apple Swift compiler via xcrun", + ); + const runner = new XcrunCommandRunner({}, undefined, () => + Promise.reject(inspection), + ); + + const result = await runner.run("file", [], {}); + + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error).toMatchObject({ + tool: "file", + reason: "io", + detail: inspection.message, + cause: { tool: "xcrun", detail: inspection.message, cause: inspection }, + }); +}); diff --git a/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts b/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts index 9e03727c1..5d6af987d 100644 --- a/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts +++ b/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts @@ -1200,6 +1200,138 @@ describe("native DMG command diagnostics", () => { }); }); +describe("native DMG verification resource availability", () => { + const transientFailure = { + stdout: "", + stderr: + 'hdiutil: verify: unable to recognize "/tmp/image.dmg" as a disk image. (Resource temporarily unavailable)\nhdiutil: verify failed - Resource temporarily unavailable\n', + exitCode: 1, + }; + + it("retries the explicit transient refusal before attachment and retains both attempts", async () => { + const { host, state } = createOmittedInventoryHost(); + state.inventoryMode = "listed"; + state.detachAttempts = 4; + const delays = vi.fn(async () => {}); + const timeouts: number[] = []; + let attempts = 0; + const reader = await createAttachedReader( + "/tmp/image.dmg", + process.env, + undefined, + { + ...host, + delay: delays, + async run(arguments_, signal, options) { + if (arguments_[0] === "verify") { + attempts += 1; + if (options === undefined) + throw new Error("missing verify deadline"); + timeouts.push(options.timeoutMs); + if (attempts === 1) return transientFailure; + } + return host.run(arguments_, signal, options); + }, + }, + ); + onTestFinished(() => reader.close()); + expect(attempts).toBe(2); + expect(delays.mock.calls).toEqual([[250]]); + expect(timeouts[0]).toBeLessThanOrEqual(120_000); + expect(timeouts[1]).toBeLessThanOrEqual(timeouts[0]!); + expect(reader.provenance().slice(0, 2)).toMatchObject([ + { + arguments: ["verify", "/tmp/image.dmg"], + exit_code: 1, + effects: ["read"], + }, + { + arguments: ["verify", "/tmp/image.dmg"], + exit_code: 0, + effects: ["read"], + }, + ]); + await reader.close(); + expect(state.attached).toBe(false); + }); + + it("bounds repeated transient refusals and never attaches an unverified image", async () => { + const run = vi.fn(async () => transientFailure); + const delay = vi.fn(async () => {}); + const reader = new NativeDmgArtifactReader("/tmp/image.dmg", process.env, { + run, + delay, + }); + await expect(entryPaths(reader)).rejects.toMatchObject({ + reason: "unavailable", + message: expect.stringContaining("Resource temporarily unavailable"), + }); + await reader.close(); + expect(run.mock.calls).toHaveLength(3); + expect(delay.mock.calls).toEqual([[250], [500]]); + expect(reader.provenance().map(({ exit_code }) => exit_code)).toEqual([ + 1, 1, 1, + ]); + }); + + it("honors cancellation during the wait without starting another command", async () => { + const controller = new AbortController(); + const run = vi.fn(async () => transientFailure); + await expect( + createAttachedReader("/tmp/image.dmg", process.env, controller.signal, { + run, + async delay() { + controller.abort(new Error("cancel verification")); + }, + }), + ).rejects.toMatchObject({ reason: "cancelled" }); + expect(run).toHaveBeenCalledTimes(1); + }); + + it("does not start another verification after the shared deadline", async () => { + const clock = vi.spyOn(performance, "now").mockReturnValue(0); + const run = vi.fn(async () => transientFailure); + try { + await expect( + createAttachedReader("/tmp/image.dmg", process.env, undefined, { + run, + async delay() { + clock.mockReturnValue(120_001); + }, + }), + ).rejects.toMatchObject({ + reason: "unavailable", + message: expect.stringContaining("Resource temporarily unavailable"), + }); + expect(run).toHaveBeenCalledTimes(1); + } finally { + clock.mockRestore(); + } + }); + + it.each([ + ["image data corrupted", "integrity"], + ["image not recognized", "format"], + ["Permission denied", "io"], + ["an unknown failure", "unavailable"], + ])("does not retry %s", async (diagnostic, reason) => { + const run = vi.fn(async () => ({ + stdout: "", + stderr: `hdiutil: verify failed - ${diagnostic}\n`, + exitCode: 1, + })); + const delay = vi.fn(async () => {}); + await expect( + createAttachedReader("/tmp/image.dmg", process.env, undefined, { + run, + delay, + }), + ).rejects.toMatchObject({ reason }); + expect(run).toHaveBeenCalledTimes(1); + expect(delay).not.toHaveBeenCalled(); + }); +}); + describe("native DMG real verification diagnostics", () => { it.skipIf(process.platform !== "darwin")( "classifies a real hdiutil verify refusal as a format failure with captured output", diff --git a/tests/boundary/providers/native/nativeProvider.test.ts b/tests/boundary/providers/native/nativeProvider.test.ts index b4a713204..0d1860b16 100644 --- a/tests/boundary/providers/native/nativeProvider.test.ts +++ b/tests/boundary/providers/native/nativeProvider.test.ts @@ -1,4 +1,5 @@ import { createHash } from "node:crypto"; +import { DarwinProcessOwnershipInspectionError } from "../../../../src/process/DarwinProcessRunTokenReader.js"; import { EventEmitter } from "node:events"; import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises"; import { join } from "node:path"; @@ -60,7 +61,13 @@ afterEach(async () => { }); describe("native macOS provider discovery", () => { - it.each(["ordinary.fixture", " spaced.fixture ", " leading", "trailing "])( + it.each([ + "ordinary.fixture", + " spaced.fixture ", + " leading", + "trailing ", + "literal\r\nidentifier\r", + ])( "preserves the exact signing identifier %j reported by codesign", (identifier) => { const parsed = parseCodeSignature( @@ -73,31 +80,68 @@ describe("native macOS provider discovery", () => { }, ); - it("separates echoed path and identifier text from signature fields", () => { - const path = "/apps/x\nAuthority=Forged\nIdentifier=forged"; - const identifier = "x\nFormat=forged\nAuthority=Forged-5555"; - const parsed = parseCodeSignature( - [ - `Executable=${path}`, - `Identifier=${identifier}`, - "Format=Mach-O thin (arm64)", - "CodeDirectory v=20400 size=342 flags=0x2(adhoc) hashes=2+2", - "CDHash=6aee90e6", - "Signature=adhoc", - "TeamIdentifier=not set", - "", - ].join("\r\n"), - false, - ["/elsewhere", path], - ); - expect(parsed).toMatchObject({ - identifier, - format: "Mach-O thin (arm64)", - authorities: [], - cdhashes: ["6aee90e6"], - team_identifier: null, - }); - }); + it.each(["\n", "\r\n"])( + "separates echoed path and identifier text from signature fields (%j)", + (newline) => { + const path = "/apps/x\r\nAuthority=Forged\nIdentifier=forged"; + const identifier = "x\r\nFormat=forged\nAuthority=Forged-5555\r"; + const parsed = parseCodeSignature( + [ + `Executable=${path}`, + `Identifier=${identifier}`, + "Format=Mach-O thin (arm64)", + "CodeDirectory v=20400 size=342 flags=0x2(adhoc) hashes=2+2", + "CDHash=6aee90e6", + "Signature=adhoc", + "TeamIdentifier=not set", + "", + ].join(newline), + false, + ["/elsewhere", path], + ); + expect(parsed).toMatchObject({ + identifier, + format: "Mach-O thin (arm64)", + authorities: [], + cdhashes: ["6aee90e6"], + team_identifier: null, + }); + }, + ); + + it.each([ + { executable: "", paths: [], newline: "\r\n", identifier: "fixture" }, + { + executable: "Executable=/apps/fixture\r\n", + paths: [], + newline: "\r\n", + identifier: "fixture\nFormat=payload\r", + }, + { + executable: "Executable=/apps/fixture\n", + paths: ["/elsewhere"], + newline: "\n", + identifier: "fixture\r\nFormat=payload\r", + }, + { + executable: "Executable=/apps/fixture\r\n", + paths: ["/elsewhere"], + newline: "\r\n", + identifier: "fixture\r", + }, + ])( + "frames the identifier without a matching executable path: %j", + ({ executable, paths, newline, identifier }) => { + const parsed = parseCodeSignature( + `${executable}Identifier=${identifier}${newline}Format=Mach-O thin (arm64)${newline}TeamIdentifier=not set${newline}`, + false, + paths, + ); + expect(parsed.identifier).toBe(identifier); + expect(parsed.format).toBe("Mach-O thin (arm64)"); + expect(parsed.team_identifier).toBeNull(); + }, + ); it.each(["timeout", "output-limit"] as const)( "preserves %s resolution failures with their captured output and cleanup status", @@ -280,6 +324,30 @@ describe("native command failure capture and limits", () => { stderr_bytes: expect.any(Number), }, }); + expect(projectAnalysisError(result.error).details).not.toHaveProperty( + "diagnostics.detail", + ); + }); + + it("projects the ownership helper prerequisite when a command cannot be supervised", async () => { + const inspection = new DarwinProcessOwnershipInspectionError( + "Direct Darwin helper compilation requires absolute REA_DARWIN_SWIFTC_PATH and SDKROOT paths.", + ); + const runner = new XcrunCommandRunner( + {}, + () => + Promise.resolve(ok({ path: process.execPath, sha256: "a".repeat(64) })), + () => Promise.reject(inspection), + ); + const result = await new NativeMacOSProvider({}, runner, "darwin") + .createClient(machoTarget("/private/fixture")) + .execute("demangle_swift", { symbols: ["fixture-symbol"] }); + + expect(result.ok).toBe(false); + if (result.ok) return; + expect(projectAnalysisError(result.error).details).toMatchObject({ + diagnostics: { reason: "io", detail: inspection.message }, + }); }); it("retains output written before cancellation and reaps the stalled command", async () => { diff --git a/tests/boundary/providers/native/nativeSelectedArchitecture.test.ts b/tests/boundary/providers/native/nativeSelectedArchitecture.test.ts index 006b13003..a651e22f6 100644 --- a/tests/boundary/providers/native/nativeSelectedArchitecture.test.ts +++ b/tests/boundary/providers/native/nativeSelectedArchitecture.test.ts @@ -1,7 +1,11 @@ import { expect, it } from "vitest"; +import { CPU } from "../../../../src/artifacts/apple/MachoImage.fixture.js"; import { inspectMachoSchema } from "../../../../src/domain/native/nativeInspection.js"; import { err } from "../../../../src/domain/result.js"; -import { NativeCommandFailure } from "../../../../src/native/CommandRunner.js"; +import { + NativeCommandFailure, + type NativeCommandRunner, +} from "../../../../src/native/CommandRunner.js"; import { NativeMacOSProvider } from "../../../../src/native/NativeMacOSProvider.js"; import { NativeFixtureRunner, @@ -9,6 +13,35 @@ import { nativeMachoTarget, } from "../../../fixtures/nativeCommands.js"; +/** Replay fixtures, failing any slice command that does not name the expected slice. */ +const sliceSelectingRunner = ( + fixtures: NativeFixtureRunner, + selected: string, + dyldArchitecture: string, + calls: { + readonly tool: string; + readonly arguments_: readonly string[]; + }[] = [], +): NativeCommandRunner => ({ + run(tool, arguments_) { + calls.push({ tool, arguments_ }); + const expected = tool === "dyld_info" ? dyldArchitecture : selected; + if ( + !["file", "lipo"].includes(tool) && + !arguments_.some( + (argument, index) => + argument === expected || + argument === `--arch=${expected}` || + (argument === "-arch" && arguments_[index + 1] === expected), + ) + ) + return Promise.resolve( + err(new NativeCommandFailure(tool, "nonzero-exit", 1)), + ); + return fixtures.run(tool, arguments_); + }, +}); + it("does not attribute the first universal slice's UUID and segments to the selected target", async () => { const singleSlice = await nativeFixture("otool-load.txt"); const selected = new NativeFixtureRunner(); @@ -58,18 +91,39 @@ it.each([ selected: "arm64e", dyldArchitecture: "arm64e.v1", }, -])( + { + architectures: ["arm64v8", "arm64e.v1"], + selected: "arm64e", + dyldArchitecture: "arm64e.v1", + }, + { + architectures: ["arm64e.v1", "arm64v8"], + selected: "arm64e", + dyldArchitecture: "arm64e.v1", + }, +] as const)( "selects the $dyldArchitecture slice of a universal arm64e target", async ({ architectures, selected, dyldArchitecture }) => { const calls: { readonly tool: string; readonly arguments_: readonly string[]; }[] = []; + const cpus = { + x86_64: CPU.x86_64, + arm64e: CPU.arm64e, + arm64v8: { type: CPU.arm64.type, subtype: 1 }, + "arm64e.x1": { type: CPU.arm64.type, subtype: 0x8000000c }, + "arm64e.v1": { type: CPU.arm64.type, subtype: 0x81000002 }, + }; const lipo = architectures - .map( - (architecture, index) => - `architecture ${architecture}\n cputype 16777228\n cpusubtype 2\n offset ${index * 16384}\n size 8192\n align 2^14 (16384)`, - ) + .map((architecture, index) => { + const cpu = cpus[architecture]; + const subtype = + architecture === "arm64e.v1" + ? "CPU_SUBTYPE_ARM64E\n capabilities PTR_AUTH_VERSION USERSPACE 1" + : String(cpu.subtype); + return `architecture ${architecture}\n cputype ${cpu.type}\n cpusubtype ${subtype}\n offset ${index * 16384}\n size 8192\n align 2^14 (16384)`; + }) .join("\n"); const fixtures = new NativeFixtureRunner({ lipo, @@ -77,25 +131,7 @@ it.each([ }); const client = new NativeMacOSProvider( {}, - { - run(tool, arguments_) { - calls.push({ tool, arguments_ }); - const expected = tool === "dyld_info" ? dyldArchitecture : selected; - if ( - !["file", "lipo"].includes(tool) && - !arguments_.some( - (argument, index) => - argument === expected || - argument === `--arch=${expected}` || - (argument === "-arch" && arguments_[index + 1] === expected), - ) - ) - return Promise.resolve( - err(new NativeCommandFailure(tool, "nonzero-exit", 1)), - ); - return fixtures.run(tool, arguments_); - }, - }, + sliceSelectingRunner(fixtures, selected, dyldArchitecture, calls), "darwin", ).createClient(nativeMachoTarget("/owned/universal")); @@ -104,6 +140,11 @@ it.each([ if (!result.ok) throw result.error; expect(result.value.result).toMatchObject({ uuid: "01234567-89AB-CDEF-0123-456789ABCDEF", + selected_architecture: { + name: dyldArchitecture, + container_file_offset: + architectures.findIndex((name) => name === dyldArchitecture) * 16384, + }, architectures: { items: architectures.map((name) => ({ name })), }, @@ -116,6 +157,36 @@ it.each([ }, ); +it.each([ + { capture: "calculator.txt", selected: "arm64e" }, + { capture: "shortcut-droplet.txt", selected: "arm64" }, +])( + "selects one slice when every universal slice has the target's CPU type ($capture)", + async ({ capture, selected }) => { + const base = nativeMachoTarget("/owned/universal"); + if (base.kind !== "executable") + throw new Error("Expected executable fixture"); + // Admission names arm64, arm64e and arm64e.x1 slices by one CPU family. + const target = { ...base, availableArchitectures: ["arm64"] as const }; + const fixtures = new NativeFixtureRunner({ + lipo: await nativeFixture(`lipo-same-cpu/${capture}`), + }); + const result = await new NativeMacOSProvider( + {}, + sliceSelectingRunner(fixtures, selected, selected), + "darwin", + ) + .createClient(target) + .execute("inspect_macho", {}); + + if (!result.ok) throw result.error; + expect(result.value.result).toMatchObject({ + selected_architecture: { name: selected, container_file_offset: 16384 }, + architectures: { total: 2 }, + }); + }, +); + it("projects universal segment evidence into the selected slice's container offsets", async () => { const client = new NativeMacOSProvider( {}, diff --git a/tests/boundary/setup/macosHopperPublisherVerification.test.ts b/tests/boundary/setup/macosHopperPublisherVerification.test.ts new file mode 100644 index 000000000..29b696e85 --- /dev/null +++ b/tests/boundary/setup/macosHopperPublisherVerification.test.ts @@ -0,0 +1,108 @@ +import { execFile } from "node:child_process"; +import { appendFile, copyFile, mkdir, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { promisify } from "node:util"; + +import { describe, expect, it } from "vitest"; + +import { + HOPPER_PUBLISHER, + macHopperInstallDisclosure, + systemMacHopperInstallHost, +} from "../../../src/application/MacHopper.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +const run = promisify(execFile); +const itDarwin = it.skipIf(process.platform !== "darwin"); +const executableSegments = ["Contents", "MacOS", "hopper"]; + +const infoPlist = (identifier: string): string => + ` + + + + CFBundleIdentifier + ${identifier} + CFBundleExecutable + hopper + CFBundlePackageType + APPL + + +`; + +/** Build a minimal `.app` whose launcher is a real signed Mach-O copy. */ +const buildBundle = async ( + root: string, + identifier: string, + options: { readonly sign?: boolean } = {}, +): Promise => { + const app = join(root, "Hopper Disassembler.app"); + const executable = join(app, ...executableSegments); + await mkdir(join(app, "Contents", "MacOS"), { recursive: true }); + await copyFile("/usr/bin/true", executable); + await writeFile(join(app, "Contents", "Info.plist"), infoPlist(identifier)); + if (options.sign !== false) + await run("/usr/bin/codesign", [ + "--sign", + "-", + "--force", + "--deep", + "--identifier", + identifier, + app, + ]); + return app; +}; + +const host = () => + systemMacHopperInstallHost("/home/rea-test", { ...process.env }); + +describe("macOS Hopper publisher verification", () => { + itDarwin( + "rejects an ad-hoc signed bundle carrying the pinned bundle identifier", + async () => { + const root = await createTestTempDirectory("rea-hopper-publisher-"); + const app = await buildBundle(root, HOPPER_PUBLISHER.bundleIdentifier); + // The pre-pinned checks accept this bundle: `codesign --verify` succeeds + // for ad-hoc signatures and the identifier clause alone also matches. + await run("/usr/bin/codesign", ["--verify", "--deep", "--strict", app]); + await expect(host().validBundle(app)).resolves.toBe( + "unverified_publisher", + ); + }, + ); + + itDarwin("rejects an unsigned bundle before any copy", async () => { + const root = await createTestTempDirectory("rea-hopper-unsigned-"); + const app = await buildBundle(root, HOPPER_PUBLISHER.bundleIdentifier, { + sign: false, + }); + await expect(host().validBundle(app)).resolves.toBe("invalid_signature"); + }); + + itDarwin("rejects a bundle modified after it was signed", async () => { + const root = await createTestTempDirectory("rea-hopper-tampered-"); + const app = await buildBundle(root, HOPPER_PUBLISHER.bundleIdentifier); + await appendFile(join(app, ...executableSegments), "appended\n"); + await expect(host().validBundle(app)).resolves.toBe("invalid_signature"); + }); + + it("discloses the exact code requirement the installer enforces", () => { + expect(macHopperInstallDisclosure.commands).toContain( + `codesign --verify --strict '-R= identifier "${HOPPER_PUBLISHER.bundleIdentifier}" and anchor apple generic and certificate leaf[subject.OU] = "${HOPPER_PUBLISHER.teamIdentifier}"' `, + ); + }); + + // Opt-in positive control: point this at a mounted official Hopper bundle, + // for example `hdiutil attach -readonly -nobrowse Hopper-6.6.0-demo.dmg`. + // It proves the pinned requirement is satisfiable by the real publisher, so + // a quoting or argument mistake cannot hide behind the rejection arms. + const realApp = process.env.REA_HOPPER_MACOS_APP; + it.skipIf(realApp === undefined)( + "accepts the officially signed Hopper application", + async () => { + await expect(host().validBundle(realApp ?? "")).resolves.toBe("verified"); + }, + ); +}); diff --git a/tests/boundary/signals/decoderDiscovery.test.ts b/tests/boundary/signals/decoderDiscovery.test.ts new file mode 100644 index 000000000..6b69d679f --- /dev/null +++ b/tests/boundary/signals/decoderDiscovery.test.ts @@ -0,0 +1,48 @@ +import { expect, it } from "vitest"; +import { inspectSignalDecodersInputSchema } from "../../../src/domain/signals/signalDecoders.js"; +import { parseDecoderDiscovery } from "../../../src/signals/parseDecoderDiscovery.js"; + +it("rejects malformed catalogs and the wrong decoder identity", () => { + for (const text of [ + "", + "Supported protocol decoders:\n", + "Supported protocol decoders:\n uart UART\n uart Duplicate", + "Supported protocol decoders:\n malformed", + ]) { + expect(() => + parseDecoderDiscovery(text, inspectSignalDecodersInputSchema.parse({})), + ).toThrow(); + } + expect(() => + parseDecoderDiscovery( + "ID: spi\nOptions:", + inspectSignalDecodersInputSchema.parse({ decoder: "uart" }), + ), + ).toThrow(); +}); + +it("keeps help line ordinals, blank lines and literal special characters through selection", () => { + const text = "ID: uart\r\nOptions:\r\n\r\n- mode: A[0] (default 'x')\r\n"; + const result = parseDecoderDiscovery( + text, + inspectSignalDecodersInputSchema.parse({ + decoder: "uart", + query: "[0]", + offset: 0, + limit: 1, + }), + ); + expect(result.help_lines).toEqual([ + { line_number: 4, text: "- mode: A[0] (default 'x')" }, + ]); + expect(result.output_window.examined).toBe(4); +}); + +it("bounds line expansion before constructing help records", () => { + expect(() => + parseDecoderDiscovery( + "ID: uart\n" + "\n".repeat(65536), + inspectSignalDecodersInputSchema.parse({ decoder: "uart" }), + ), + ).toThrow("representation budget"); +}); diff --git a/tests/boundary/signals/recordingProvider.test.ts b/tests/boundary/signals/recordingProvider.test.ts index 9ddf2c21a..27bc6ff09 100644 --- a/tests/boundary/signals/recordingProvider.test.ts +++ b/tests/boundary/signals/recordingProvider.test.ts @@ -1,3 +1,4 @@ +import { signalDecodersSchema } from "../../../src/domain/signals/signalDecoders.js"; import { OwnedCommandFailure } from "../../../src/process/OwnedCommand.js"; import { it, expect, onTestFinished } from "vitest"; import { writeFile, readdir, chmod, symlink } from "node:fs/promises"; @@ -23,13 +24,17 @@ const fixture = async (mode = "ok", failCleanup = false) => { await writeFile( script, `import {readFileSync, writeFileSync, chmodSync, truncateSync} from 'node:fs'; -if (process.argv.includes('--version')) { console.log('sigrok-cli 0.7.2\\nlibsigrokdecode 0.5.3'); console.error('version warning'); } +if (process.argv.includes('--version')) { console.log(${JSON.stringify(mode)} === 'bad-version' ? 'sigrok-cli 0.7.1' : 'sigrok-cli 0.7.2\\nlibsigrokdecode 0.5.3'); console.error('version warning'); } +else if (${JSON.stringify(mode)} === 'bad-version') console.log('unexpected version fallback'); else if (${JSON.stringify(mode)} === 'nonzero') { console.error('invalid decoder'); process.exitCode = 1; } else if (${JSON.stringify(mode)} === 'malformed-copy') { chmodSync('recording', 0o600); writeFileSync('recording', 'changed'); } else if (${JSON.stringify(mode)} === 'oversized-copy') { chmodSync('recording', 0o600); truncateSync('recording', 32 * 1024 * 1024 + 1); } +else if (${JSON.stringify(mode)} === 'line-budget') process.stdout.write('ID: uart' + '\\n'.repeat(65536)); else if (${JSON.stringify(mode)} === 'overflow') process.stdout.write('x'.repeat(5 * 1024 * 1024)); else if (${JSON.stringify(mode)} === 'wait') { console.log('ready'); setInterval(() => {}, 1000); } else if (${JSON.stringify(mode)} === 'many') process.stdout.write(Array.from({length:90},(_,i)=>'line '+(i+1)+'\\r\\n').join('')); +else if (process.argv.includes('--list-supported')) { console.log('Supported hardware drivers:\\n ignored Device\\nSupported protocol decoders:\\n uart Universal Asynchronous Receiver/Transmitter\\n i2c Inter-Integrated Circuit\\n'); console.error('catalog warning'); } +else if (process.argv.includes('--show')) console.log('ID: uart\\nOptions:\\n- baudrate: Baud rate (default 115200)\\n- parity: Parity'); else { if(readFileSync('recording', 'utf8') !== 'recording bytes') throw Error('wrong copy'); console.log('10-20 uart-1: 42'); console.error('producer warning'); } `, ); @@ -285,6 +290,9 @@ it("retains a completed observation when cancellation arrives at the service bou const execution = await f.service.provider.decode(input); if (!execution.ok) throw execution.error; const service = new SignalRecordingService({ + inspectDecoders: async () => { + throw new Error("Unexpected discovery call"); + }, decode: async () => { f.controller.abort(); return execution; @@ -419,3 +427,182 @@ it("preserves termination signal and effective file ceiling as a resource failur capturedOutput: { signal: "SIGXFSZ", stderr: "before file limit\n" }, }); }); + +it("discovers decoders without reading a recording and retains installation provenance", async () => { + const f = await fixture(); + for (const [input, expected] of [ + [ + { query: "UART" }, + { + decoders: [ + { id: "uart", name: "Universal Asynchronous Receiver/Transmitter" }, + ], + output_window: { + examined: 2, + matching: 1, + returned: 1, + has_more: false, + }, + }, + ], + [ + { limit: 1 }, + { + decoders: [ + { id: "uart", name: "Universal Asynchronous Receiver/Transmitter" }, + ], + output_window: { matching: 2, returned: 1, has_more: true }, + }, + ], + [ + { offset: 1, limit: null }, + { + decoders: [{ id: "i2c", name: "Inter-Integrated Circuit" }], + output_window: { returned: 1, has_more: false }, + }, + ], + [ + { decoder: "uart", query: "baud" }, + { + help_lines: [ + { line_number: 3, text: "- baudrate: Baud rate (default 115200)" }, + ], + output_window: { unit: "help-lines", examined: 4, matching: 1 }, + }, + ], + [ + { query: "no-such-decoder" }, + { + decoders: [], + output_window: { examined: 2, matching: 0, returned: 0 }, + }, + ], + ] as const) { + const result = await f.service.inspectDecoders(input); + if (!result.ok) throw result.error; + const report = signalDecodersSchema.parse(result.value.normalized_result); + expect(report).toMatchObject(expected); + expect(result.value.operation).toBe("inspect_signal_decoders"); + expect(report.tool.version_diagnostics).toBe("version warning\n"); + expect(report.tool.arguments).toContain("--dont-scan"); + expect( + report.tool.arguments.some((arg) => arg.startsWith("--input-file")), + ).toBe(false); + } + expect( + (await readdir(f.directory)).filter((name) => name.startsWith("decoder-")), + ).toEqual([]); +}); + +it("attributes discovery admission failures to discovery while sharing the decoding slot", async () => { + const f = await fixture("gated"); + const active = f.service.decode({ path: f.path, decoders: "uart" }); + await f.acquired; + const busy = await f.service.inspectDecoders({}); + f.release(); + if (!(await active).ok) throw new Error("Decode failed"); + expect(busy).toMatchObject({ + ok: false, + error: { operation: "inspect_signal_decoders", resource: "capacity" }, + }); + await f.service.close(); + expect(await f.service.inspectDecoders({})).toMatchObject({ + ok: false, + error: { + operation: "inspect_signal_decoders", + _tag: "AnalysisCancelledError", + }, + }); +}); + +it.each([ + "bad-version", + "nonzero", + "overflow", + "line-budget", + "wait", + "oversized-tool", +])("preserves discovery failure diagnostics: %s", async (mode) => { + const f = await fixture(mode); + const result = await f.service.inspectDecoders( + {}, + { signal: f.controller.signal }, + ); + expect(result.ok).toBe(false); + if (result.ok) throw new Error("Expected failure"); + expect(result.error).toMatchObject({ + operation: "inspect_signal_decoders", + }); + if (mode === "line-budget") { + expect(result.error).toMatchObject({ + _tag: "AnalysisResourceConstraintError", + }); + expect(result.error.capturedOutput?.stdout).toBe( + "ID: uart" + "\n".repeat(65536), + ); + } + if (mode === "bad-version") + expect(result.error.capturedOutput).toMatchObject({ + stdout: "sigrok-cli 0.7.1\n", + stderr: "version warning\n", + }); +}); + +it("retains completed discovery when cleanup fails, then retries before accepting work", async () => { + const f = await fixture("ok", true); + const first = await f.service.inspectDecoders({ query: "uart" }); + expect(first).toMatchObject({ + ok: false, + error: { + operation: "inspect_signal_decoders", + partialObservation: { operation: "inspect_signal_decoders" }, + }, + }); + await f.service.inspectDecoders({}); + await f.service.decode({ path: f.path, decoders: "uart" }); + expect(f.calls()).toBe(2); + for (let attempt = 0; attempt < 2; attempt++) + await expect(f.service.close()).rejects.toMatchObject({ + operation: "inspect_signal_decoders", + cleanupIncomplete: true, + }); + f.allowCleanup(); + await f.service.close(); +}); + +it("rejects ambiguous decoder selectors before launch and retains malformed help output", async () => { + const f = await fixture(); + for (const decoder of ["uart:baudrate=1", "uart,spi", "uart\0"]) { + expect(await f.service.inspectDecoders({ decoder })).toMatchObject({ + ok: false, + error: { _tag: "AnalysisInputError" }, + }); + } + expect(f.calls()).toBe(0); + expect(await f.service.inspectDecoders({ decoder: "spi" })).toMatchObject({ + ok: false, + error: { + _tag: "AnalysisOutputError", + capturedOutput: { stdout: expect.stringContaining("ID: uart") }, + }, + }); +}); + +it("retains completed discovery on cancellation during identity verification", async () => { + const f = await fixture("post-run-abort"); + expect( + await f.service.inspectDecoders( + { query: "uart" }, + { signal: f.controller.signal }, + ), + ).toMatchObject({ + ok: false, + error: { + _tag: "AnalysisCancelledError", + partialObservation: { + operation: "inspect_signal_decoders", + normalized_result: { decoders: [{ id: "uart" }] }, + }, + }, + }); +}); diff --git a/tests/ciTestSequencer.ts b/tests/ciTestSequencer.ts index 5e8c4fe5f..996e8ce7a 100644 --- a/tests/ciTestSequencer.ts +++ b/tests/ciTestSequencer.ts @@ -5,14 +5,13 @@ import { BaseSequencer, type TestSpecification } from "vitest/node"; import { z } from "zod"; const reportSchema = z.object({ + version: z.literal(1), success: z.literal(true), - numFailedTests: z.literal(0), - testResults: z.array(z.unknown()), + files: z.array(z.unknown()), }); const fileSchema = z.object({ name: z.string(), - startTime: z.number(), - endTime: z.number(), + durationMs: z.number().finite().positive(), }); export function parseTestDurations( @@ -30,15 +29,12 @@ export function parseTestDurations( if (!report.success) return undefined; const durations = new Map(); - for (const value of report.data.testResults) { + for (const value of report.data.files) { const result = fileSchema.safeParse(value); if (!result.success) continue; - const { name, startTime, endTime } = result.data; - const duration = endTime - startTime; + const { name, durationMs } = result.data; const path = relative(root, resolve(root, name)); if ( - !Number.isFinite(duration) || - duration <= 0 || path === "" || path === ".." || path.startsWith(".." + sep) || @@ -46,7 +42,7 @@ export function parseTestDurations( ) continue; const key = path.split(sep).join("/"); - durations.set(key, Math.max(durations.get(key) ?? 0, duration)); + durations.set(key, Math.max(durations.get(key) ?? 0, durationMs)); } return durations.size ? durations : undefined; } diff --git a/tests/composition/evmModuleContract.test.ts b/tests/composition/evmModuleContract.test.ts new file mode 100644 index 000000000..b04a41d93 --- /dev/null +++ b/tests/composition/evmModuleContract.test.ts @@ -0,0 +1,62 @@ +import { expect, expectTypeOf, it, vi } from "vitest"; +import { z } from "zod"; +import { evmInterfaceModule } from "../../src/composition/evm.js"; +import { wasmArtifactModule } from "../../src/composition/wasm.js"; +import { CLI_COMMANDS } from "../../src/cliCommandNames.js"; +import { INSPECT_EVM_INTERFACE_CONTRACT } from "../../src/contracts/evm/evmToolContracts.js"; + +it("rejects incompatible static bindings through the complete project typecheck", () => { + // expect-type's negative assertions are checked by tsc, not the runtime + // test runner. No malformed descriptor is registered or executed here. + expectTypeOf({ + ...evmInterfaceModule, + contract: wasmArtifactModule.contract, + }).not.toExtend(); + expectTypeOf({ + ...evmInterfaceModule, + cliCommand: CLI_COMMANDS.inspectWasmArtifact, + }).not.toExtend(); + expectTypeOf({ + ...evmInterfaceModule, + create: wasmArtifactModule.create, + }).not.toExtend(); + expectTypeOf({ + ...evmInterfaceModule, + contract: { + ...evmInterfaceModule.contract, + inputSchema: z.strictObject({ unrelated: z.string() }), + }, + }).not.toExtend(); + expectTypeOf({ + ...evmInterfaceModule, + contract: { + ...evmInterfaceModule.contract, + outputSchema: z.strictObject({ unrelated: z.string() }), + }, + }).not.toExtend(); +}); + +it("keeps the named binding and gives each caller a separate lazy service owner", async () => { + expect(evmInterfaceModule.contract).toBe(INSPECT_EVM_INTERFACE_CONTRACT); + expect(evmInterfaceModule.cliCommand).toBe(CLI_COMMANDS.inspectEvmInterface); + const first = evmInterfaceModule.create({}); + const second = evmInterfaceModule.create({}); + try { + expect(first).not.toBe(second); + expect(first.provider).not.toBe(second.provider); + await first.close(); + const inspect = vi.spyOn(second.provider, "inspect"); + const invalid = await second.inspect({ + path: "relative.hex", + encoding: "hex", + }); + expect(invalid).toMatchObject({ + ok: false, + error: { _tag: "AnalysisInputError" }, + }); + expect(inspect).not.toHaveBeenCalled(); + } finally { + await first.close(); + await second.close(); + } +}); diff --git a/tests/conformance/c/fixture.c b/tests/conformance/c/fixture.c index 6708ac9dd..e1dff9a9c 100644 --- a/tests/conformance/c/fixture.c +++ b/tests/conformance/c/fixture.c @@ -5,13 +5,24 @@ volatile int rea_c_global = 7; #define REA_LONG_CHUNK "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" #define REA_LONG_256 REA_LONG_CHUNK REA_LONG_CHUNK REA_LONG_CHUNK REA_LONG_CHUNK #define REA_LONG_1024 REA_LONG_256 REA_LONG_256 REA_LONG_256 REA_LONG_256 +/* Keep the full-size literal even when a loader does not type it as a string. */ +__attribute__((used)) const char rea_long_literal[] = + "REA_LONG_LITERAL_" REA_LONG_1024 REA_LONG_1024 REA_LONG_1024 REA_LONG_1024 "needle"; +/* Linux Hopper 6.4.2 recognizes this extent and splits it into native objects. */ +__attribute__((used)) const char rea_fragmented_literal[] = + "REA_FRAGMENTED_LITERAL_" REA_LONG_256 REA_LONG_256 "fragment_tail"; +__attribute__((used)) const char rea_utf8_literal[] = "REA_UTF8_é_😀"; +__attribute__((used)) const char rea_ellipsis_literal[] = "REA_LITERAL_…"; +__attribute__((used)) const char rea_latin1_literal[] = "REA_LATIN1_\xff"; + __attribute__((noinline, used)) void rea_long_literal_procedure(void) { - puts("REA_LONG_LITERAL_" REA_LONG_1024 REA_LONG_1024 REA_LONG_1024 REA_LONG_1024 "needle"); - puts("REA_UTF8_é_😀"); + puts(rea_long_literal); + puts(rea_fragmented_literal); + puts(rea_utf8_literal); puts("REA_ESCAPED_\"\\line\nend\t\r"); puts("REA_LITERAL_BACKSLASH_\\n"); - puts("REA_LITERAL_…"); - puts("REA_LATIN1_\xff"); + puts(rea_ellipsis_literal); + puts(rea_latin1_literal); } __attribute__((noinline, used)) int rea_leaf(int value) { diff --git a/tests/conformance/c/pie-address-context.c b/tests/conformance/c/pie-address-context.c new file mode 100644 index 000000000..970d2fc6e --- /dev/null +++ b/tests/conformance/c/pie-address-context.c @@ -0,0 +1,7 @@ +__attribute__((noinline)) int rea_pie_add(int value) { + return value + 7; +} + +int rea_pie_entry(void) { + return rea_pie_add(35); +} diff --git a/tests/conformance/ghidra/ReaFileOffsetSourceProbe.java b/tests/conformance/ghidra/ReaFileOffsetSourceProbe.java new file mode 100644 index 000000000..57da9d28e --- /dev/null +++ b/tests/conformance/ghidra/ReaFileOffsetSourceProbe.java @@ -0,0 +1,118 @@ +//@category REA Verification + +import java.io.ByteArrayInputStream; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Locale; + +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import ghidra.app.script.GhidraScriptUtil; +import ghidra.app.util.headless.HeadlessScript; +import ghidra.program.model.address.AddressSet; +import ghidra.program.model.listing.Function; +import ghidra.program.model.symbol.SourceType; +import ghidra.app.decompiler.DecompInterface; +import ghidra.app.decompiler.DecompileResults; +import ghidra.app.decompiler.DecompileProcess.DisposeState; +import ghidra.util.task.TaskMonitor; + +/** Real source-identity cases unavailable through ordinary single-file CLI imports. */ +public final class ReaFileOffsetSourceProbe extends HeadlessScript { + @Override + public void run() throws Exception { + var file = GhidraScriptUtil.findScriptByName("ReaGhidraBridge.java"); + var bridge = GhidraScriptUtil.getProvider(file).getScriptInstance(file, new PrintWriter(System.out, true)); + bridge.set(state, monitor, new PrintWriter(System.out, true)); + var space = bridge.getClass().getDeclaredField("sessionDefaultAddressSpace"); + space.setAccessible(true); + space.set(null, currentProgram.getAddressFactory().getDefaultAddressSpace()); + var identity = bridge.getClass().getDeclaredField("admittedTargetSha256"); + identity.setAccessible(true); + identity.set(bridge, currentProgram.getExecutableSHA256().toLowerCase(Locale.ROOT)); + var resolve = bridge.getClass().getDeclaredMethod("resolveDecompileProcedure", String.class, JsonObject.class); + resolve.setAccessible(true); + var reverse = bridge.getClass().getDeclaredMethod("addressToFileOffset", JsonObject.class); + reverse.setAccessible(true); + + var memory = currentProgram.getMemory(); + var original = memory.getAllFileBytes().get(0); + byte[] bytes = new byte[Math.toIntExact(original.getSize())]; + require(original.getOriginalBytes(0, bytes) == bytes.length, "complete fixture source"); + byte[] auxiliary = new byte[0x1000]; + auxiliary[0x910] = (byte)0xc3; + var foreign = memory.createFileBytes("auxiliary.bin", 0, auxiliary.length, + new ByteArrayInputStream(auxiliary), monitor); + var address = toAddr(0x140100000L); + memory.createInitializedBlock("auxiliary", address, foreign, 0, auxiliary.length, false); + var entry = address.add(0x910); + currentProgram.getFunctionManager().createFunction("foreign_only", entry, + new AddressSet(entry), SourceType.USER_DEFINED); + rejected(resolve, bridge, "no loaded source mapping", "file-offset:0x910", new JsonObject()); + rejected(reverse, bridge, "0 authoritative target-file mappings", reverseInput("0x140100910")); + + // A source object's declared original-file start does not make its local + // offsets a complete, digest-matched target representation. + var partial = memory.createFileBytes("partial.bin", 0x200, 0x200, + new ByteArrayInputStream(bytes, 0x200, 0x200), monitor); + memory.createInitializedBlock("partial", toAddr(0x140300000L), partial, 0, 0x200, false); + rejected(reverse, bridge, "0 authoritative target-file mappings", reverseInput("0x140300010")); + var selected = (Function)resolve.invoke(bridge, "file-offset:0x210", new JsonObject()); + require(selected.getEntryPoint().equals(toAddr(0x140001010L)), "original target selected despite other sources"); + var mapped = (JsonObject)reverse.invoke(bridge, reverseInput("0x140001010")); + require(mapped.get("file_offset").getAsLong() == 0x210, "original target round trip"); + + // Inject backend failures after real source/function resolution. This + // verifies context propagation, not a naturally failing decompiler. + var pseudocode = bridge.getClass().getDeclaredMethod("procedurePseudocode", JsonObject.class); + pseudocode.setAccessible(true); + var decompiler = bridge.getClass().getDeclaredField("decompiler"); + decompiler.setAccessible(true); + JsonObject request = new JsonObject(); + request.add("document", JsonNull.INSTANCE); + request.addProperty("procedure", "file-offset:0x210"); + for (DisposeState disposition : new DisposeState[] { DisposeState.NOT_DISPOSED, DisposeState.DISPOSED_ON_CANCEL }) { + decompiler.set(bridge, new DecompInterface() { + @Override + public DecompileResults decompileFunction(Function function, int timeout, TaskMonitor taskMonitor) { + return new DecompileResults(function, currentProgram.getLanguage(), + currentProgram.getCompilerSpec(), null, "Injected backend failure", null, disposition); + } + }); + Throwable failure = rejected(pseudocode, bridge, + "Selector file-offset:0x210 mapped to analysis address 0x140001010 and procedure 0x140001010", request); + var code = failure.getClass().getDeclaredField("code"); + code.setAccessible(true); + require(code.get(failure).equals(disposition == DisposeState.DISPOSED_ON_CANCEL + ? "decompile_cancelled" : "decompile_failed"), "backend failure code retained"); + } + + var duplicate = memory.createFileBytes("duplicate.bin", 0, bytes.length, + new ByteArrayInputStream(bytes), monitor); + memory.createInitializedBlock("duplicate", toAddr(0x140201000L), duplicate, 0x200, 0x200, false); + rejected(resolve, bridge, "multiple loaded mappings", "file-offset:0x210", new JsonObject()); + println("REA_FILE_OFFSET_SOURCE_OK foreign/partial rejected; original round trip; duplicate ambiguity; injected backend failure context retained"); + } + + private JsonObject reverseInput(String address) { + JsonObject params = new JsonObject(); + params.add("document", JsonNull.INSTANCE); + params.addProperty("address", address); + return params; + } + + private Throwable rejected(Method method, Object bridge, String reason, Object... arguments) throws Exception { + try { + method.invoke(bridge, arguments); + } catch (InvocationTargetException rejected) { + require(rejected.getCause().getMessage().contains(reason), "expected mapping failure: " + reason); + return rejected.getCause(); + } + throw new AssertionError("Expected mapping failure: " + reason); + } + + private void require(boolean condition, String message) { + if (!condition) throw new AssertionError(message); + } +} diff --git a/tests/conformance/providers/hopper/realHopperSearch.test.ts b/tests/conformance/providers/hopper/realHopperSearch.test.ts new file mode 100644 index 000000000..10aedb433 --- /dev/null +++ b/tests/conformance/providers/hopper/realHopperSearch.test.ts @@ -0,0 +1,97 @@ +import { expect, it } from "vitest"; + +import { verifyHopperStringObjects } from "../../../../scripts/lib/real-hopper-search.mjs"; + +const value = "REA_UTF8_é_😀"; +const address = "0x402020"; +const bytes = Buffer.from(`${value}\0`); +const item = { + address, + value, + string: { + encoding: "utf-8", + encoding_status: "inferred" as const, + termination: "present_or_not_required" as const, + byte_length: bytes.length, + }, +}; +const expectation = { + value, + encoding: "utf-8", + symbol: "rea_utf8_literal", + recognitionOptional: true, +}; + +it("keeps source identity and unknown decoding when the same text exists elsewhere", async () => { + const report = await verifyHopperStringObjects( + fixtureCall(), + [expectation], + [{ ...item, address: "0x403000" }], + ); + expect(report.recognition).toEqual([ + { value, address, state: "not_observed", decodedObject: "unverified" }, + ]); +}); + +it("reuses source bytes and inventory while checking real address filters and searches", async () => { + const calls: string[] = []; + const report = await verifyHopperStringObjects( + fixtureCall(calls), + [expectation], + [item], + ); + expect(report.recognition).toEqual([ + { value, address, state: "observed", decodedObject: "verified" }, + ]); + expect(calls).toEqual([ + "read_bytes:rea_utf8_literal", + `list_strings:${address}`, + `search_strings:${value}`, + "search_strings:\\xC3\\xA9", + ]); +}); + +it.each([ + ["changed source bytes", { bytes_hex: "00" }, item], + ["incomplete source read", { complete: false }, item], + ["wrong decoded value", {}, { ...item, value: "wrong" }], + [ + "wrong decoded extent", + {}, + { ...item, string: { ...item.string, byte_length: 1 } }, + ], +])( + "rejects %s even when native recognition is optional", + async (_label, override, decoded) => { + await expect( + verifyHopperStringObjects( + fixtureCall([], override), + [expectation], + [decoded], + ), + ).rejects.toThrow(); + }, +); + +function fixtureCall( + calls: string[] = [], + override: Record = {}, +) { + return async (name: string, arguments_: Record = {}) => { + calls.push( + `${name}:${String(arguments_.address ?? arguments_.pattern ?? "")}`, + ); + if (name === "read_bytes") + return { + address, + bytes_hex: bytes.toString("hex"), + complete: true, + ...override, + }; + if (name === "list_strings" && arguments_.address === address) + return [item]; + if (name === "search_strings") + return arguments_.pattern === value ? [item] : []; + throw new Error(`Unmodeled verifier call: ${name}`); + }; +} diff --git a/tests/evaluation/ciTestSelection.test.ts b/tests/evaluation/ciTestSelection.test.ts new file mode 100644 index 000000000..1dff7f9e3 --- /dev/null +++ b/tests/evaluation/ciTestSelection.test.ts @@ -0,0 +1,240 @@ +import { expect, it } from "vitest"; + +import { + compareTestSelection, + planTestSelection, +} from "../../scripts/ci/test-selection.mjs"; + +const sqliteSource = "src/sqlite/SqliteDatabaseProvider.test.ts"; +const sqliteBoundary = "tests/boundary/sqlite/sqliteDatabaseProvider.test.ts"; +const adbSource = "src/adb/AdbProvider.test.ts"; +const adbBoundary = + "tests/boundary/providers/adb/adbBugreportPublication.test.ts"; +const cliBoundary = "tests/boundary/cli/apktoolCli.test.ts"; +const mcpBoundary = "tests/boundary/mcp/apktoolMcp.test.ts"; +const processBoundary = + "tests/boundary/process/processCaptureLifecycle.test.ts"; +const acceptance = "tests/acceptance/tools/localToolContracts.test.ts"; +const composition = "tests/composition/directAnalysisCleanup.test.ts"; +const evaluation = "tests/evaluation/testDiscovery.test.ts"; + +const passed = (name: string) => ({ name, durationMs: 10, state: "passed" }); + +it("unions affected leaf owners, keeps changed tests and retains unowned integration tests", () => { + const plan = planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts", adbBoundary], + "pull_request", + "fast", + ); + const inventory = [ + sqliteSource, + sqliteBoundary, + adbSource, + adbBoundary, + cliBoundary, + mcpBoundary, + processBoundary, + acceptance, + composition, + evaluation, + ]; + const report = compareTestSelection(plan, inventory, inventory.map(passed)); + + expect(plan).toMatchObject({ + mode: "candidate", + owners: ["adb", "sqlite"], + }); + expect(report.selected).toEqual( + expect.arrayContaining([ + sqliteSource, + sqliteBoundary, + adbSource, + adbBoundary, + cliBoundary, + mcpBoundary, + processBoundary, + acceptance, + composition, + evaluation, + ]), + ); + expect(report.omitted).toEqual([]); +}); + +it("omits only unrelated owned tests while retaining dynamic boundary suites", () => { + const plan = planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts"], + "pull_request", + "fast", + ); + const inventory = [ + sqliteSource, + sqliteBoundary, + adbSource, + adbBoundary, + cliBoundary, + mcpBoundary, + processBoundary, + acceptance, + composition, + evaluation, + ]; + const report = compareTestSelection(plan, inventory, inventory.map(passed)); + + expect(report.selected).toEqual( + expect.arrayContaining([ + sqliteSource, + sqliteBoundary, + cliBoundary, + mcpBoundary, + processBoundary, + acceptance, + composition, + evaluation, + ]), + ); + expect(report.omitted).toEqual([adbSource, adbBoundary]); + expect(report.complete).toBe(true); +}); + +it.each([ + ["unowned shared source", "src/application/Workflow.ts"], + ["fixture input", "tests/conformance/c/fixture.c"], + ["configuration", "vitest.config.ts"], + ["documentation", "README.md"], + ["CLI implementation", "src/cli/apktoolCommands.ts"], + ["MCP implementation", "src/server/registerSqliteTools.ts"], + ["process ownership", "src/process/ProcessOwnership.ts"], + ["acceptance test", acceptance], + ["composition test", composition], +])("uses full fallback for %s changes", (_description, path) => { + expect(planTestSelection([path], "pull_request", "fast")).toMatchObject({ + mode: "full", + owners: [], + changedTests: [], + }); +}); + +it("uses full fallback outside ordinary fast pull requests or without diff paths", () => { + expect( + planTestSelection(["src/sqlite/SqliteDatabaseProvider.ts"], "push", "fast") + .mode, + ).toBe("full"); + expect( + planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts"], + "pull_request", + "full", + ).mode, + ).toBe("full"); + expect(planTestSelection([], "pull_request", "fast").mode).toBe("full"); +}); + +it("keeps new changed tests and falls back when a changed test was removed", () => { + const addedTest = "src/sqlite/NewDatabaseRule.test.ts"; + const candidate = planTestSelection([addedTest], "pull_request", "fast"); + expect(candidate.changedTests).toEqual([addedTest]); + const inventory = [addedTest, adbSource]; + expect( + compareTestSelection(candidate, inventory, inventory.map(passed)).selected, + ).toContain(addedTest); + + const removedTest = "src/sqlite/RemovedDatabaseRule.test.ts"; + const report = compareTestSelection( + planTestSelection([removedTest], "pull_request", "fast"), + [sqliteSource, adbSource], + [passed(sqliteSource), passed(adbSource)], + ); + expect(report.plan.mode).toBe("full"); + expect(report.selected).toEqual([adbSource, sqliteSource]); + expect(report.omitted).toEqual([]); +}); + +it("marks incomplete inventories and nonterminal outcomes as incomplete", () => { + const plan = planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts"], + "pull_request", + "fast", + ); + const inventory = [sqliteSource, adbSource]; + const completeResults = inventory.map(passed); + + expect( + compareTestSelection(plan, inventory, [passed(sqliteSource)]).complete, + ).toBe(false); + expect( + compareTestSelection(plan, inventory, [ + ...completeResults, + passed("tests/evaluation/unexpected.test.ts"), + ]), + ).toMatchObject({ + complete: false, + unexpected: ["tests/evaluation/unexpected.test.ts"], + }); + expect( + compareTestSelection(plan, inventory, [ + ...completeResults, + passed(adbSource), + ]), + ).toMatchObject({ complete: false, duplicateFiles: 1 }); + for (const state of ["pending", "skipped"]) + expect( + compareTestSelection(plan, inventory, [ + passed(sqliteSource), + { name: adbSource, durationMs: 0, state }, + ]), + ).toMatchObject({ complete: false, unobserved: [adbSource] }); +}); + +it("reports a failure from an omitted test, including collection or module failures", () => { + const plan = planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts"], + "pull_request", + "fast", + ); + const report = compareTestSelection( + plan, + [sqliteSource, adbSource], + [passed(sqliteSource), { name: adbSource, durationMs: 1, state: "failed" }], + ); + + expect(report.omitted).toContain(adbSource); + expect(report.missedFailures).toEqual([adbSource]); +}); + +it("rejects plans that name unowned owners or malformed changed tests", () => { + const plan = planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts"], + "pull_request", + "fast", + ); + expect(() => + compareTestSelection( + { ...plan, owners: ["unknown"] }, + [sqliteSource], + [passed(sqliteSource)], + ), + ).toThrow("Invalid observational test selection plan"); + expect(() => + compareTestSelection( + { ...plan, changedTests: ["src/sqlite/not-a-test.ts"] }, + [sqliteSource], + [passed(sqliteSource)], + ), + ).toThrow("Invalid observational test selection plan"); +}); + +it("uses full fallback when a changed owner has no executable tests", () => { + const report = compareTestSelection( + planTestSelection( + ["src/sqlite/SqliteDatabaseProvider.ts"], + "pull_request", + "fast", + ), + [adbSource], + [passed(adbSource)], + ); + + expect(report.plan.mode).toBe("full"); + expect(report.omitted).toEqual([]); +}); diff --git a/tests/evaluation/model-evals/codexAgentEval.test.ts b/tests/evaluation/model-evals/codexAgentEval.test.ts index d96265202..6b46d9b1d 100644 --- a/tests/evaluation/model-evals/codexAgentEval.test.ts +++ b/tests/evaluation/model-evals/codexAgentEval.test.ts @@ -134,6 +134,114 @@ describe("Codex agent release evaluation", () => { }); }); +describe("Codex completed tool call parsing", () => { + it("does not let an unfinished direct event reserve a completed call identity", () => { + const evidence = observation(); + const metrics = evaluateCodexEvents( + [ + { + type: "mcp_tool_call", + id: "same-call", + status: "in_progress", + server: "rea", + tool: evidence.operation, + arguments: {}, + }, + { + type: "item.completed", + item: { + id: "same-call", + type: "mcp_tool_call", + status: "completed", + server: "rea", + tool: evidence.operation, + arguments: {}, + result: { structuredContent: evidence }, + }, + }, + { + type: "item.completed", + item: { + type: "agent_message", + text: `Observed Evidence ${evidence.evidence_id} supports the artifact claim; runtime behavior remains unknown without runtime authority.`, + }, + }, + ], + evidence.operation, + { requireEvidence: true }, + ); + + expect(metrics).toMatchObject({ + naturalUse: true, + correctFirstTool: true, + reaCalls: [{ id: "same-call" }], + evidenceIds: [evidence.evidence_id], + finalCitesEvidence: true, + answerHeuristicsMet: true, + }); + }); + + it.each([ + { server: "rea", server_name: "other" }, + { tool: "inspect_managed_artifact", name: "other_tool" }, + { server: 42 }, + { arguments: { value: 1 }, input: { value: 2 } }, + ])( + "rejects completed calls with invalid or conflicting fields: %j", + (aliases) => { + const evidence = observation(); + const metrics = evaluateCodexEvents( + [ + { + type: "item.completed", + item: { + type: "mcp_tool_call", + status: "completed", + server: "rea", + tool: evidence.operation, + arguments: {}, + result: { structuredContent: evidence }, + ...aliases, + }, + }, + ], + evidence.operation, + { requiredToolSubsequence: [evidence.operation] }, + ); + + expect(metrics).toMatchObject({ + naturalUse: false, + correctFirstTool: false, + requiredToolSubsequenceMet: false, + evidenceIds: [], + }); + }, + ); + + it("preserves legacy completed calls with no server field", () => { + const metrics = evaluateCodexEvents( + [ + { + type: "item.completed", + item: { + type: "mcp_tool_call", + status: "completed", + tool: "inspect_managed_artifact", + arguments: {}, + }, + }, + ], + "inspect_managed_artifact", + ); + + expect(metrics).toMatchObject({ + naturalUse: true, + correctFirstTool: true, + reaCalls: [{ server: null }], + }); + }); +}); + describe("Codex Evidence delivery", () => { it("rejects diagnostic IDs and failed results as delivered Evidence", () => { const evidenceId = `ev_${"a".repeat(64)}`; @@ -524,28 +632,32 @@ describe("Codex agent completion evaluation", () => { }); }); - it("recognizes Codex MCP failed status when the error field is null", () => { - const metrics = evaluateCodexEvents( - [ - { - type: "item.completed", - item: { - id: "item-failed", - type: "mcp_tool_call", - server: "rea", - tool: "analyze_javascript_application", - arguments: { input_path: "/tmp/app.asar" }, - result: { structured_content: { error: { code: "denied" } } }, - error: null, - status: "failed", - }, - }, - ], - "analyze_javascript_application", - ); + it.each(["item.completed", "mcp_tool_call"] as const)( + "counts a failed completed invocation from %s without delivering Evidence", + (type) => { + const item = { + id: "item-failed", + type: "mcp_tool_call", + server: "rea", + tool: "analyze_javascript_application", + arguments: { input_path: "/tmp/app.asar" }, + result: { structured_content: { error: { code: "denied" } } }, + error: null, + status: "failed", + }; + const metrics = evaluateCodexEvents( + [type === "item.completed" ? { type, item } : item], + "analyze_javascript_application", + ); - expect(metrics.reaCalls[0]?.error).toBe(true); - }); + expect(metrics).toMatchObject({ + naturalUse: true, + correctFirstTool: true, + evidenceIds: [], + reaCalls: [{ error: true }], + }); + }, + ); }); describe("Codex agent workflow evaluation", () => { diff --git a/tests/evaluation/package/nativeAotBuild.test.ts b/tests/evaluation/package/nativeAotBuild.test.ts new file mode 100644 index 000000000..6e71db42a --- /dev/null +++ b/tests/evaluation/package/nativeAotBuild.test.ts @@ -0,0 +1,90 @@ +import { join } from "node:path"; + +import { expect, it, vi } from "vitest"; + +import { buildNativeAotFixture } from "../../../scripts/lib/nativeaot-build.mjs"; + +const options = { + dotnet: "dotnet", + project: "fixture.csproj", + runtime: "win-x64", + output: "fixture-output", +}; + +it("restores the exact publish target before compiling without network restore", async () => { + const run = vi.fn<(command: string, args: string[]) => void>(); + await buildNativeAotFixture(run, options); + expect(run).toHaveBeenCalledTimes(2); + const restore = run.mock.calls[0]?.[1] ?? []; + const publish = run.mock.calls[1]?.[1] ?? []; + expect(restore[0]).toBe("restore"); + expect(publish[0]).toBe("publish"); + expect(publish).toContain("--no-restore"); + for (const argument of [ + options.project, + options.runtime, + "-p:Configuration=Release", + `-p:BaseIntermediateOutputPath=${join(options.output, "obj")}/`, + ]) { + expect(restore).toContain(argument); + expect(publish).toContain(argument); + } +}); + +it("retries without logging credential-bearing restore diagnostics", async () => { + const logged = vi.spyOn(console, "error").mockImplementation(() => {}); + const timeout = Object.assign( + new Error( + "dotnet restore ETIMEDOUT https://fixture-user:fixture-password@feed.invalid/v3/index.json", + ), + { + code: "ETIMEDOUT", + }, + ); + const run = vi + .fn<(command: string, args: string[]) => void>() + .mockImplementationOnce(() => { + throw timeout; + }); + try { + await buildNativeAotFixture(run, options); + expect( + logged.mock.calls.flat().every((value) => typeof value === "string"), + ).toBe(true); + expect(logged.mock.calls.flat().join("\n")).not.toContain( + "fixture-password", + ); + } finally { + logged.mockRestore(); + } + expect(run.mock.calls.map((call) => call[1][0])).toEqual([ + "restore", + "restore", + "publish", + ]); +}); + +it("stops after two restore failures and preserves the final diagnostic", async () => { + const failure = new Error("NuGet source unavailable"); + const run = vi.fn<(command: string, args: string[]) => void>(() => { + throw failure; + }); + await expect(buildNativeAotFixture(run, options)).rejects.toMatchObject({ + message: "NativeAOT dependency restore failed after two attempts", + cause: failure, + }); + expect(run).toHaveBeenCalledTimes(2); + expect(run.mock.calls.every((call) => call[1][0] === "restore")).toBe(true); +}); + +it("does not retry compilation failures", async () => { + const failure = new Error("Native compiler rejected the fixture"); + const run = vi + .fn<(command: string, args: string[]) => void>() + .mockImplementationOnce(() => {}) + .mockImplementationOnce(() => { + throw failure; + }); + await expect(buildNativeAotFixture(run, options)).rejects.toBe(failure); + expect(run).toHaveBeenCalledTimes(2); +}); diff --git a/tests/evaluation/package/nativeAotDiagnostics.test.ts b/tests/evaluation/package/nativeAotDiagnostics.test.ts new file mode 100644 index 000000000..f5b42a5ce --- /dev/null +++ b/tests/evaluation/package/nativeAotDiagnostics.test.ts @@ -0,0 +1,150 @@ +import { execFile } from "node:child_process"; +import { readdir, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; + +import { expect, it } from "vitest"; + +import { + nativeAotCommandError, + supportsNativeAotFixtureHost, +} from "../../../scripts/lib/nativeaot-build.mjs"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; + +const generator = fileURLToPath( + new URL("../../../scripts/generate-nativeaot-fixtures.mjs", import.meta.url), +); + +const supportedHost = supportsNativeAotFixtureHost( + process.platform, + process.arch, +); + +it.skipIf(!supportedHost).each(["restore", "publish"])( + "redacts authenticated feed URLs from the uncaught %s diagnostic", + async (operation) => { + const directory = await createTestTempDirectory( + "rea-nativeaot-diagnostic-", + ); + const hook = join(directory, "child-output.cjs"); + await writeFile( + hook, + ` +const child = require("node:child_process"); +child.spawnSync = (_command, args) => { + if (args[0] === "--version") return { status: 0, stdout: "8.0.416\\n", stderr: "" }; + if (args[0] === ${JSON.stringify(operation)}) return { + status: 1, + error: new Error("failed HTTPS://error-user:error-secret@feed.invalid/v3/index.json"), + stdout: "NU1301 https://stdout-user:stdout-secret@feed.invalid/v3/index.json\\n", + stderr: "source https://stderr-user:stderr-secret%40suffix@feed.invalid/v3/index.json\\nkeep https://feed.invalid/path/user@name?label=token-name\\n" + }; + return { status: 0, stdout: "", stderr: "" }; +}; +require("node:module").syncBuiltinESMExports(); +`, + "utf8", + ); + const failure = await promisify(execFile)( + process.execPath, + ["--require", hook, generator], + { + env: { + ...process.env, + REA_NATIVEAOT_FIXTURE_ROOT: join(directory, "output"), + }, + timeout: 15_000, + }, + ).then( + () => { + throw new Error("Expected fixture generation to fail"); + }, + (error: { stderr: string; code: number }) => error, + ); + expect(failure.code).toBe(1); + for (const secret of [ + "error-user", + "error-secret", + "stdout-user", + "stdout-secret", + "stderr-user", + "stderr-secret", + ]) + expect(failure.stderr).not.toContain(secret); + expect(failure.stderr).toContain("NU1301"); + expect(failure.stderr).toContain("feed.invalid/v3/index.json"); + expect(failure.stderr).toContain( + "https://feed.invalid/path/user@name?label=token-name", + ); + if (operation === "restore") { + expect(failure.stderr).toContain("attempt 2/2"); + expect(failure.stderr).toContain("failed after two attempts"); + expect(failure.stderr).toContain("[cause]"); + } + }, +); + +it.skipIf(supportedHost)( + "refuses unsupported fixture hosts before tooling or output creation", + async () => { + const directory = await createTestTempDirectory("rea-nativeaot-host-"); + const hook = join(directory, "unexpected-child.cjs"); + await writeFile( + hook, + `const child = require("node:child_process"); +child.spawnSync = () => { throw new Error("Unexpected fixture tooling invocation"); }; +require("node:module").syncBuiltinESMExports(); +`, + "utf8", + ); + const failure = await promisify(execFile)( + process.execPath, + ["--require", hook, generator], + { + env: { + ...process.env, + REA_NATIVEAOT_FIXTURE_ROOT: join(directory, "output"), + }, + timeout: 15_000, + }, + ).then( + () => { + throw new Error("Expected unsupported fixture host refusal"); + }, + (error: { stderr: string; code: number }) => error, + ); + expect(failure.code).toBe(1); + expect(failure.stderr).toContain("requires Linux or Windows x64"); + expect(failure.stderr).not.toContain( + "Unexpected fixture tooling invocation", + ); + expect(await readdir(directory)).toEqual(["unexpected-child.cjs"]); + }, +); + +it("preserves diagnostics without transport authentication exactly", () => { + const error = nativeAotCommandError( + "C:/token projects/dotnet.exe", + "restore", + { + status: 1, + stdout: "NU1301 https://feed.invalid/user@name?label=password\n", + stderr: "project C:/token projects/fixture.csproj unavailable", + }, + ); + expect(error.message).toBe( + "NativeAOT fixture lane requires/action failed C:/token projects/dotnet.exe restore: exit 1\nNU1301 https://feed.invalid/user@name?label=password\nproject C:/token projects/fixture.csproj unavailable", + ); + expect(error.cause).toBeUndefined(); +}); + +it("treats HTTP backslashes as path separators rather than authentication", () => { + const output = String.raw`https://feed.invalid\path\user@name`; + expect(new URL(output).username).toBe(""); + const error = nativeAotCommandError("dotnet", "restore", { + status: 1, + stdout: output, + }); + expect(error.message).toContain(output); +}); diff --git a/tests/fixtures/evm/interface.ts b/tests/fixtures/evm/interface.ts index 23bfcfa02..f0f1960ba 100644 --- a/tests/fixtures/evm/interface.ts +++ b/tests/fixtures/evm/interface.ts @@ -1,5 +1,6 @@ import { createHash } from "node:crypto"; import { createAnalysisExecution } from "../../../src/application/AnalysisProvider.js"; +import type { EvmInterfaceExecution } from "../../../src/application/evm/EvmInterfacePort.js"; import type { EvmInterface } from "../../../src/domain/evm/evmInterface.js"; /** Source-owned transport seam, independent of real engine verification. */ @@ -27,8 +28,10 @@ export const evmInterfaceFixture = ( }); /** Bind a fixture to its explicit producing seam and carrier identity. */ -export const evmInterfaceExecution = (value = evmInterfaceFixture()) => - createAnalysisExecution( +export const evmInterfaceExecution = ( + value = evmInterfaceFixture(), +): EvmInterfaceExecution => { + return createAnalysisExecution( value, { id: "fixture-evm", name: "Source-owned EVM seam", version: "1" }, { @@ -42,3 +45,4 @@ export const evmInterfaceExecution = (value = evmInterfaceFixture()) => locations: [{ kind: "artifact-path", path: value.artifact.path }], }, ); +}; diff --git a/tests/fixtures/hopperLifetimeLaunch.py b/tests/fixtures/hopperLifetimeLaunch.py new file mode 100644 index 000000000..68d65c9ff --- /dev/null +++ b/tests/fixtures/hopperLifetimeLaunch.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +"""Inspect the real Node launcher stdio with the production lifetime parser.""" + +import importlib.util +import json +from pathlib import Path +import sys + +spec = importlib.util.spec_from_file_location( + "hopper_demo_x11", Path(__file__).resolve().parents[2] / "scripts/hopper-demo-x11.py" +) +assert spec is not None and spec.loader is not None +helper = importlib.util.module_from_spec(spec) +spec.loader.exec_module(helper) +assert "--owner-stdin" in sys.argv +print(json.dumps({"owner_alive": helper.OwnerLifetime(True).alive()})) diff --git a/tests/fixtures/hopperOwnerLifetime.py b/tests/fixtures/hopperOwnerLifetime.py new file mode 100644 index 000000000..741bffbd9 --- /dev/null +++ b/tests/fixtures/hopperOwnerLifetime.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +"""Exercise the production runner with real children and a simulated X11 surface.""" + +import argparse +import importlib.util +import json +from pathlib import Path +import signal +import subprocess +import sys +import tempfile +import time + + +spec = importlib.util.spec_from_file_location("hopper_demo_x11", sys.argv[1]) +assert spec is not None and spec.loader is not None +helper = importlib.util.module_from_spec(spec) +spec.loader.exec_module(helper) + + +def child_command(receipt): + return [ + sys.executable, + "-c", + "import os,pathlib,time;" + f"receipt=pathlib.Path({str(receipt)!r});" + "pending=receipt.with_suffix('.pending');" + "pending.write_text(str(os.getpid()));pending.replace(receipt);" + "time.sleep(100)", + ] + + +if len(sys.argv) > 3: + phase, directory = sys.argv[2], Path(sys.argv[3]) + + def terminate_worker(*_): + raise SystemExit(143) + + # Failed assertions in the parent must still unwind run_launch's finally. + signal.signal(signal.SIGTERM, terminate_worker) + + class X11: + def XOpenDisplay(self, *_): + return 1 + + def XDefaultRootWindow(self, *_): + return 1 + + def XDisplayWidth(self, *_): + return 1280 + + def XDisplayHeight(self, *_): + return 1024 + + def XCloseDisplay(self, *_): + return 1 + + def start_xvfb(*_): + child = subprocess.Popen( + child_command(directory / "xvfb.pid"), + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE, + ) + return child, ":123", directory / "Xauthority", helper.CapturedStderr(child.stderr) + + helper.digest = lambda _: next(iter(helper.SUPPORTED_HOPPER_SHA256)) + helper.start_xvfb = start_xvfb + helper.ctypes.CDLL = lambda _: X11() + helper.configure_x11 = lambda *_: None + helper.windows = lambda *_: [] + socket = directory / "bridge.sock" + if phase == "ready": + socket.touch() + raise SystemExit(helper.run_launch(argparse.Namespace( + owner_stdin=True, + hopper=sys.executable, + socket=str(socket), + command=child_command(directory / "hopper.pid"), + ))) + + +with tempfile.TemporaryDirectory(prefix="rea-owner-lifetime-") as root: + directory = Path(root) + sentinel = subprocess.Popen([sys.executable, "-c", "import time;time.sleep(100)"]) + worker = subprocess.Popen( + [sys.executable, __file__, sys.argv[1], sys.argv[2], root], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + try: + deadline = time.monotonic() + 5 + receipts = [directory / "hopper.pid", directory / "xvfb.pid"] + while not all(receipt.exists() for receipt in receipts): + assert worker.poll() is None, worker.communicate() + assert time.monotonic() < deadline, "owned children did not start" + time.sleep(0.01) + pids = [int(receipt.read_text()) for receipt in receipts] + assert worker.poll() is None, "live owner did not retain the helper" + assert worker.stdin is not None + worker.stdin.close() + assert worker.wait(timeout=5) == 0, worker.stderr.read() + for pid in pids: + assert not Path(f"/proc/{pid}").exists(), f"owned child {pid} survived EOF" + assert sentinel.poll() is None, "unrelated process was stopped" + print(json.dumps({"phase": sys.argv[2], "children_cleaned": True, "sentinel_alive": True})) + finally: + helper.stop_process(worker) + helper.stop_process(sentinel) diff --git a/tests/fixtures/localToolsMcp.ts b/tests/fixtures/localToolsMcp.ts index 1e1e91909..bf9c7617a 100644 --- a/tests/fixtures/localToolsMcp.ts +++ b/tests/fixtures/localToolsMcp.ts @@ -34,7 +34,9 @@ const compileValidator = (schema: unknown): ValidateFunction => { }; /** Start the built production server without configuring deep binary providers. */ -export async function connectLocalToolsMcp() { +export async function connectLocalToolsMcp( + environment: Readonly> = {}, +) { const transport = new StdioClientTransport({ command: process.execPath, args: [ @@ -45,6 +47,7 @@ export async function connectLocalToolsMcp() { PATH: process.env.PATH ?? "/usr/bin:/bin", REA_LOG_LEVEL: "silent", HOPPER_LAUNCHER_PATH: "/rea-unconfigured-deep-provider/hopper", + ...environment, }, stderr: "pipe", }); diff --git a/tests/fixtures/native-macos/lipo-same-cpu/README.md b/tests/fixtures/native-macos/lipo-same-cpu/README.md new file mode 100644 index 000000000..d376e3b5d --- /dev/null +++ b/tests/fixtures/native-macos/lipo-same-cpu/README.md @@ -0,0 +1,19 @@ +# Universal Mach-O captures whose slices share one CPU type + +Captured on macOS 27.0.1 (26A434), arm64, from two system executables whose +FAT slices all use `CPU_TYPE_ARM64`: + +```sh +lipo -detailed_info /System/Applications/Calculator.app/Contents/MacOS/Calculator > calculator.txt +lipo -detailed_info /System/Library/CoreServices/ShortcutDroplet.app/Contents/MacOS/ShortcutDroplet > shortcut-droplet.txt +``` + +Calculator holds `arm64e` (subtype `0x80000002`) and `arm64e.x1` (subtype +`0x8000000c`); ShortcutDroplet holds `arm64` (subtype `0`) and `arm64e.x1`. +Target admission names both files by the single CPU family `arm64`, while lipo +lists two slices. + +The executable path on the `Fat header in:` line was replaced with `fixture`, +and trailing whitespace (lipo prints `capabilities ` for a slice without +capabilities) and the final blank line were removed. Tool fields are otherwise +unchanged. diff --git a/tests/fixtures/native-macos/lipo-same-cpu/calculator.txt b/tests/fixtures/native-macos/lipo-same-cpu/calculator.txt new file mode 100644 index 000000000..8e90b4902 --- /dev/null +++ b/tests/fixtures/native-macos/lipo-same-cpu/calculator.txt @@ -0,0 +1,17 @@ +Fat header in: fixture +fat_magic 0xcafebabe +nfat_arch 2 +architecture arm64e + cputype CPU_TYPE_ARM64 + cpusubtype CPU_SUBTYPE_ARM64E + capabilities PTR_AUTH_VERSION USERSPACE 0 + offset 16384 + size 1727552 + align 2^14 (16384) +architecture arm64e.x1 + cputype CPU_TYPE_ARM64 + cpusubtype unknown arm64 cpusubtype + capabilities PTR_AUTH_VERSION USERSPACE 0 + offset 1753088 + size 1711088 + align 2^14 (16384) diff --git a/tests/fixtures/native-macos/lipo-same-cpu/shortcut-droplet.txt b/tests/fixtures/native-macos/lipo-same-cpu/shortcut-droplet.txt new file mode 100644 index 000000000..252ff7234 --- /dev/null +++ b/tests/fixtures/native-macos/lipo-same-cpu/shortcut-droplet.txt @@ -0,0 +1,17 @@ +Fat header in: fixture +fat_magic 0xcafebabe +nfat_arch 2 +architecture arm64 + cputype CPU_TYPE_ARM64 + cpusubtype CPU_SUBTYPE_ARM64_ALL + capabilities + offset 16384 + size 52000 + align 2^14 (16384) +architecture arm64e.x1 + cputype CPU_TYPE_ARM64 + cpusubtype unknown arm64 cpusubtype + capabilities PTR_AUTH_VERSION USERSPACE 0 + offset 81920 + size 52000 + align 2^14 (16384) diff --git a/tests/fixtures/pcap/capinfos-stub.cmd b/tests/fixtures/pcap/capinfos-stub.cmd new file mode 100644 index 000000000..6f783bcf5 --- /dev/null +++ b/tests/fixtures/pcap/capinfos-stub.cmd @@ -0,0 +1,19 @@ +@echo off +rem capinfos stub for Windows: emulates capinfos --version and metadata output. + +if "%~1"=="--version" ( + echo Capinfos ^(Wireshark^) 4.6.6-windows-stub + exit /b 0 +) + +if not "%~1"=="-M" exit /b 2 +if not "%~2"=="--" exit /b 2 +if "%~3"=="" exit /b 2 + +echo File name: capture.pcap +echo File type: Wireshark/tcpdump/... - pcap +echo File encapsulation: Ethernet +echo Packet size limit: file hdr: 262144 bytes +echo Number of packets: 3 +echo Capture duration: 0.123 seconds +exit /b 0 diff --git a/tests/fixtures/pcap/capinfos-stub.sh b/tests/fixtures/pcap/capinfos-stub.sh new file mode 100755 index 000000000..47d61b1b1 --- /dev/null +++ b/tests/fixtures/pcap/capinfos-stub.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# POSIX capinfos stub (mirrors capinfos-stub.cmd for Windows parity). +if [ "$1" = "--version" ]; then printf 'Capinfos (Wireshark) 4.6.6-posix-stub\n'; exit 0; fi +[ "$1" = "-M" ] && [ "$2" = "--" ] && [ "$#" = "3" ] || exit 2 +printf '%s\n' 'File name: capture.pcap' +printf '%s\n' 'File type: Wireshark/tcpdump/... - pcap' +printf '%s\n' 'File encapsulation: Ethernet' +printf '%s\n' 'Packet size limit: file hdr: 262144 bytes' +printf '%s\n' 'Number of packets: 3' +printf '%s\n' 'Capture duration: 0.123 seconds' +exit 0 diff --git a/tests/fixtures/pcap/tshark-stub.cmd b/tests/fixtures/pcap/tshark-stub.cmd new file mode 100644 index 000000000..d157ed721 --- /dev/null +++ b/tests/fixtures/pcap/tshark-stub.cmd @@ -0,0 +1,17 @@ +@echo off +rem Pcap tool stub for Windows: emulates tshark --version and field output. +rem %1 is the first argument; the capture path arrives as %2 for -r/-c. + +if "%~1"=="--version" ( + echo TShark ^(Wireshark^) 4.6.6-windows-stub + exit /b 0 +) + +if not "%~1"=="-n" exit /b 2 +if not "%~2"=="-r" exit /b 2 +if not "%~4"=="-T" exit /b 2 +if not "%~5"=="json" exit /b 2 + +rem Emit the same JSON as the POSIX stub +echo [{"_source":{"layers":{"frame.number":["1"],"frame.protocols":["eth:ethertype:ip:udp:dns"],"ip.src":["192.168.1.100"],"ip.dst":["8.8.8.8"],"dns.qry.name":["api.example.com"],"dns.flags.response":["1"],"dns.a":["93.184.216.34"]}}},{"_source":{"layers":{"frame.number":["2"],"frame.protocols":["eth:ethertype:ip:tcp:tls"],"ip.src":["192.168.1.100"],"ip.dst":["93.184.216.34"],"tls.handshake.extensions_server_name":["api.example.com"]}}},{"_source":{"layers":{"frame.number":["3"],"frame.protocols":["eth:ethertype:ip:tcp:http"],"ip.src":["192.168.1.100"],"ip.dst":["93.184.216.34"],"http.request.full_uri":["http://api.example.com/v1/data"]}}}] +exit /b 0 diff --git a/tests/fixtures/pcap/tshark-stub.sh b/tests/fixtures/pcap/tshark-stub.sh new file mode 100755 index 000000000..8633dd7c0 --- /dev/null +++ b/tests/fixtures/pcap/tshark-stub.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# POSIX pcap tool stub (mirrors tshark-stub.cmd for Windows parity). +if [ "$1" = "--version" ]; then printf 'TShark (Wireshark) 4.6.6-posix-stub\n'; exit 0; fi +[ "$1" = "-n" ] && [ "$2" = "-r" ] && [ "$4" = "-T" ] && [ "$5" = "json" ] || exit 2 +printf '%s' '[{"_source":{"layers":{"frame.number":["1"],"frame.protocols":["eth:ethertype:ip:udp:dns"],"ip.src":["192.168.1.100"],"ip.dst":["8.8.8.8"],"dns.qry.name":["api.example.com"],"dns.flags.response":["1"],"dns.a":["93.184.216.34"]}}},{"_source":{"layers":{"frame.number":["2"],"frame.protocols":["eth:ethertype:ip:tcp:tls"],"ip.src":["192.168.1.100"],"ip.dst":["93.184.216.34"],"tls.handshake.extensions_server_name":["api.example.com"]}}},{"_source":{"layers":{"frame.number":["3"],"frame.protocols":["eth:ethertype:ip:tcp:http"],"ip.src":["192.168.1.100"],"ip.dst":["93.184.216.34"],"http.request.full_uri":["http://api.example.com/v1/data"]}}}]' +exit 0 diff --git a/tests/fixtures/wasm/artifact.ts b/tests/fixtures/wasm/artifact.ts index d4cc803b4..3b615ca06 100644 --- a/tests/fixtures/wasm/artifact.ts +++ b/tests/fixtures/wasm/artifact.ts @@ -1,5 +1,6 @@ import { createHash } from "node:crypto"; import { createAnalysisExecution } from "../../../src/application/AnalysisProvider.js"; +import type { WasmArtifactExecution } from "../../../src/application/wasm/WasmArtifactPort.js"; import type { WasmArtifact } from "../../../src/domain/wasm/wasmArtifact.js"; /** Source-owned transport seam; upstream binaries are verified in a separate lane. */ export const wasmArtifactFixture = ( @@ -42,8 +43,10 @@ export const wasmArtifactFixture = ( network_fetch: "not-performed" as const, limitations: ["Source-owned transport seam."], }); -export const wasmArtifactExecution = (value = wasmArtifactFixture()) => - createAnalysisExecution( +export const wasmArtifactExecution = ( + value = wasmArtifactFixture(), +): WasmArtifactExecution => { + return createAnalysisExecution( value, { id: "fixture-wabt", name: "Source-owned WABT seam", version: "1" }, { @@ -55,3 +58,4 @@ export const wasmArtifactExecution = (value = wasmArtifactFixture()) => limitations: value.limitations, }, ); +}; diff --git a/tests/fixtures/windows/processBoundary.cc b/tests/fixtures/windows/processBoundary.cc index 18dcb2dbd..05ee218e8 100644 --- a/tests/fixtures/windows/processBoundary.cc +++ b/tests/fixtures/windows/processBoundary.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,41 @@ int wmain(int count, wchar_t** args) { value(L"REA_\u00df") == expectedSharp && value(L"REA_SS") == L"double" ? "true" : "false"); return 0; } + if ((count == 2 || count == 3) && std::wstring(args[1]) == L"affinity") { + // Without a process id this observes itself, which is what an owned child + // reports. With one it observes that process, so a caller's own affinity is + // read from the process that spawns the child rather than from a separate + // probe Windows may place in another processor group. + HANDLE opened = nullptr; + if (count == 3) { + opened = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, + static_cast(std::wcstoul(args[2], nullptr, 10))); + if (!opened) return 9; + } + const HANDLE target = opened ? opened : GetCurrentProcess(); + DWORD_PTR affinity = 0, systemAffinity = 0; + USHORT groupCount = 1; + USHORT groups[1]{}; + const bool read = GetProcessAffinityMask(target, &affinity, &systemAffinity) != 0; + const bool single = read && GetProcessGroupAffinity(target, &groupCount, groups) && groupCount == 1; + if (opened) CloseHandle(opened); + if (!read) return 8; + // A mask can set bits above JavaScript's safe-integer range, so masks cross + // as fixed-width hexadecimal strings and are compared without rounding. The + // group's own active set distinguishes an unconstrained process from one + // deliberately pinned to fewer processors. + auto mask = [](DWORD_PTR value, char* text) { + std::snprintf(text, 19, "0x%08lX%08lX", static_cast(value >> 32), + static_cast(value & 0xFFFFFFFFu)); + return text; + }; + char affinityText[19]{}, systemText[19]{}; + std::printf("{\"affinityMask\":\"%s\",\"systemMask\":\"%s\"," + "\"singleProcessorGroup\":%s,\"processorGroup\":%u}\n", + mask(affinity, affinityText), mask(systemAffinity, systemText), + single ? "true" : "false", single ? static_cast(groups[0]) : 0u); + return 0; + } if (count == 4 && std::wstring(args[1]) == L"reparse-directory") { // Only the conformance lane's disposable, nonempty source directory is used. const auto substitute = L"\\??\\" + std::wstring(args[3]); diff --git a/tests/process-global/cleanLinuxHopperRuntime.test.ts b/tests/process-global/cleanLinuxHopperRuntime.test.ts new file mode 100644 index 000000000..d356f5abf --- /dev/null +++ b/tests/process-global/cleanLinuxHopperRuntime.test.ts @@ -0,0 +1,113 @@ +import { execFile } from "node:child_process"; +import { randomUUID } from "node:crypto"; +import { chmod, copyFile, readFile, symlink, unlink } from "node:fs/promises"; +import { join } from "node:path"; +import { promisify } from "node:util"; + +import { expect, it } from "vitest"; + +import { assertCleanLinuxHopperRuntime } from "../../scripts/lib/clean-linux-hopper-runtime.mjs"; +import { completeVerifierRun } from "../../scripts/lib/verifier-run.mjs"; +import { cleanupOwnedProcessGroup } from "../../src/process/ProcessOwnership.js"; +import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js"; + +const execFileAsync = promisify(execFile); + +it + .runIf(process.platform === "linux") + .each(["demo helper", "alternate launcher"])( + "rejects a reparented %s without signaling it", + async (mode) => { + const runId = randomUUID(); + const childCode = + "process.title = 'Xvfb'; setInterval(() => {}, 1000); process.send('ready');"; + const directory = await createTestTempDirectory("rea-clean-runtime-test-"); + const launcher = join(directory, "Hopper"); + const alternate = join(directory, "Hopper-alternate"); + const alternateMode = mode === "alternate launcher"; + if (alternateMode) { + await copyFile("/usr/bin/sleep", launcher); + await chmod(launcher, 0o700); + await symlink(launcher, alternate); + } + const command = alternateMode ? alternate : process.execPath; + const arguments_ = alternateMode ? ["30"] : ["-e", childCode]; + const parentCode = ` + const { spawn } = require('node:child_process'); + const child = spawn(${JSON.stringify(command)}, ${JSON.stringify(arguments_)}, { + detached: true, stdio: ${JSON.stringify(alternateMode ? "ignore" : ["ignore", "ignore", "ignore", "ipc"])} + }); + child.once('error', () => process.exit(1)); + child.once(${JSON.stringify(alternateMode ? "spawn" : "message")}, () => { + process.stdout.write(JSON.stringify({ pid: child.pid, parentPid: process.pid })); + if (child.connected) child.disconnect(); + child.unref(); + }); + `; + const parent = execFileAsync(process.execPath, ["-e", parentCode], { + env: { ...process.env, REA_PROCESS_RUN_ID: runId }, + timeout: 10_000, + }); + const parentPid = parent.child.pid; + if (parentPid === undefined) + throw new Error("Fixture parent did not spawn"); + let orphanPid: number | undefined; + try { + const { stdout } = await parent; + const { pid } = JSON.parse(stdout) as { pid: number }; + orphanPid = pid; + const { stdout: coordinates } = await execFileAsync("ps", [ + "-p", + String(pid), + "-o", + "ppid=,pgid=", + ]); + const [currentParent, group] = coordinates + .trim() + .split(/\s+/u) + .map(Number); + expect(currentParent).not.toBe(parentPid); + expect(group).toBe(pid); + + const lineage = await completeVerifierRun({ + run_id: runId, + verifier_pid: process.pid, + parent_pid: process.ppid, + }); + expect(lineage.process_lineage.status).toBe("verified"); + if (lineage.process_lineage.status === "verified") + expect( + lineage.process_lineage.descendants.some((p) => p.pid === pid), + ).toBe(false); + + if (alternateMode) { + const commandLine = await readFile( + `/proc/${String(pid)}/cmdline`, + "utf8", + ); + expect(commandLine.split("\0")[0]).toBe(alternate); + await unlink(alternate); + } + await expect( + assertCleanLinuxHopperRuntime(alternateMode ? [launcher] : []), + ).rejects.toThrow("Clean Linux runner retained a Hopper demo process"); + // Observation must not terminate the fixture, even though it resembles Xvfb. + const { stdout: alive } = await execFileAsync("ps", [ + "-p", + String(pid), + "-o", + "stat=", + ]); + expect(alive.trim()).not.toMatch(/^Z/u); + } finally { + if (orphanPid !== undefined) { + const cleanup = await cleanupOwnedProcessGroup({ + runId, + leaderPid: orphanPid, + processGroupId: orphanPid, + }); + expect(cleanup.cleaned, JSON.stringify(cleanup)).toBe(true); + } + } + }, +); diff --git a/tests/process-global/pwntoolsStageRetirement.test.ts b/tests/process-global/pwntoolsStageRetirement.test.ts index bcdaf858f..6ec062535 100644 --- a/tests/process-global/pwntoolsStageRetirement.test.ts +++ b/tests/process-global/pwntoolsStageRetirement.test.ts @@ -261,6 +261,14 @@ it.runIf(supportedHost).each([ if (result.ok) throw new Error("Expected unresolved process ownership"); const projected = projectAnalysisError(result.error); expect(projected.code).toBe("cleanup_incomplete"); + expect(projected).toMatchObject({ + details: { + resources: expect.arrayContaining([ + expect.stringMatching(/^pid:\d+$/u), + expect.stringMatching(/^process-group:\d+$/u), + ]), + }, + }); if (stage === "debugger") expect(projected).toMatchObject({ details: { diff --git a/tests/process-global/regularFileNoFollowFallback.test.ts b/tests/process-global/regularFileNoFollowFallback.test.ts new file mode 100644 index 000000000..44ce66c7c --- /dev/null +++ b/tests/process-global/regularFileNoFollowFallback.test.ts @@ -0,0 +1,55 @@ +import { readFile, symlink } from "node:fs/promises"; +import { join } from "node:path"; + +import { expect, it, vi } from "vitest"; + +vi.mock("node:fs", async (importOriginal) => { + const original = await importOriginal(); + return { + ...original, + constants: { ...original.constants, O_NOFOLLOW: 0 }, + }; +}); + +import { openRegularFile } from "../../src/filesystem/RegularFile.js"; +import { ZipArtifactReader } from "../../src/artifacts/ZipArtifactReader.js"; +import { writeOrderedZip } from "../fixtures/artifactEntryOrder.js"; +import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js"; + +it("rejects a symlink when O_NOFOLLOW is unavailable and still follows when requested", async () => { + const root = await createTestTempDirectory("rea-no-nofollow-"); + const target = join(root, "target.zip"); + const link = join(root, "selected.zip"); + await writeOrderedZip(target, ["member.bin"]); + await symlink(target, link); + + const reader = new ZipArtifactReader(target, "zip"); + try { + const entries = []; + for await (const entry of reader.entries()) entries.push(entry); + expect(entries.map(({ path }) => path)).toEqual(["member.bin"]); + } finally { + await reader.close(); + } + + const linkedReader = new ZipArtifactReader(link, "zip"); + try { + await expect(async () => { + for await (const _entry of linkedReader.entries()) { + // Consume through the public reader boundary. + } + }).rejects.toMatchObject({ + name: "ArtifactReaderFailure", + reason: "format", + }); + } finally { + await linkedReader.close(); + } + + const followed = await openRegularFile(link, { symlinks: "follow" }); + try { + await expect(readFile(followed)).resolves.toEqual(await readFile(target)); + } finally { + await followed.close(); + } +}); diff --git a/tests/process-global/setupConfigurationRollback.test.ts b/tests/process-global/setupConfigurationRollback.test.ts new file mode 100644 index 000000000..cf6504c32 --- /dev/null +++ b/tests/process-global/setupConfigurationRollback.test.ts @@ -0,0 +1,325 @@ +import { open, readFile } from "node:fs/promises"; +import { createHash } from "node:crypto"; +import { join } from "node:path"; + +import { afterEach, expect, it, onTestFinished, vi } from "vitest"; + +const state = vi.hoisted(() => ({ + readbackFailed: false, + rejectRestore: false, + rejectRemove: false, + removeCopiedRecovery: false, + initialCleanupFailure: undefined as unknown, + readbackCleanupFailure: undefined as unknown, +})); + +afterEach(() => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.removeCopiedRecovery = false; + state.initialCleanupFailure = undefined; + state.readbackCleanupFailure = undefined; +}); + +vi.mock("node:fs/promises", async (importOriginal) => { + const original = await importOriginal(); + return { + ...original, + rm: ( + ...arguments_: Parameters + ): ReturnType => { + if (state.rejectRemove && state.readbackFailed) + return Promise.reject(new Error("injected restore remove failure")); + return original.rm(...arguments_); + }, + writeFile: ( + ...arguments_: Parameters + ): ReturnType => { + if (state.rejectRestore && state.readbackFailed) + return Promise.reject(new Error("injected restore write failure")); + return original.writeFile(...arguments_); + }, + copyFile: async ( + ...arguments_: Parameters + ): Promise => { + await original.copyFile(...arguments_); + const destination = arguments_[1]; + if ( + state.removeCopiedRecovery && + typeof destination === "string" && + destination.endsWith(".recovery") + ) + await original.rm(destination); + }, + }; +}); + +vi.mock("write-file-atomic", async (importOriginal) => { + const original = await importOriginal<{ + default: typeof import("write-file-atomic"); + }>(); + return { + ...original, + default: async (...arguments_: Parameters) => { + if (state.initialCleanupFailure !== undefined) + throw new Error("unexpected config write before initial read"); + const result = await original.default(...arguments_); + state.readbackFailed = true; + return result; + }, + }; +}); + +vi.mock("../../src/application/RegularFileRead.js", async (importOriginal) => { + const original = + await importOriginal< + typeof import("../../src/application/RegularFileRead.js") + >(); + return { + ...original, + readRegularFileText: ( + ...arguments_: Parameters + ) => + state.initialCleanupFailure !== undefined + ? Promise.reject(state.initialCleanupFailure) + : state.readbackFailed && state.readbackCleanupFailure !== undefined + ? Promise.reject(state.readbackCleanupFailure) + : state.readbackFailed + ? Promise.reject(new Error("injected readback failure")) + : original.readRegularFileText(...arguments_), + }; +}); + +import { configureClientConfiguration } from "../../src/application/SetupClientConfiguration.js"; +import { RegularFileCleanupFailure } from "../../src/application/RegularFileRead.js"; +import { OwnedFileHandle } from "../../src/filesystem/OwnedFileHandle.js"; +import type { DoctorHost } from "../../src/application/Doctor.js"; +import { systemSetupHost } from "../../src/application/SetupHost.js"; +import { ConfigurationError } from "../../src/domain/configurationErrors.js"; +import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js"; + +const ownReadHandle = async (path: string) => { + const owner = new OwnedFileHandle(await open(path, "r")); + onTestFinished(() => owner.close()); + return owner; +}; + +it("reports a failed config rollback and retains its backup path", async () => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.initialCleanupFailure = undefined; + state.readbackCleanupFailure = undefined; + const root = await createTestTempDirectory("rea-config-rollback-"); + const path = join(root, "client.json"); + const original = '{"keep":true}\n'; + await import("node:fs/promises").then(({ writeFile }) => + writeFile(path, original), + ); + state.rejectRestore = true; + + const result = await configureClientConfiguration( + { name: "cursor", configPath: path, format: "json" }, + {}, + ["rea", "mcp"], + ); + + expect(result).toEqual({ + status: "failed", + reason: "rollback", + backupPath: `${path}.rea.backup`, + failure: { + kind: "restore", + path, + detail: "injected restore write failure", + }, + }); + expect(await readFile(`${path}.rea.backup`, "utf8")).toBe(original); + expect(JSON.parse(await readFile(path, "utf8"))).toMatchObject({ + mcpServers: { rea: { command: "rea", args: ["mcp"] } }, + }); +}); + +it("preserves the first backup and reports a verified backup of the current original", async () => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.initialCleanupFailure = undefined; + state.readbackCleanupFailure = undefined; + const root = await createTestTempDirectory("rea-config-stale-backup-"); + const path = join(root, "client.json"); + const firstOriginal = '{"keep":"first"}\n'; + const currentOriginal = '{"keep":"current"}\n'; + await import("node:fs/promises").then(async ({ writeFile }) => { + await writeFile(path, currentOriginal); + await writeFile(`${path}.rea.backup`, firstOriginal); + }); + state.rejectRestore = true; + + const result = await configureClientConfiguration( + { name: "cursor", configPath: path, format: "json" }, + {}, + ["rea", "mcp"], + ); + state.rejectRestore = false; + + const recoveryPath = `${path}.rea.backup.${createHash("sha256") + .update(currentOriginal, "utf8") + .digest("hex")}.recovery`; + expect(result).toMatchObject({ + status: "failed", + reason: "rollback", + backupPath: recoveryPath, + failure: { + kind: "restore", + path, + detail: "injected restore write failure", + }, + }); + expect(await readFile(`${path}.rea.backup`, "utf8")).toBe(firstOriginal); + expect(await readFile(recoveryPath, "utf8")).toBe(currentOriginal); +}); + +it("does not write config when a recovery copy disappears before verification", async () => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.removeCopiedRecovery = false; + state.initialCleanupFailure = undefined; + state.readbackCleanupFailure = undefined; + const root = await createTestTempDirectory("rea-config-vanished-recovery-"); + const path = join(root, "client.json"); + const firstOriginal = '{"keep":"first"}\n'; + const currentOriginal = '{"keep":"current"}\n'; + await import("node:fs/promises").then(async ({ writeFile }) => { + await writeFile(path, currentOriginal); + await writeFile(`${path}.rea.backup`, firstOriginal); + }); + state.removeCopiedRecovery = true; + + const result = await configureClientConfiguration( + { name: "cursor", configPath: path, format: "json" }, + {}, + ["rea", "mcp"], + ); + state.removeCopiedRecovery = false; + + expect(result).toEqual({ status: "failed", reason: "backup" }); + expect(await readFile(path, "utf8")).toBe(currentOriginal); + expect(await readFile(`${path}.rea.backup`, "utf8")).toBe(firstOriginal); +}); + +it("does not roll back or remove config when its initial read cleanup fails", async () => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.readbackCleanupFailure = undefined; + const root = await createTestTempDirectory("rea-config-initial-cleanup-"); + const path = join(root, "client.json"); + const original = '{"keep":true}\n'; + await import("node:fs/promises").then(({ writeFile }) => + writeFile(path, original), + ); + const failure = new RegularFileCleanupFailure( + path, + await ownReadHandle(path), + { kind: "completed", value: original }, + new Error("injected initial close failure"), + ); + state.initialCleanupFailure = failure; + + await expect( + configureClientConfiguration( + { name: "cursor", configPath: path, format: "json" }, + {}, + ["rea", "mcp"], + ), + ).rejects.toBe(failure); + expect(await readFile(path, "utf8")).toBe(original); +}); + +it("reports first-run rollback removal failure without a backup", async () => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.initialCleanupFailure = undefined; + state.readbackCleanupFailure = undefined; + const root = await createTestTempDirectory("rea-config-first-run-rollback-"); + const path = join(root, "client.json"); + state.rejectRemove = true; + + const result = await configureClientConfiguration( + { name: "cursor", configPath: path, format: "json" }, + {}, + ["rea", "mcp"], + ); + state.rejectRemove = false; + + expect(result).toMatchObject({ + status: "failed", + reason: "rollback", + failure: { + kind: "restore", + path, + detail: "injected restore remove failure", + }, + }); + expect(result).not.toHaveProperty("backupPath"); + expect(JSON.parse(await readFile(path, "utf8"))).toMatchObject({ + mcpServers: { rea: { command: "rea", args: ["mcp"] } }, + }); +}); + +it("retains readback cleanup ownership when rollback also fails", async () => { + state.readbackFailed = false; + state.rejectRestore = false; + state.rejectRemove = false; + state.initialCleanupFailure = undefined; + const root = await createTestTempDirectory("rea-config-readback-cleanup-"); + const path = join(root, "client.json"); + const original = '{"keep":true}\n'; + await import("node:fs/promises").then(({ writeFile }) => + writeFile(path, original), + ); + const owner = await ownReadHandle(path); + const cleanupFailure = new RegularFileCleanupFailure( + path, + owner, + { kind: "completed", value: "" }, + new Error("injected readback close failure"), + ); + state.readbackCleanupFailure = cleanupFailure; + state.rejectRestore = true; + + const host = systemSetupHost( + { platform: "linux", homeDirectory: root } as DoctorHost, + { HOME: root }, + ); + let caught: unknown; + try { + await host.configureClient( + { name: "cursor", configPath: path, format: "json" }, + {}, + ["rea", "mcp"], + ); + } catch (cause: unknown) { + caught = cause; + } finally { + await host.close?.(); + } + + if (!(caught instanceof ConfigurationError)) throw caught; + expect(caught.message).toContain("injected restore write failure"); + expect(caught.message).toContain(`${path}.rea.backup`); + const cleanupOwnerError = caught.cause; + if (!(cleanupOwnerError instanceof RegularFileCleanupFailure)) + throw new Error("Configuration failure lost its read owner"); + expect(cleanupOwnerError).toMatchObject({ + path, + outcome: { kind: "completed", value: "" }, + cleanupCause: expect.any(AggregateError), + }); + expect(cleanupOwnerError.owner).toBe(owner); + expect(await readFile(`${path}.rea.backup`, "utf8")).toBe(original); +}); diff --git a/tests/process-global/updateMaintenance.test.ts b/tests/process-global/updateMaintenance.test.ts index a60a2e213..ae057bab2 100644 --- a/tests/process-global/updateMaintenance.test.ts +++ b/tests/process-global/updateMaintenance.test.ts @@ -126,6 +126,41 @@ describe("OMP integration maintenance", () => { }); }); +describe("maintenance activation and layered configuration", () => { + it("leaves a natively disabled ZCode registration outside maintenance", async () => { + const configPath = await writeClient( + "zcode", + JSON.stringify({ + mcp: { + servers: { + rea: { command: entryPoint, args: ["mcp"], enable: false }, + }, + }, + }), + ); + const original = await readFile(configPath, "utf8"); + await expect( + existingMaintenanceScope(home, entryPoint, process.env), + ).resolves.toMatchObject({ clients: [] }); + expect(await readFile(configPath, "utf8")).toBe(original); + }); + + it("selects an enabled registration inherited through layered OpenCode files", async () => { + const directory = join(home, ".config", "opencode"); + await mkdir(directory, { recursive: true }); + await writeFile( + join(directory, "opencode.json"), + JSON.stringify({ + mcp: { rea: { type: "local", command: [entryPoint, "mcp"] } }, + }), + ); + await writeClient("opencode", JSON.stringify({ theme: "user-selected" })); + await expect( + existingMaintenanceScope(home, entryPoint, process.env), + ).resolves.toMatchObject({ clients: ["opencode"] }); + }); +}); + describe("existing REA integration maintenance", () => { it("selects owned registrations while preserving unconfigured, foreign, and disabled choices", async () => { await writeClient("codex", staleCodex); diff --git a/tests/process-global/windowsRuntimeAdmission.test.ts b/tests/process-global/windowsRuntimeAdmission.test.ts new file mode 100644 index 000000000..a9f328a18 --- /dev/null +++ b/tests/process-global/windowsRuntimeAdmission.test.ts @@ -0,0 +1,99 @@ +import { beforeEach, expect, it, vi } from "vitest"; +import { WindowsPrivateRuntime } from "../../src/windows/WindowsPrivateRuntime.js"; +import { PrivateRuntimeRootUnavailableError } from "../../src/process/PrivateRuntimeRootUnavailableError.js"; + +const { nativeCall } = vi.hoisted(() => ({ nativeCall: vi.fn() })); +vi.mock("../../src/windows/WindowsNativeLoader.js", async (original) => ({ + ...(await original< + typeof import("../../src/windows/WindowsNativeLoader.js") + >()), + requireWindowsNativeAuthority: () => ({ call: nativeCall }), +})); +beforeEach(() => { + nativeCall.mockReset(); +}); + +it.each([ + { + label: "sharing conflict before allocation", + win32Code: 32, + runtimeAllocation: "not-started", + retryable: true, + }, + { + label: "lock conflict before allocation", + win32Code: 33, + runtimeAllocation: "not-started", + retryable: true, + }, + { label: "unknown allocation", win32Code: 32, retryable: false }, + { + label: "possible allocation", + win32Code: 32, + runtimeAllocation: "started", + retryable: false, + }, + { + label: "permission failure", + win32Code: 5, + runtimeAllocation: "not-started", + retryable: false, + }, + { + label: "string code", + win32Code: "32", + runtimeAllocation: "not-started", + retryable: false, + }, + { + label: "inconsistent error code", + win32Code: 32, + code: "EACCES", + runtimeAllocation: "not-started", + retryable: false, + }, +])( + "retains $label without guessing runtime ownership", + ({ retryable, label: _label, ...facts }) => { + const cause = Object.assign(new Error("Selected native diagnostic"), { + code: "ERR_REA_WINDOWS_NATIVE", + ...facts, + }); + nativeCall.mockImplementation(() => { + throw cause; + }); + let observed: unknown; + try { + WindowsPrivateRuntime.create("D:/selected parent", "selected-prefix-"); + } catch (failure: unknown) { + observed = failure; + } + expect(nativeCall).toHaveBeenCalledTimes(1); + expect(nativeCall).toHaveBeenCalledWith("runtime_create", [ + "D:/selected parent", + "selected-prefix-", + ]); + if (retryable) { + expect(observed).toBeInstanceOf(PrivateRuntimeRootUnavailableError); + expect(observed).toMatchObject({ + message: cause.message, + cause, + retryable: true, + }); + } else expect(observed).toBe(cause); + }, +); + +it("does not infer a transient status from a human-readable diagnostic", () => { + const cause = new Error("Open Windows path component failed (Win32 32)"); + nativeCall.mockImplementation(() => { + throw cause; + }); + let observed: unknown; + try { + WindowsPrivateRuntime.create("D:/selected parent", "selected-prefix-"); + } catch (failure: unknown) { + observed = failure; + } + expect(observed).toBe(cause); +}); diff --git a/turbo.json b/turbo.json index e8bfbf06e..758f31e32 100644 --- a/turbo.json +++ b/turbo.json @@ -151,6 +151,7 @@ "scripts/fixtures/apple/*.mjs", "src/generated*.ts", "src/contracts/**/*.ts", + "licenses/**", "docs/**", "!docs/public/product-catalog.json", "!docs/verification/managed-conformance-*.json", diff --git a/vitest.config.ts b/vitest.config.ts index 74dbf5305..bfef8e139 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -51,7 +51,7 @@ const TEST_PROJECTS = [ name: "adapters", include: [ "src/*.test.ts", - "src/{apktool,jeb,adb,artifacts,browser,dotnet,evm,firmware,flutter,ghidra,go,hopper,ida,inspector,javascript,native,process,reference,server,wasm,windows}/**/*.test.ts", + "src/{apktool,jeb,adb,artifacts,browser,dotnet,evm,firmware,flutter,pcap,ghidra,go,hopper,ida,inspector,javascript,native,process,reference,server,wasm,windows}/**/*.test.ts", ], pool: "forks" as const, maxWorkers: MAX_TEST_WORKERS, diff --git a/website/AGENTS.md b/website/AGENTS.md index 37c9c0f50..5448512d1 100644 --- a/website/AGENTS.md +++ b/website/AGENTS.md @@ -43,8 +43,9 @@ for asset notes and the source of case-study claims. from HTML automatically. Mark example applications `noindex` in the head and keep them crawlable. Maintain the SVG sharing source, not the generated PNG. - Check both local root and `/rea/` paths, mobile layouts, expanded details, - copying and downloads. Run `python3 scripts/website.py check`, using the Python - environment described in the README. It rejects drift rather than silently + copying and downloads. Check light and dark themes, including a manual choice + opposite to the system preference. Run `python3 scripts/website.py check`, + using the Python environment described in the README. It rejects drift rather than silently rewriting shared HTML. Use `website.py links` for an optional network audit; distinguish missing targets from access denials and unverified fragments. - Check setup and support statements against the current installation/provider diff --git a/website/README.md b/website/README.md index 4d6e351fd..151c68005 100644 --- a/website/README.md +++ b/website/README.md @@ -47,14 +47,15 @@ Edit the page's HTML in `public/`. Keep the question, evidence and result easy t follow. The writing and design guidance in [style-guide.md](style-guide.md) applies to every page. -| Change | Edit | Then run | -| ------------------------------ | ---------------------------------------------------------------- | ----------------------------------------------- | -| Page text, examples or figures | The page's HTML outside the marked shared regions | `python3 scripts/website.py check` | -| Search title or description | The page's `` and first description meta tag | `python3 scripts/website.py sync`, then `check` | -| Main navigation | `NAVIGATION` in `scripts/website.py` | `sync`, then `check` | -| Header, social links or footer | `templates/header.html.tmpl` or `templates/footer.html.tmpl` | `sync`, then `check` | -| Shared link previews | `templates/sharing.html.tmpl` or `public/assets/social-card.svg` | `sync`, then `check` | -| Translation | `locales/<language>/messages.po` | `translations check`, then `check` | +| Change | Edit | Then run | +| ------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------- | +| Page text, examples or figures | The page's HTML outside the marked shared regions | `python3 scripts/website.py check` | +| Search title or description | The page's `<title>` and first description meta tag | `python3 scripts/website.py sync`, then `check` | +| Main navigation | `NAVIGATION` in `scripts/website.py` | `sync`, then `check` | +| Header, social links or footer | `templates/header.html.tmpl` or `templates/footer.html.tmpl` | `sync`, then `check` | +| Theme loading and browser color | `templates/theme.html.tmpl` and `public/assets/theme.js` | `sync`, then `check` | +| Shared link previews | `templates/sharing.html.tmpl` or `public/assets/social-card.svg` | `sync`, then `check` | +| Translation | `locales/<language>/messages.po` | `translations check`, then `check` | After changing English text, run `python3 scripts/website.py translations extract` before `check`. Existing translations and reviewer comments survive extraction; @@ -130,6 +131,7 @@ describe its recorded investigation; update them only when repeating that work. - `public/showcase/index.html`: the case-study index. - `public/blog/index.html`: articles about reconstruction methods, ports, mods and reverse engineering. - `public/blog/touhou-reconstruction/index.html`: a personal essay about agent autonomy, oracle quality, knowledge carried between TH08 and TH095, PC-98 TH04, and the path from exact reconstruction to readable source and modern ports. +- `public/blog/reverse-engineering-models/index.html`: an essay on general models, compiler specialization and learning useful reconstruction experiments, with historical evidence from TH08, TH095, TH04 and TH09. Model attribution and verification scope are in [evidence/reverse-engineering-models.md](evidence/reverse-engineering-models.md). - `public/showcase/aegis/index.html`: Aegis's Android login-code calculation, with an adjustable clock and reference checks. - `public/showcase/dx-ball/index.html`: sound-pan investigation and project status. - `public/showcase/notion/index.html`: Notion's Electron clipboard bridge and rich clipboard format. @@ -256,6 +258,19 @@ respecting reduced-motion preferences. Both the prompt and animation work without JavaScript. The homepage and agent setup section share a copyable installation prompt; setup still presents its plan for approval. +The header's sun/moon button switches the color theme. A first visit follows the +system preference, falling back to light when no preference is given. Manual +choices are saved in browser storage under `rea-theme` and apply across pages, +language editions and tabs on the same host. If storage is blocked, the button +still works for the current page. Without JavaScript, the site stays light and +the button stays hidden. + +The shared `theme` head region loads `assets/theme.js` before the stylesheet so a +saved choice applies before the first paint. That script owns the resolved +`data-theme`, browser `theme-color` and `website-theme-change` event. The CSS +palette, embedded SVGs and dinosaur canvas follow that choice. Keep the theme +region in the page scaffold and run `sync` after editing its template. + Reading pages share a small `↑ Top` link at the bottom right. It appears after scrolling and returns to the page header, with smooth scrolling when reduced motion is disabled. Keyboard activation returns focus to the first navigation diff --git a/website/evidence/reverse-engineering-models.md b/website/evidence/reverse-engineering-models.md new file mode 100644 index 000000000..069d6eea3 --- /dev/null +++ b/website/evidence/reverse-engineering-models.md @@ -0,0 +1,166 @@ +# General models and specialist models: article evidence + +Supporting record for `public/blog/reverse-engineering-models/index.html`. +The article is published from the English source and translated through the +website's gettext catalogs. + +## Research scope + +Repository history, maintained source and recorded comparison notes were reviewed +on 13 October 2026. This research did not run game targets, compile reconstruction +candidates or repeat historical runtime checks. Public commit availability was +checked through GitHub CLI. + +The evidence describes specific historical functions and their recorded checks. +Source presence, compiler exactness, complete-product builds and runtime agreement +remain distinct. The proposed specialist/RL comparisons are future experiments; +no trained specialist was evaluated for this article. + +## Model attribution + +- The project operator identifies `gpt-dots` as **GPT-6-Astra**. +- `gpt-web` is a changing label for the model used at the time. The operator + describes then-latest models, usually xhigh, commonly GPT-5.6-Sol earlier and + GPT-6-Sol recently. Do not assign all such commits a single model or infer + individual identities from a release date. +- Explicit `gpt-6-sol` and `gpt-6.1-sol` subjects establish the recorded names. + Per-run reasoning effort and full budgets are not uniformly recorded. +- `gpt-6-luna-max` records GPT-6-Luna and max effort. It does not establish + parameter count or specialist training. + +Later sessions inherited earlier source, diagnostics and failed experiments. +Historical before/after closures support the essay's questions; they are not +controlled estimates of model-size effects. + +## TH09 Type18/24 attack update + +Earlier source-context review: +[GPT-6-Sol, 26 September](https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425). +Closing reconstruction: +[GPT-6.1-Sol, 10 October](https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616). + +The earlier candidate was 1,435 bytes against a 1,436-byte target. Matching the +overall frame size concealed different homes for returned vectors and real +collision storage. Declaration and helper-visibility controls did not close it. + +The closing session introduces an ordinary XYZ destination assignment, consumes +real returned vectors directly and groups six actual publication/rotation +operations into one comma-sequenced full expression. Keeping the real collision +point at function scope preserves separate storage. The seventh warm candidate +matches, followed by a maintained-path canonical cold comparison of all 1,436 +bytes and 44 encoded fields. Original class/source spelling and later runtime +gates remain separate. + +The article's four-row table groups selected lessons from seven candidates. It +does not enumerate every build or reproduce a complete source listing. + +## TH09 Front callback + +Earlier diagnostic checkpoint: +[GPT-6.1-Sol, 2 October](https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269). +Full graph closure: +[GPT-6-Astra (`gpt-dots`), 6 October](https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f). +Accepted replay: +[6 October follow-up](https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0). + +The earlier maintained owner was 1,510 bytes versus the 1,491-byte target. Its +prefix and suffix matched only as independently positioned diagnostic regions; +they did not establish a complete-function match. + +A common outer continuation places completion and frame dispatch in complementary +arms with one final frame increment/return. Within this graph, the side/stage +decision recovers target block sharing. The record establishes the complete +1,491-byte owner, 107 independently bound fields, 384 instructions and 42 calls. +The follow-up records accepted forced-recompile replay for `da33a646`. +Bounded trace models are static checks, not game-runtime validation. + +## TH095 identifier-bucket reuse + +[Supervisor::LoadDat, 2 September](https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f). + +Under observed VC7.1 build 3077, declaration order alone did not recover the real +local homes. Earlier background work established useful identifier buckets. +Backing the real file-size scalar with `averagedPanLocal12` places it at +`EBP-0x04` and the genuine 128-byte buffer at `EBP-0x88`. All 151 bytes and 15 +relocations close. + +This is compiler-context evidence. It does not establish a universal C++ rule +or uniquely recover the original author's variable name. The `gpt-web` label +does not identify this run's model individually. + +## TH09 Luna enemy-spawn closure + +[GPT-6-Luna-max, 27 September](https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e). + +An ordinary loop with `continue`/`break`, branch-local RunEcl failure handling +and a shared success tail closes the 373-byte owner. TH08 source supplies the +source-family hypothesis; TH09 establishes the bounds, fields, ABI and callees. +Two independent cold builds and canonical replay are recorded. + +The earlier stable 361-byte candidate is `gpt-web`, with an individually +unresolved model identity. This case demonstrates a useful discovery across +model tiers, not a measured specialist or smaller-parameter advantage. + +## TH04 compiler diversity + +[Player MAIN_0 cohort, 15 September](https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98). + +Natural Turbo C++ 4.0J source produces a 629-byte update/miss contribution and a +334-byte renderer. Expression lifetimes, branch-local stores, declaration order +and a shared firing tail matter. Correct physical linker order avoids an extra +alignment byte. The recorded focused and aggregate replays cover 129 and 208 +owners respectively. These are historical owned-extent checks; this checkpoint +does not establish whole-game execution. + +TH08 uses VC7, while TH095/TH09 use VC7.1. Avoid treating every game's source +patterns as output from the same compiler. Shared game authorship supplies a +prior; target-local evidence validates an actual transfer. + +## TH08 numerical investigation + +[Polar motion and x87 behavior, 13 October](https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847). + +A collision divergence at stage 2 frame 6,825 leads back to a one-ULP +displacement difference at frame 5,573. Historical CRT wrappers retain a wider +x87 return despite storing a rounded float. A distinct i386 case involves x87 +precision-control state. The record includes field probes and replay checks for +specified scenarios. Several preceding investigations use the same model; this +is breadth-of-investigation evidence, not a model-switch comparison. + +## TH08 floating-literal oracle repair + +[Repository-wide audit, 2 September](https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78). + +Literal payload checks previously depended on optional explicit `data_hex` +attestation. The fix decodes and target-checks every VC7 `__real@...` relocation. +The follow-up audits 1,548 relocations and corrects 12 stale rows in five already +accepted units. One source change corrects a bullet-spread increment from +`1.0f` to `32.0f`. + +Affected-unit replay and a complete 1,106-unit cold replay are recorded after +repair. This defect is separate from the later one-ULP numerical investigation. +The RL consequence in the article is an inference: a reward based on the earlier +check could reinforce wrong source. The record does not describe an actual RL +exploit or trained model doing so. + +## TH09 target-sized replay-save candidate + +[Replay-save closure, 2 October](https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016). + +The earlier candidate already had the target's 1,825-byte length but 467 complete +comparison differences. Shared index identity, loop structure and the real +cancel/overwrite continuation close the complete owner. The example supports +using size as a diagnostic rather than final acceptance. + +## Related research + +The article links these primary sources: + +- [LLM4Decompile, EMNLP 2024](https://aclanthology.org/2024.emnlp-main.203/). +- [AutoDecompiler, June 2026 preprint](https://arxiv.org/html/2606.16162v1). +- [When LLM Decompilers Recompile More and Preserve Less, September 2026 preprint](https://arxiv.org/html/2609.05370v1). + +These works concern specialized decompilation, feedback-based refinement and +functional checking. Their published setups do not establish a winner for the +article's proposed historical-compiler reconstruction experiment. Preserve that +objective distinction when expanding the discussion. diff --git a/website/locales/ar/messages.po b/website/locales/ar/messages.po index 4c8264a50..daaa1d33a 100644 --- a/website/locales/ar/messages.po +++ b/website/locales/ar/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}الرئيسية{ph1} / المدونة" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "مدونة." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "أفكار حول الهندسة العكسية." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "لعبة إعادة الإعمار{ph0}مقال" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "الثورة الصناعية في الهندسة العكسية" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "ما دليل إعادة تعمير TH08, TH095 و TH04 علمني عن وكلاء والتحقق المعرفة أن " "المركبات عبر المشاريع." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "اقرأ المقال" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "بواسطة N0zoM1z0 * 10 أكتوبر 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "العفو الدولية." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -133,112 +136,117 @@ msgid "" "agent." msgstr "REA - اكتشف كيف يعمل البرنامج. الهندسة العكسية مع مساعدك البرمجي." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "الصفحة الرئيسية لـ REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "التنقل الرئيسي" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA على GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "انضم إلى REA على Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "تابع REA على X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -247,35 +255,35 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}الرئيسية{ph1} / {ph2}المدونة{ph3} / إعادة إعمار توهو" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "مقال * إعادة إعمار توهو" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "الثورة الصناعية في الهندسة العكسية." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "بواسطة N0zoM1z0 * 10 أكتوبر 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "أهم الأفكار" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -287,7 +295,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -301,7 +309,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -313,7 +321,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -325,7 +333,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -335,65 +343,65 @@ msgstr "" "{ph0}نحن في الأيام الأولى للثورة الصناعية في ري.{ph1} الأساليب لا تزال " "تتشكل. هناك الكثير من اليسار لاستكشاف." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "كيف تجربة المركبات" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}الاتجاه البشري{ph1} * الهدف ومعايير القبول" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "الاستقلالية" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "المساعد" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "اختر تجربة.{ph0}اقتراح فرضية." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "التحقق" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "مرجع التحقق" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "اختبار ضد أ{ph0}مرجع ملموس." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "مستودع الكود" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "ذاكرة العمل" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -402,7 +410,7 @@ msgstr "رمز ، دليل,{ph0}الشيكات والدروس." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -411,26 +419,26 @@ msgstr "عدم التطابق{ph0}{ph1}مراجعة الفرضية{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "أفضل{ph0}{ph1}نقطة البداية{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "إعادة الاستخدام" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}تمريرة{ph1} * الحفاظ على النتيجة والأدلة" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -439,14 +447,14 @@ msgstr "" "كل مشروع يترك التالي مع نقطة انطلاق أفضل. يتضمن ذلك إصلاح الشيكات عندما " "نكتشف فجوة." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "في هذه المقالة" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -454,7 +462,7 @@ msgstr "{ph0}أغسطس 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -462,7 +470,7 @@ msgstr "{ph0}TH08: استمرار{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -470,7 +478,7 @@ msgstr "{ph0}نهجين{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -478,7 +486,7 @@ msgstr "{ph0}TH095: يضاعف{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -486,7 +494,7 @@ msgstr "{ph0}TH04: عبر البنى{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -494,7 +502,7 @@ msgstr "{ph0}من الدقيق للقراءة{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -502,18 +510,18 @@ msgstr "{ph0}التحول الصناعي{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}ما يصبح ممكنا{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "ما الذي تغير في أغسطس 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -527,7 +535,7 @@ msgstr "" " مزيد من قضاء المزيد من وقتي في الوظيفة التالية. كان يعني أيضا الاحتفاظ " "بصورة كبيرة بشكل متزايد في رأسي." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -540,7 +548,7 @@ msgstr "" "تكون الطريقة مفيدة في مكان آخر ، ولكن يحتاج كل حقل إلى تحديد ما يمكنه التحقق" " منه مقابل مرجع موثوق." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -552,7 +560,7 @@ msgstr "" "إلى أي مدى يمكن للوكيل الوصول إلى البرنامج وأدوات التطوير العادية. أعطاني " "إعادة الإعمار توهو مشروع كبير لمعرفة ذلك." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -568,7 +576,7 @@ msgstr "" "ذلك. إن إعطائها تلك الحرية أحدثت فرقا: يمكنني أن أنفق المزيد من الاهتمام على" " اتجاه المشروع وعلى ما إذا كانت الشيكات جديرة بالثقة." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -578,7 +586,7 @@ msgstr "" "حصلت على وتيرة انتباهي أولا. ثم بدأت أتساءل ما الذي سيبقى بعد المشروع " "الحالي. هل ستستفيد اللعبة التالية من كل ما تعلمناه للتو?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: البناء على العمل البشري" @@ -587,7 +595,7 @@ msgstr "TH08: البناء على العمل البشري" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -600,7 +608,7 @@ msgstr "" "الإعمار{ph3}. أعطاني مصدرها العام أساسا كبيرا. جاء مع معرفة البناء وتاريخ " "المساهمات التي حافظت عليها في الاستمرار." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -611,7 +619,7 @@ msgstr "" "المستقل في 13 أغسطس. بحلول 19 أغسطس ، سجل دفتر الأستاذ مصدرا لجميع وظائف " "اللعبة المحددة البالغ عددها 1107 وظيفة." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -622,7 +630,7 @@ msgstr "" " من بدء الاستمرار. تبع ذلك إصدار ويب. الأم Linux وصل إصدار 64 بت في 30 " "أغسطس." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -637,7 +645,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -654,12 +662,12 @@ msgstr "" "المسار الذي تم ممارسته يصل إلى الحالة المتوقعة. يقترح الوكيل تفسيرا ويختبره " "؛ عدم التطابق يعطيها شيئا محددا للتحقيق فيه." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "تطابق تام مع ثابت خاطئ" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -670,7 +678,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -682,7 +690,7 @@ msgstr "" "التلقائي للعناصر. فحص المصدر المعاد بناؤه قوة اللاعب ضد {ph0}. الأصل " "المستخدم {ph1}، الحد الأقصى-عتبة الطاقة." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -696,13 +704,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}ومع ذلك ، فإن الوظيفة قد اجتازت بالفعل المقارنة الدقيقة.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -716,7 +724,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -732,7 +740,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -745,7 +753,7 @@ msgstr "" " الفعلية للثابت المشار إليه. A {ph2}مراجعة أوسع{ph3} ثم فحص 1548 نقطة عائمة " "المراجع الثابتة. وجدت اثني عشر مرجعا آخر غير صحيح عبر خمس وظائف مقبولة." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -758,7 +766,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -768,7 +776,7 @@ msgstr "" "{ph0}احتاج مرجع التحقق (أوراكل) إلى إعادة البناء أيضا.{ph1} كان إصلاحه جزءا " "من إصلاح اللعبة." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -785,7 +793,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -800,7 +808,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -809,7 +817,7 @@ msgid "" msgstr "" "{ph0}أعطتنا دفعة ناجحة كلا من الكود المسترد وبيئة أفضل للدفعة التالية.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "فكرتان مختلفتان لإعادة الإعمار" @@ -818,7 +826,7 @@ msgstr "فكرتان مختلفتان لإعادة الإعمار" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -830,7 +838,7 @@ msgstr "" "واضحا. يعلن الإشعار أن المزيد من التطوير سيحدث بشكل خاص حتى الانتهاء. مقطع " "واحد يقرأ:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -839,7 +847,7 @@ msgstr "" "إن صعود القواطع (عمليات فك التجميع والمنافذ بالذكاء الاصطناعي) في هذا الفضاء" " المأخوذ من عملنا يرسم صورة سيئة لجهود فك التجميع المستقبلية…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -855,7 +863,7 @@ msgstr "" "أحترم الجهد وراء ذلك. والخلاف الذي أريد مناقشته يتعلق بكيفية المضي قدما في " "إعادة الإعمار وكيف ينبغي الحكم على المساهمة." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -867,7 +875,7 @@ msgstr "" " نفس الشخص. اعتمد المشروع بشكل كبير على خبرة ذلك الشخص. كانت الثقة في " "المساهم مهمة لأن الكثير من المنطق حدث أثناء عملهم." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -878,7 +886,7 @@ msgstr "" "بالنسبة لي هو أن الوكيل يمكنه استخدام هذه المعرفة لمتابعة التحقيق التالي " "بمفرده." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -892,7 +900,7 @@ msgstr "" "أريد أن يكون شخص آخر قادرا على فحص سبب اختيارنا للتنفيذ ، حتى لو قام الوكيل " "بمعظم العمل." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -904,7 +912,7 @@ msgstr "" " يتحرك بشكل أسرع. هذا يثير أسئلة حقيقية حول الائتمان. كما أنه يغير ما يحتاج " "المشرفون إلى معرفته قبل قبول المساهمة." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -919,7 +927,7 @@ msgstr "" "إنتاجها خاطئا. يمكن للمجتمعات المختلفة اختيار مقدار هذا التغيير الذي تريد " "القيام به." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -943,7 +951,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -955,14 +963,14 @@ msgstr "" " و {ph2}سياسة المساهمة{ph3}. الاقتباس هو مقتطف مختصر. TH08في {ph4}الاعتمادات" " والمصدر{ph5} سجل حدود الاستمرارية." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: تبدأ التجربة بالتفاقم" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -976,7 +984,7 @@ msgstr "" "لا يزال يتعين علينا تعلم اللعبة. لكننا عرفنا بالفعل الكثير عن كيفية بدء " "إعادة الإعمار وكيفية الحفاظ عليها تتحرك." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -989,7 +997,7 @@ msgstr "" "سبتمبر. ال Windows أنا 386 تم وضع علامة على إعادة الإعمار للعب في 10 سبتمبر " "، بعد حوالي اثني عشر يوما من التهيئة." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1000,7 +1008,7 @@ msgstr "" "العمل المنجز في لعبة أخرى. كانت التجربة موجودة بالفعل في الأدوات وفي طريقة " "تنظيم المشروع." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1014,7 +1022,7 @@ msgstr "" "المعزولة تترك سؤالا مهما مفتوحا. نحن بحاجة إلى رؤيتهم يعملون معا. ساعد هذا " "الدرس في تشكيل كيفية اقترابنا TH095بناء البرنامج بأكمله." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1026,7 +1034,7 @@ msgstr "" "جلسة أخرى يمكن تشغيلها ، يمكن أن تستمر في المساعدة بعد أن انتقلت. يمكن " "للوكيل التالي استخدام النتيجة دون تكرار التحقيق الذي أدى إليها." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1041,7 +1049,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1052,7 +1060,7 @@ msgstr "" "{ph0}تصبح الطريقة جزءا من مادة البداية للعبة التالية.{ph1} يمكننا إنفاق " "المزيد من جهد المشروع التالي على ما هو جديد بالفعل حول هدفه." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1064,7 +1072,7 @@ msgstr "" "تشغيله قبل مواصلة العمل. لا يتعين عليهم إعادة بناء تاريخ المشروع بأكمله " "لمعرفة سبب ظهور المصدر بالطريقة التي يعمل بها." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: سير العمل ينجو من بنية مختلفة" @@ -1073,7 +1081,7 @@ msgstr "TH04: سير العمل ينجو من بنية مختلفة" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1088,7 +1096,7 @@ msgstr "" "عن Windows ألعاب. القائمة {ph2}التوصية 98 العمل{ph3} قدم لنا معرفة قيمة " "ومصدر المواد هنا أيضا." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1100,7 +1108,7 @@ msgstr "" "كاملة من خلال نهاياتها وفحص يحفظ. العمل الحالي هو منفذ 64 بت الأصلي. إنشاء " "إصدار دوس العمل يعطي أولا أن ميناء الاتصالات مرجعا." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1112,7 +1120,7 @@ msgstr "" "ووقت التشغيل الذي تحققنا من عملنا. لكن لا يزال بإمكان الوكيل متابعة سؤال حتى" " النتيجة والسماح لهذه النتيجة بتوجيه التجربة التالية." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1126,7 +1134,7 @@ msgstr "" "التحقيق ضد المنتج دوس. مرة واحدة هي الأدلة والشيكات المتاحة ، وكيل يمكن أن " "تعمل من خلال السؤال بقدر ما فعلت على Windows العنوان." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1137,7 +1145,7 @@ msgstr "" "على البدء من جديد بطريقة جديدة للعمل. حددت البنية المشكلة ؛ لا يزال سير " "العمل يعطينا طريقة لحلها." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1154,7 +1162,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1164,19 +1172,19 @@ msgstr "" "حالة المشروع اعتبارا من 10 أكتوبر 2026: {ph0}إعادة بناء دوس والاختبار " "اليدوي{ph1} · {ph2}منفذ 64 بت{ph3}. الميناء لا يزال قيد التطوير." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "من الكود الدقيق إلى الكود المقروء" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "بمجرد أن تعمل إعادة الإعمار ، أريد أن يتمكن شخص آخر من فهمها." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1190,7 +1198,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1205,7 +1213,7 @@ msgstr "" "نتمكن من شرح دورها. ثم يمكننا أن نعطيها اسما ذا معنى ونوعا يناسب الأدلة. " "نحافظ على المنطق مع المصدر حتى يتمكن الشخص التالي من رؤية مصدر هذا التفسير." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1219,14 +1227,14 @@ msgstr "" "الكائن الذي يجب أن يمتلك تلك الحالة. لنقل السلوك بأمان ، نحتاج إلى استعادة " "العلاقة وراء الوصول إلى الذاكرة القديمة." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "الترتيب الذي أستخدمه الآن هو:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1241,7 +1249,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1257,7 +1265,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1272,7 +1280,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1286,7 +1294,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1302,7 +1310,7 @@ msgstr "" "الثاني من أن البرنامج الذي أعيد بناؤه لا يزال يبني ويتصرف بشكل صحيح على طول " "المسارات التي نمارسها." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1315,7 +1323,7 @@ msgstr "" "كل من الشيكات المتاحة يعطي وكيل فشل ملموس للتحقيق قبل أن يحمل ريفاكتور أبعد " "من ذلك." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1332,7 +1340,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1350,7 +1358,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1360,12 +1368,12 @@ msgstr "" "{ph0}إعادة الإعمار الدقيق يعطينا مرجعا. إعادة البناء الدلالي يجعل المعرفة " "المستردة قابلة للاستخدام.{ph1} يمكن للمنفذ بعد ذلك البناء على كليهما." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "ما الذي يجعل هذا التحول الصناعي" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1378,7 +1386,7 @@ msgstr "" "التي يمكنني القيام بها. يمكن أن تساعد الأداة الأفضل في كل وظيفة لاحقة " "تحتاجها." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1391,7 +1399,7 @@ msgstr "" "متوقع. إذا كان عليه أن ينتظر مني أن أصف كل خطوة ، فإن الكثير من العمل لا " "يزال مرتبطا باهتمامي." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1404,7 +1412,7 @@ msgstr "" "للمحاولة مرة أخرى. لا يزال يتعين علي أن أقرر ما إذا كانت الأدلة المتراكمة " "تدعم علامة فارقة في المشروع." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1418,7 +1426,7 @@ msgstr "" "والشيكات المرجعية الخاصة به. يمكن للوكيل استخدام تلك لاختبار المصدر الذي " "يقترحه ومعرفة أين يحمل تفسيره." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1435,7 +1443,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1454,7 +1462,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1470,7 +1478,7 @@ msgstr "" " مشتركة ، يتعين علينا إصلاحه وإعادة النظر في النتائج التي تأثرت بها. يمكن " "للمشروع التالي بعد ذلك أن يرث أداة أقوى." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1485,7 +1493,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1497,7 +1505,7 @@ msgstr "" "وسيلة مشتركة لتنفيذ الشيكات والدروس إلى الأمام. العمل على لعبة واحدة يمكن أن" " يحسن ظروف البداية لآخر." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1508,12 +1516,12 @@ msgstr "" "من الأدوات التي يمكن للآخرين استخدامها. يؤدي تحسين هذه الأدوات إلى تغيير " "مقدار ما يمكن للشخص التالي—أو الوكيل التالي—إنجازه." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "المشاريع التي يمكننا النظر فيها الآن" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1524,7 +1532,7 @@ msgstr "" "ولا تزال تتطلب المزيد من اهتمامي الخاص مما كنت يمكن أن تعطي واقعيا. العديد " "من المشاريع ستبقى الأفكار." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1540,7 +1548,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1550,7 +1558,7 @@ msgstr "" "أنا الآن ننظر إلى برنامج غير مألوف ونسأل: {ph0}ما هو الوصول, ردود الفعل " "والمعرفة المتراكمة ستسمح للوكيل بالعمل على هذا بشكل موثوق?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1561,12 +1569,12 @@ msgstr "" " واحد تحسين الطريقة التي نقترب بها من التالي. أريد أن أستمر في استكشاف إلى " "أي مدى يمكن أن يأخذنا ذلك." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "معالم المشروع ومصادره" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1599,7 +1607,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1633,7 +1641,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1651,7 +1659,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1674,7 +1682,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1695,7 +1703,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1711,7 +1719,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1732,7 +1740,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1746,7 +1754,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1766,27 +1774,27 @@ msgstr "" "N0zoM1z0 يعكس على دليل الهندسة العكسية, Touhou إعادة الإعمار مع منظمة العفو " "الدولية وكلاء, كيفية معرفة المركبات عبر TH08, TH095 و PC-98 TH04." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "الخبرة المنقولة بين المشاريع" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "مقال إعادة إعمار توهو" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -1795,18 +1803,18 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}الرئيسية{ph1}{ph2}/{ph3}مختبر سرعة الديناصورات" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "تفقد rebuild إعادة بناء change تغيير" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "إعادة بناء قاعدة سرعة الديناصور." @@ -1815,7 +1823,7 @@ msgstr "إعادة بناء قاعدة سرعة الديناصور." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1827,15 +1835,15 @@ msgstr "" "عاد البرنامج النصي قيد التشغيل;{ph1} استخدمنا حكمها لبناء هذه اللعبة المصغرة" " مع {ph2}سرعة قابلة للتعديل.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "في هذه الصفحة" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1843,7 +1851,7 @@ msgstr "{ph0}اللعب وتغيير السرعة{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1851,7 +1859,7 @@ msgstr "{ph0}اقرأ القاعدة المستردة{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1859,18 +1867,18 @@ msgstr "{ph0}تحقق من إعادة الإعمار{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}جرب التحليل{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "اللعب وتغيير السرعة" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1881,47 +1889,47 @@ msgstr "" "أو أسرع ؛ يتحول إلى سرعة ثابتة. حدد القاعدة المستردة للبدء في 6 وتسريع " "تدريجيا مرة أخرى." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "جرّب اللعبة المعاد بناؤها" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "العب" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "اقفز ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "ابدأ من جديد" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "السرعة" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "استخدم قاعدة التسارع المستردة" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "القاعدة الأصلية: ابدأ من 6 ، ثم زد نحو 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "حرك شريط التمرير لضبط السرعة الخاصة بك. الفضاء أو القفز يزيل الصبار." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -1929,7 +1937,7 @@ msgid "" msgstr "" "تمكين JavaScript للعب إعادة الإعمار. يظل الرمز والشرح أعلاه قابلا للقراءة." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "قراءة السيناريو REA عاد" @@ -1937,7 +1945,7 @@ msgstr "قراءة السيناريو REA عاد" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1951,7 +1959,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1961,18 +1969,18 @@ msgstr "" "الإعدادات هي {ph0}, {ph1} و {ph2}. تدير اللعبة هذا الفرع على تحديث دون " "تصادم." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "استخدم نفس القاعدة في اللعبة الجديدة" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "نسخ" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -1989,18 +1997,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}قم بتنزيل قاعدة السرعة{ph1} · {ph2}قراءة رمز اللعبة{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "تحقق من إعادة الإعمار" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2010,27 +2018,27 @@ msgstr "" "اتصلنا بوظيفة تحديث اللعبة الأصلية مع تعطيل العقبات والجدولة التلقائية. قارن" " تلك السرعات المسجلة مع إعادة تشغيل القاعدة المستردة." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "التحديثات" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "اللعبة الأصلية" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "قاعدة أعيد بناؤها" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "قم بتشغيل فحص السرعة" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2039,14 +2047,14 @@ msgstr "" "تقريب القيم إلى ثلاثة كسور عشرية. يتحقق الفرع قبل الإضافة ، لذلك يمكن أن " "تأخذ الزيادة النهائية سرعة أعلى بقليل من 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "جرب التحليل بنفسك" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2055,14 +2063,14 @@ msgstr "{ph0}إعداد REA{ph1} مع مساعدك البرمجي." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "اتبع {ph0}خطوات اتصال المتصفح{ph1}، باستخدام {ph2} كما رابط الصفحة." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2079,7 +2087,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2091,7 +2099,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2105,7 +2113,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2120,7 +2128,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2145,12 +2153,12 @@ msgstr "" "اقرأ قاعدة سرعة لعبة الديناصورات باستخدام REA، إعادة بنائه ، ثم تغيير السرعة" " واللعب." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "إعادة بناء سرعة الديناصورات" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2158,52 +2166,52 @@ msgid "" msgstr "" "ديناصور لعبة صغيرة. استخدم زر القفز أو اضغط على الفضاء أثناء تركيز اللعبة." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "نسخ قاعدة السرعة المعاد بناؤها" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "نسخة ديناصور تحليل موجه" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}الرئيسية{ph1} / أسئلة وأجوبة" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA التعليمات." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "الإعداد والتحديثات والتحليل واستكشاف الأخطاء وإصلاحها." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "المواضيع" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2211,7 +2219,7 @@ msgstr "{ph0}الإعداد والتحديثات{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2219,7 +2227,7 @@ msgstr "{ph0}التحليل{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2227,31 +2235,31 @@ msgstr "{ph0}استكشاف الأخطاء وإصلاحها{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}البيانات والمشاركة{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "الإعداد والتحديثات" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "كيف أثبّت REA؟" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "محطة * وكيل الإعداد" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "نسخ" @@ -2259,7 +2267,7 @@ msgstr "نسخ" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2272,13 +2280,13 @@ msgstr "" "اكتماله، أعد تشغيل مساعدك وأعطه مسار الملف وسؤالك. يوضّح {ph0}دليل " "الإعداد{ph1} المتطلبات وخطوات التحليل الأول." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "ما هي عوامل الترميز التي يمكن استخدامها REA?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2293,18 +2301,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}قم بتوصيل مساعدك البرمجي{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "كيف أحدّث REA؟" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2313,14 +2321,14 @@ msgstr "" "REA الإصدارات بشكل متكرر ، بما في ذلك إصلاحات الأخطاء. إذا قمت بتثبيت CLI مع" " npm:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "المحطة الطرفية * مثبتة CLI" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2330,14 +2338,14 @@ msgstr "" "اتبع أمر تحديث الإعداد الذي يظهر بعد التحديث. إذا أعددت مساعدك باستخدام " "{ph0}، فنفّذ:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "محطة * تحديث وكيل الإعداد" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2349,7 +2357,7 @@ msgstr "" " لذلك أعد تشغيل الإعداد لاستخدام الإصدار الجديد. لتنفيذ أمر CLI مرة واحدة، " "أضف الأمر بعد {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "يتم تثبيت المهارة من skills.sh كفى?" @@ -2357,7 +2365,7 @@ msgstr "يتم تثبيت المهارة من skills.sh كفى?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2368,17 +2376,17 @@ msgstr "" "تزوّد المهارة مساعدك بتعليمات التحليل. شغّل {ph0}إعداد REA{ph1} لتوصيل خادم " "MCP وتثبيت المهارة المناسبة، ثم أعد تشغيل مساعدك ليتمكّن من استخدام الأدوات." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "التحليل" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "ماذا يمكنني تحليل مع REA?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "تبدأ مع هذا النوع من البرامج لديك:" @@ -2386,7 +2394,7 @@ msgstr "تبدأ مع هذا النوع من البرامج لديك:" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2398,7 +2406,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2410,7 +2418,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2420,7 +2428,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2432,13 +2440,13 @@ msgstr "" "Android APK والبرامج الثابتة والموارد المعبأة. تعرض {ph0}دراسات الحالة{ph1} " "أمثلة عملية." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "هل أحتاج Hopper, Ghidra أو IDA?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2451,7 +2459,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2463,13 +2471,13 @@ msgstr "" "تثبيته. تعتمد الأداة المتاحة على نظام التشغيل والهدف. {ph0}إعداد التحليل " "الأصلي{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "هل يمكنني استخدام REA بدون المساعد البرمجي?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2478,7 +2486,7 @@ msgstr "" "نعم. تستخدم CLI عمليات التحليل نفسها. لتحليل تطبيق JavaScript أو Electron " "محلي:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "محطة * تحليل التطبيق الثابت" @@ -2486,7 +2494,7 @@ msgstr "محطة * تحليل التطبيق الثابت" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2497,13 +2505,13 @@ msgstr "" " لخيارات التثبيت." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "ما الكود الذي يعيده REA؟" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2519,7 +2527,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2530,13 +2538,13 @@ msgstr "" "يستخدم مساعدك النتائج لشرح السلوك أو كتابة تنفيذ واختباره. توضح {ph0}حسابات " "DX-Ball{ph1} و{ph2}أداة التحقق من flag في CTF{ph3} هذه العملية." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "ماذا أسأل مساعدي؟" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2553,7 +2561,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2562,7 +2570,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2572,19 +2580,19 @@ msgstr "" "استبدل المسار بهدفك. تحتوي {ph0}الأدلة{ph1} على طلبات نموذجية للبرامج " "الأصلية وElectron والمتصفح." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "استكشاف الأخطاء وإصلاحها" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "لماذا لا يستطيع وكيل أعمالي رؤية REA أدوات?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2594,7 +2602,7 @@ msgstr "" "أعد تشغيل مساعدك أو اتصاله بعد الإعداد. افحص تسجيل REA باستخدام {ph0}؛ مثال " "لـ Codex:" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "محطة * تحقق عميل واحد" @@ -2603,7 +2611,7 @@ msgstr "محطة * تحقق عميل واحد" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2613,7 +2621,7 @@ msgstr "" "استبدل {ph0} بمعرّف العميل، مثل {ph1} أو {ph2}. إذا أظهر التقرير تسجيلًا " "مفقودًا أو قديمًا، فأعد الإعداد لذلك العميل:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "محطة * إصلاح إعداد عميل واحد" @@ -2621,7 +2629,7 @@ msgstr "محطة * إصلاح إعداد عميل واحد" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2632,7 +2640,7 @@ msgstr "" "راجع الخطة وأعد تشغيل العميل. إذا كان التسجيل سليمًا لكن الأدوات لا تظهر، " "فافحص خطأ اتصال MCP لدى العميل. {ph0}تشخيصات إعداد إضافية{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "هل أحتاج إلى البدء Hopper أولا?" @@ -2640,7 +2648,7 @@ msgstr "هل أحتاج إلى البدء Hopper أولا?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2652,7 +2660,7 @@ msgstr "" "التجريبي أو فعّل الترخيص في شاشة التشغيل الأول قبل بدء التحليل دون تدخل. " "{ph0}إعداد أدوات التحليل الأصلية{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "ماذا أفعل إذا واجهت خطأ؟" @@ -2660,7 +2668,7 @@ msgstr "ماذا أفعل إذا واجهت خطأ؟" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2673,7 +2681,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2685,18 +2693,18 @@ msgstr "" "الهدف وخطوات إعادة إنتاج المشكلة ومخرجات الخطأ. أضف اسم أداة التحليل إذا " "كانت المشكلة تتعلق بالتحليل الأصلي." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "البيانات والمشاركة" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "هل REA تحميل تطبيقي?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2705,7 +2713,7 @@ msgstr "" "يحلّل REA الأهداف على جهازك. يستقبل مساعدك النتائج، وتخضع هذه النتائج لسياسة" " البيانات الخاصة بمزوّد نموذجه." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "كيف يمكنني مشاركة مثال أو المساهمة?" @@ -2715,7 +2723,7 @@ msgstr "كيف يمكنني مشاركة مثال أو المساهمة?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2731,7 +2739,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2756,77 +2764,77 @@ msgstr "" "إجابات عن أسئلة REA الشائعة: التثبيت والتحديث وأدوات التحليل والمساعدون " "البرمجيون وحل المشكلات ومشاركة الأمثلة." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "الأسئلة المتداولة حول REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "نسخ REA أمر الإعداد" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "نسخ REA أمر التحديث" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "أمر تحديث إعداد وكيل النسخ" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "نسخ REA CLI أمر التحليل" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "نسخ مثال تحليل موجه" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "نسخ أمر تشخيص العميل" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "نسخ أمر إعداد النطاق" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}الرئيسية{ph1} / تحقيقك الأول" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "اكتشف أين{ph0}الملاحظات المصدرة تذهب." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2835,14 +2843,14 @@ msgstr "" "استخدام REA لتفقد تطبيق صغير ، اتبع زر ملاحظات التصدير الخاص به وتحقق من أحد" " التفاصيل بنفسك." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "في هذا التمرين" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2850,7 +2858,7 @@ msgstr "{ph0}1. إعداد{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2858,7 +2866,7 @@ msgstr "{ph0}2. اسأل عن التصدير{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2866,7 +2874,7 @@ msgstr "{ph0}3. اتبع الجواب{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2874,13 +2882,13 @@ msgstr "{ph0}4. تحقق من التنبؤ{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. اطرح سؤالا آخر{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. ربط وكيلك إلى REA" @@ -2893,29 +2901,29 @@ msgstr "1. ربط وكيلك إلى REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "نسخ" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "أو قم بتشغيل هذا الأمر في جهازك الطرفي:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2924,14 +2932,14 @@ msgstr "" "راجع الخطة ، ووافق على الإعداد ، ثم أعد تشغيل وكيلك. متصل بالفعل? تابع " "أدناه." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. اسأل أين CSV هو مكتوب" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2942,7 +2950,7 @@ msgstr "" "المثال هو ملف ستة Electron التطبيق مع {ph0}ملاحظات التصدير{ph1} زر. وكيلك " "يمكن فحص التعليمات البرمجية الخاصة به دون تثبيت أو إطلاق Electron." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2952,14 +2960,14 @@ msgstr "وكيلك بتحميل الملفات ويعطي المجلد تفكي #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}تحميل مثال الرمز البريدي{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2969,12 +2977,12 @@ msgstr "" "إذا لم يتمكن وكيلك من تنزيل الملفات ، فقم بفك ضغط هذا الأرشيف بنفسك. تعطيه " "الطريق إلى {ph0} المجلد ونفس سؤال التصدير." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. اتبع الجواب مرة أخرى إلى التعليمات البرمجية" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "ابحث عن شرح قصير مع مراجع الملفات والخط:" @@ -2983,7 +2991,7 @@ msgstr "ابحث عن شرح قصير مع مراجع الملفات والخط: #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2995,12 +3003,12 @@ msgstr "" "التالي CSV ويكتب {ph1} في مجلد التنزيلات الخاص بالمستخدم. الأعمدة هي {ph2} و" " {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "من الزر إلى كاتب الملف" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3009,7 +3017,7 @@ msgstr "" "REAالصورة تحليل ثابت أزواج الرسالة مع معالج لها. تتم قراءة الوجهة من " "التعليمات البرمجية." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3020,18 +3028,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}انظر تتبع رمز كامل وسجلت REA النتيجة{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. تحقق من التنبؤ" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3040,19 +3048,19 @@ msgstr "" "فاصلة تفصل CSV الأعمدة. ماذا يحدث عندما يحتوي عنوان الملاحظة نفسه على فاصلة " "أو علامات اقتباس?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "قم بتشغيل الشيك بنفسك" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "فتح محطة في تفكيك {ph0} المجلد:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3061,24 +3069,24 @@ msgstr "" "يستخدم هذا الأمر قذيفة مع دعم وثيقة هنا ، مثل باش أو زش. وكيلك يمكن تشغيل " "نفسه JavaScript في قذيفة النظام الأساسي الخاص بك." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. اطرح سؤالا آخر" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "جرب المتابعة في نفس المحادثة:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "ماذا يحدث إذا تعذر كتابة الملف? اتبع الخطأ مرة أخرى إلى الصفحة." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3089,7 +3097,7 @@ msgstr "أو امنح وكيلك تطبيقا خاصا بك واسأل عن زر #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3103,7 +3111,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3117,7 +3125,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3141,114 +3149,114 @@ msgstr "" "حاول REA على تطبيق ملاحظات صغير. قم بإعداد وكيلك ، واسأل أين تذهب الملاحظات " "المصدرة ، وتحقق من CSV المنسق مع عنوان عينة." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "الخاص بك أولا REA التحقيق" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "نسخ REA موجه التثبيت" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "نسخ أمر الإعداد" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "نسخة ملاحظات التحقيق الفوري" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "نسخ CSV تحقق موجه" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "نسخ أمر التحقق من المنسق" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}الرئيسية{ph1} / ابدأ" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "إعداد REA." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "" "الاتصال REA إلى مساعدك البرمجي ، أو تفقد التطبيق المحلي من محطة الخاص بك." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "افتح محطة وتحقق:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "محطة" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "نسخ" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0}Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3261,7 +3269,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3271,17 +3279,17 @@ msgstr "" "إذا قال PowerShell لاحقا {ph0}\"تشغيل البرامج النصية معطل على هذا " "النظام\"{ph1} عند تشغيل {ph2}، قم بتشغيل هذا مرة واحدة وحاول مرة أخرى:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "إذا كنت تستخدم Homebrew:" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "خلاف ذلك:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "إغلاق المحطة ، فتحه مرة أخرى ، ثم:" @@ -3289,7 +3297,7 @@ msgstr "إغلاق المحطة ، فتحه مرة أخرى ، ثم:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3301,7 +3309,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3313,7 +3321,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3321,14 +3329,14 @@ msgid "" "{ph0}nodejs.org{ph1}." msgstr "تفضل المثبت العادي? تحميل النسخة لتس من {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "خيارات الإعداد" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3336,7 +3344,7 @@ msgstr "{ph0}قم بتوصيل مساعدك البرمجي{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3344,7 +3352,7 @@ msgstr "{ph0}استخدام CLI{ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3352,18 +3360,18 @@ msgstr "{ph0}إعداد تحليل برامج رمز الجهاز{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}الحصول على المساعدة{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "قم بتوصيل مساعدك البرمجي" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3374,12 +3382,12 @@ msgstr "" "Claude Code, Codex, Cursor, Gemini CLI, Windsurf, Grok Build، وغيرها من " "الدعم MCP العملاء. يضاف موصل Grok Bot من الدردشة لها." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "جديد في وكلاء الترميز?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3390,7 +3398,7 @@ msgstr "" " بدلا من علامة تبويب المتصفح. يمكنه قراءة الملفات وتشغيل الأوامر ، ويسأل قبل" " إجراء التغييرات. REA يعطيها أدوات الهندسة العكسية." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3402,7 +3410,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3414,7 +3422,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3427,7 +3435,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3437,7 +3445,7 @@ msgstr "" "{ph0}{ph1}OpenCode{ph2}{ph3}, المصدر المفتوح. قم بتوصيل موفر النموذج الذي " "تختاره." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3454,18 +3462,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "أو قم بتشغيل الإعداد بنفسك" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "كيف يمكنني فتح محطة?" @@ -3474,7 +3482,7 @@ msgstr "كيف يمكنني فتح محطة?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3490,7 +3498,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3503,7 +3511,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3518,7 +3526,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3528,7 +3536,7 @@ msgstr "" "لصق أمر مع {ph0} {ph1} (macOS: {ph2} {ph3}; Linux المحطات: {ph4} {ph5} " "{ph6}) ، ثم اضغط أدخل." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3539,12 +3547,12 @@ msgstr "" "المطابقة ، مع الاحتفاظ بنسخة احتياطية من التكوين الحالي. يسأل قبل تطبيق " "التغييرات." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "أعد تشغيل العميل عند انتهاء الإعداد." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "كيف يمكنني إعادة تشغيل موكلي?" @@ -3553,7 +3561,7 @@ msgstr "كيف يمكنني إعادة تشغيل موكلي?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3569,7 +3577,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3579,7 +3587,7 @@ msgstr "" "{ph0}وكلاء المحطة الطرفية{ph1} (Claude Code, Codex, Gemini CLI): الخروج من " "الدورة وبدء تشغيله مرة أخرى." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3589,7 +3597,7 @@ msgstr "" "تبدأ مع:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3599,12 +3607,12 @@ msgstr "" "انظر إلى {ph0} والعثور على كيفية تصدير البيانات. عرض نقاط الدخول والمكالمات " "والتبعيات المعنية ، مع مواقع المصدر للنتائج الخاصة بك." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "استبدال المسار مع الهدف المحلي الخاص بك." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "كيف يمكنني الحصول على المسار الكامل للمجلد?" @@ -3613,7 +3621,7 @@ msgstr "كيف يمكنني الحصول على المسار الكامل للم #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3628,7 +3636,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3640,7 +3648,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3648,17 +3656,17 @@ msgid "" "appears." msgstr "{ph0}أي نظام:{ph1} اسحب المجلد إلى نافذة طرفية ويظهر مساره." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "في المحطة الطرفية ، ضع علامات اقتباس حول مسار يحتوي على مسافات." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "استخدام CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3666,14 +3674,14 @@ msgid "" msgstr "" "تحليل JavaScript أو Electron مجلد التطبيق أو ASAR الأرشيف دون تشغيل التطبيق:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "تحليل التطبيق الثابت" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3683,13 +3691,13 @@ msgstr "" "استبدل المسار بدليل التطبيق المستخرج أو {ph0} ملف. على Windows، مسار مثل " "{ph1} يعمل هنا." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "أين أجد التطبيق .ملف اسار?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3700,7 +3708,7 @@ msgstr "Electron تطبيقات عادة يبقيه في {ph0} المجلد:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3712,7 +3720,7 @@ msgstr "{ph0}Windows:{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3725,20 +3733,20 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0}Linux:{ph1} في كثير من الأحيان {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "يتم تثبيت بعض التطبيقات في مكان آخر. ابحث في مجلد التطبيق عن {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3749,31 +3757,31 @@ msgstr "" "اتصالات REA لا يمكن حل يتم وضع علامة في النتيجة." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "إذا كنت ترغب في الحصول على وظيفة دائمة {ph0} الأمر في قذيفة الخاص بك:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "تثبيت CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}تواصل مع JavaScript دليل التطبيق{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "إعداد تحليل برامج رمز الجهاز" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3782,12 +3790,12 @@ msgstr "" "تحتاج الثنائيات الأصلية إلى أداة تحليل محلية. اختيار وتكوين واحد أدناه ، ثم " "إعطاء REA الملف القابل للتنفيذ أو المكتبة." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "اختر أداة: Ghidra, Hopper أو IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3798,17 +3806,17 @@ msgstr "" "macOS، على إكس 64 أو أرم 64. الخاص بك Ghidra يحتاج التثبيت إلى برنامج فك " "التحويل الأصلي لهندسة المضيف. اضبط المسارات قبل تشغيل الإعداد:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "ربط الخاص بك Ghidra تركيب" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra اتصال · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3819,12 +3827,12 @@ msgstr "" "إعدادات صالحة للعميل الذي اخترته. على Linux أرم 64 ، قد تحتاج إلى بناء " "Ghidraالصورة المفكك الأصلي بشكل منفصل." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "الاتصال Ghidra على Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3835,18 +3843,18 @@ msgstr "" " على محركات نتفس المحلية الثابتة. استخدام القائمة Ghidra 12.1.س التثبيت و 64" " بت جدك 21 أو أحدث:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra اتصال · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "استبدال المسارين مع المنشآت الخاصة بك ، ثم مراجعة خطة الإعداد." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3855,7 +3863,7 @@ msgstr "" "الاتصال Hopper على macOS أو Linux. قم بتشغيل أمر الإعداد أعلاه ؛ يكتشف " "تثبيتا موجودا أو يقدم خطة تثبيت للموافقة عليها." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3864,7 +3872,7 @@ msgstr "" "على macOS، كاملة Hopperخيار التشغيل الأول للوضع التجريبي أو تنشيط الترخيص " "قبل إجراء تحليل غير مراقب." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3875,7 +3883,7 @@ msgstr "" "المستخدم الرسومية المرفقة أو قاعدة بيانات مقطوعة الرأس. Linux و macOS لا " "يزال تحليل مقطوعة الرأس لم يتم التحقق منها." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "ربط القائمة IDA MCP التسجيل" @@ -3885,7 +3893,7 @@ msgstr "ربط القائمة IDA MCP التسجيل" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3897,13 +3905,13 @@ msgstr "" "القائمة {ph3} كائن مع {ph4} يتم قبول الدخول أيضا. نقطة REA في هذا الملف قبل " "الإعداد:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA اتصال · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3920,7 +3928,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3931,29 +3939,29 @@ msgstr "" "أعط REA المسار القابل للتنفيذ الأصلي ، مع {ph0} في CLI الاستعلام. بالنسبة " "للوكيل ، تشمل {ph1} في ال REA بيئة التسجيل واختيار IDA عند فتح ثنائي." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "للحصول على القائمة Ghidra الإعداد ، فحص وظيفة مع:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "تحليل الوظيفة" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "استبدال {ph0} مع اسم الوظيفة أو العنوان الذي تريد فحصه." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "كيف يعمل تحليل جلسات برامج كود الآلة" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3965,7 +3973,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3975,18 +3983,18 @@ msgstr "" "{ph0}اتبع مثال تحليل برامج كود الآلة{ph1} لنرى كيف تؤدي نتيجة الوظيفة إلى " "عملية حسابية مستردة." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "الحصول على المساعدة" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "إذا كان وكيلك لا يرى REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3996,27 +4004,27 @@ msgstr "" "أعد تشغيل العميل أو أعد توصيله بعد الإعداد. تحقق لها REA اتصال مع {ph0}؛ إلى" " عن على Codex:" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "تحقق من عميل واحد" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "إذا احتاج مقدم الخدمة إلى الاهتمام" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "تحقق من الموفر الذي تستخدمه. ل Ghidra:" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "تحقق من مزود واحد" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "يعطي التقرير الاختيار الفاشل والخطوة التالية المقترحة." @@ -4025,7 +4033,7 @@ msgstr "يعطي التقرير الاختيار الفاشل والخطوة ا #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4038,7 +4046,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4052,7 +4060,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4064,7 +4072,7 @@ msgstr "{ph0}GitHub القضايا{ph1}{ph2}الإبلاغ عن مشكلة في #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4086,112 +4094,112 @@ msgstr "" "الاتصال REA إلى الترميز الخاصة بك أو وكيل أو فحص محلي JavaScript أو Electron" " التطبيق من المحطة. الإعداد والأسئلة الأولى وأدلة الموفر الأصلي." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "نسخ Node.js فحص الإصدار" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "نسخ Node.js أمر التثبيت ل Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "نسخ أمر سياسة تنفيذ PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "نسخ Homebrew Node.js أمر التثبيت" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "نسخة فنم أمر التثبيت ل macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "نسخ Node.js 24 أوامر ل macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "نسخة فنم أمر التثبيت ل Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "نسخ Node.js 24 أوامر ل Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA دليل البدء" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "نسخ REA موجه التثبيت" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "أمر إعداد وكيل النسخ" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "نسخ JavaScript أمر التحليل" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "نسخ CLI أمر التثبيت" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "نسخ أمر اتصال Ghidra على macOS وLinux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "نسخ Ghidra اتصال ل Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "نسخ IDA اتصال ل Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "نسخ أمر تحليل الوظيفة الأصلية" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "نسخ أمر تشخيص العميل" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "أمر تشخيص مزود النسخ" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -4200,20 +4208,20 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}الرئيسية{ph1} / {ph2}أدلة{ph3} / مراقبة المتصفح" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "انظر ماذا سيحدث{ph0}عند النقر فوق." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4222,14 +4230,14 @@ msgstr "" "استخدام التطبيق متصفح صغير لربط العمل ، طلب شبكتها و JavaScript أن يبني " "تحميل." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "في هذا الدليل" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4237,7 +4245,7 @@ msgstr "{ph0}المثال{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4245,7 +4253,7 @@ msgstr "{ph0}افتح المتصفح{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4253,7 +4261,7 @@ msgstr "{ph0}اسأل وكيلك{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4261,13 +4269,13 @@ msgstr "{ph0}التقاط من CLI{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}قراءة الطلب والسيناريو{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "ماذا يحدث عند النقر فوق تصدير?" @@ -4277,7 +4285,7 @@ msgstr "ماذا يحدث عند النقر فوق تصدير?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4289,7 +4297,7 @@ msgstr "" "النقر عليه الأحمال {ph4}، تنسيقات المذكرتين على النحو التالي CSV, ويبدأ " "التنزيل." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "من النقر إلى CSV تحميل" @@ -4300,7 +4308,7 @@ msgstr "من النقر إلى CSV تحميل" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4316,7 +4324,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4334,7 +4342,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4344,17 +4352,17 @@ msgstr "" "{ph0}03 * وكيلك{ph1}{ph2}اقرأ رمز التصدير{ph3}{ph4}قم بتوصيل الطلب المرصود " "بـ {ph5} في {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "ابدأ الالتقاط قبل النقر فوق تصدير الملاحظات." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "فتح Chrome مع التصحيح عن بعد" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4363,21 +4371,21 @@ msgstr "" "افتح مثال الملاحظات المستضافة باستخدام ملف تعريف متصفح منفصل ومنفذ تصحيح " "أخطاء محلي. على Linux:" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "ابدأ تشغيل متصفح المثال" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "نسخ" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4386,7 +4394,7 @@ msgstr "" "استخدم المسار القابل للتنفيذ للمتصفح المثبت على macOS أو Windows. يمكنك " "استبدال رابط الصفحة بصفحة أخرى تريد فحصها." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4395,7 +4403,7 @@ msgstr "" "REA يتصل بهذا المتصفح الحالي. يمكنك التحكم في الصفحة وتنفيذ الإجراء وإغلاق " "المتصفح عند الانتهاء." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "اطلب من وكيلك مشاهدة إجراء واحد" @@ -4408,7 +4416,7 @@ msgstr "اطلب من وكيلك مشاهدة إجراء واحد" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4420,7 +4428,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4431,7 +4439,7 @@ msgstr "" "الملاحظات. ما هو الطلب الذي يقدمه ، وكيف هو CSV بنيت?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4441,7 +4449,7 @@ msgstr "" "مثال موجه. إعطاء وكيلك نقطة النهاية التصحيح, {ph0}، وعنوان الصفحة. السماح " "لها بدء التقاط قبل النقر فوق." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4451,23 +4459,23 @@ msgstr "" "يكتشف وكيلك هدف الصفحة ، ويبدأ نافذة مراقبة ، ويقرأ الأدلة الناتجة. ويمكن " "بعد ذلك فحص البرنامج النصي وراء التصدير." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "أو التقاط من المحطة" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "ابحث عن معرف الهدف للصفحة:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "ابحث عن الصفحة" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4477,14 +4485,14 @@ msgstr "" "اختر الهدف مع عنوان ورل مثال الملاحظات. استبدال {ph0} أدناه مع معرفه ، ثم " "تشغيل:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "التقاط الثواني العشر القادمة" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4494,7 +4502,7 @@ msgstr "" "دع الأمر يتصل لبضع ثوان ، ثم انقر فوق {ph0}ملاحظات التصدير{ph1} في هذا " "المتصفح. تصل النتيجة بعد انتهاء نافذة المراقبة." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4504,49 +4512,49 @@ msgstr "" "تتضمن النتيجة الملتقطة الصفحة المحددة ونشاط الشبكة أثناء تلك النافذة وشكل " "استجابة جسون. الطلبات السابقة خارج هذا الالتقاط." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "قراءة الطلب وتصدير البرنامج النصي" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "سجلت مع REA 4.1.0 في مثال الملاحظات المحلية" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "حقيقة القبض" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "القيمة" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "الطلب" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "الرد" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "طلب البادئ" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * النصي" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "هيكل الاستجابة" @@ -4554,19 +4562,19 @@ msgstr "هيكل الاستجابة" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} مع {ph1} و {ph2} الحقول" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "قراءة البرامج النصية المحملة" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4577,7 +4585,7 @@ msgstr "" "البرنامج النصي الملتقط لمعرفة كيفية استخدام البيانات:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4589,7 +4597,7 @@ msgstr "" "من البرنامج النصي ؛ يثبت التقاط الشبكة أن هذه النقرة مطلوبة {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4601,7 +4609,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4625,65 +4633,65 @@ msgstr "" "مراقبة تصدير الملاحظات مع REA: حدد صفحة متصفح ، والتقاط نقرة ، وفحص الطلب " "واتبع البرنامج النصي للتصدير." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "مراقبة المتصفح" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "نسخ بدء متصفح المثال" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "نسخة مثال موجه" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "نسخ ابحث عن الصفحة" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "نسخ التقاط الثواني العشر القادمة" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "نسخ قراءة البرامج النصية المحملة" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}الرئيسية{ph1} / أدلة" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA أدلة." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4692,37 +4700,37 @@ msgstr "" "تحليل وظيفة الأم ، وهو Electron تصدير أو طلب متصفح. يتضمن كل دليل موجه ورمز " "ونتائج." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "التحقيق الأول" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "إعداد REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "ربط مساعدك البرمجي أو استخدام REA من المحطة." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "تبدأ مع REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "برامج كود الآلة" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "استعادة حساب يسار / يمين موقف الصوت" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4731,22 +4739,22 @@ msgstr "" "تبدأ مع Windows لعبة قابلة للتنفيذ. فحص التعليمات ، اتبع الدالة المستدعية ، " "وقراءة الثوابت الرقمية والتحقق من ج المستردة." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "تحليل دليل برامج كود الآلة" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "اتبع أ CSV تصدير" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4755,30 +4763,30 @@ msgstr "" "التطبيق ملاحظات صغيرة ينتشر ميزة واحدة عبر العارض ، التحميل المسبق والعملية " "الرئيسية. استخدام REA لتوصيل أبي ، قناة إيبك وكاتب الملف." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript & Electron دليل" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "للحصول على تطبيق أكبر حجما ، اتبع {ph0}Notionجسر الحافظة{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "سلوك المتصفح" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "مراقبة نقرة" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4787,7 +4795,7 @@ msgstr "" "افتح مثال ملاحظات العمل ، والتقط طلب تصدير وابحث عن الكود الذي يحول استجابته" " إلى تنزيل." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "دليل مراقبة المتصفح" @@ -4806,12 +4814,12 @@ msgstr "" "تعلم REA من خلال أمثلة قصيرة العمل: حساب أصلي ، و Electron CSV تصدير وطلب " "المتصفح." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -4820,20 +4828,20 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}الرئيسية{ph1} / {ph2}أدلة{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "تتبع Electron{ph0}CSV تصدير." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4842,14 +4850,14 @@ msgstr "" "اتبع نقرة زر من واجهة برمجة تطبيقات الصفحة ، من خلال Electron التصنيف الدولي" " للبراءات ، إلى CSV كاتب ملف." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "في هذا الدليل" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4857,7 +4865,7 @@ msgstr "{ph0}المثال{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4865,7 +4873,7 @@ msgstr "{ph0}اسأل وكيلك{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4873,7 +4881,7 @@ msgstr "{ph0}تتبع رمز التصدير{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4881,20 +4889,20 @@ msgstr "{ph0}جرب المثال{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}فحص CSV كاتب{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "أين تذهب\" ملاحظات التصدير\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4906,7 +4914,7 @@ msgstr "" " يدعو أبي في الصفحة ، يعبر إلى العملية الرئيسية ، ويكتب CSV. ينتشر السلوك " "عبر عدة ملفات." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "ال CSV تصدير عبر Electron العمليات" @@ -4920,7 +4928,7 @@ msgstr "ال CSV تصدير عبر Electron العمليات" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4937,7 +4945,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4954,7 +4962,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4967,13 +4975,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} تنسيق الملاحظات → {ph1} يكتب {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -4984,14 +4992,14 @@ msgstr "" "المسار من التعليمات البرمجية ؛ يمكن لالتقاط وقت التشغيل التحقق مما يتم " "تنفيذه." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "اسأل عن CSV تصدير" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5007,14 +5015,14 @@ msgstr "{ph0}ربط وكيلك إلى REA{ph1} وإعطائها دليل الت #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "نسخ" @@ -5025,7 +5033,7 @@ msgstr "نسخ" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5036,7 +5044,7 @@ msgstr "" "في هذا التطبيق. أين هو CSV خلق?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5044,7 +5052,7 @@ msgid "" "{ph0}." msgstr "مثال موجه. قم بتضمين المسار المطلق إلى مجلد التطبيق أو {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5054,17 +5062,17 @@ msgstr "" "REA يقرأ ملفات التطبيق ويبني خريطة نقاط الدخول والوحدات وحدود العملية. " "يستخدم وكيلك هذه الخريطة لتضييق التحقيق إلى ميزة التصدير." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "تتبع رمز التصدير" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "تستدعي الصفحة واجهة برمجة تطبيقات صغيرة" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5074,7 +5082,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5086,7 +5094,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5096,7 +5104,7 @@ msgstr "" "قراءة المعالج يجيب على السؤال الأصلي: {ph0} تنسيق الملاحظات ، والعملية " "الرئيسية يكتب {ph1} في مجلد التنزيلات الخاص بالمستخدم." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5105,7 +5113,7 @@ msgstr "" "سجلت بواسطة REA 4.1.0 في المثال القابل للتنزيل أدناه. تصاحب مواقع المصدر " "نتائج واجهة برمجة التطبيقات والقناة والمعالج." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "حلل المثال بنفسك" @@ -5113,25 +5121,25 @@ msgstr "حلل المثال بنفسك" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}تحميل مثال الرمز البريدي{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "تصفح ملفات المصدر الستة" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "تحليل التطبيق الثابت" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5141,7 +5149,7 @@ msgstr "" "استبدل المسار بالمجلد الذي قمت بفك ضغطه. يجب أن تجد قناة إيبك واحدة ومعالج " "واحد مطابقة في {ph0}. مواقع المصدر في {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5152,13 +5160,13 @@ msgstr "" "اتباع سلسلة حرفية أو اسم واجهة برمجة التطبيقات أو قناة إيبك مع REAأدوات تتبع" " الميزات." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "فحص CSV كاتب" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5168,7 +5176,7 @@ msgstr "" "اتبع {ph0} إلى معالجها. المدخلات التي تصل إلى CSV كاتب, وماذا يحدث إذا فشلت " "كتابة الملف?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5183,7 +5191,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5197,7 +5205,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5211,7 +5219,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5236,32 +5244,32 @@ msgstr "" "تتبع الملاحظات CSV تصدير من خلال أبي العارض ، التحميل المسبق ومعالج إيبك مع " "REA. يتضمن ملفات أمثلة قابلة للتنزيل ونتائج تحليل تم التحقق منها." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "نسخة مثال موجه" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "نسخ تحليل التطبيق الثابت" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -5270,20 +5278,20 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}الرئيسية{ph1} / {ph2}أدلة{ph3} / تحليل برامج كود الآلة" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "استعادة DX-Ballفي{ph0}حساب عموم الصوت." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5291,14 +5299,14 @@ msgid "" msgstr "" "افحص التعليمات الأصلية ، وحدد المدخلات والثوابت ، ثم تحقق من ج المستردة." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "في هذا الدليل" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5306,7 +5314,7 @@ msgstr "{ph0}المثال{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5314,7 +5322,7 @@ msgstr "{ph0}اسأل وكيلك{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5322,7 +5330,7 @@ msgstr "{ph0}قراءة REA النتائج{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5330,18 +5338,18 @@ msgstr "{ph0}استرداد والتحقق{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}استخدام ثنائي الخاصة بك{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "حساب اليسار / اليمين ستيريو الصوت لتحديد المواقع" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5352,7 +5360,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5364,7 +5372,7 @@ msgstr "" "يعود تعليماته والدوال المستدعية ، والتي تعطي وكيل وسيلة للتحقيق في الحساب " "المفقود." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "جديد على هذه الشروط?" @@ -5373,7 +5381,7 @@ msgstr "جديد على هذه الشروط?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5385,7 +5393,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5398,7 +5406,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5411,7 +5419,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5422,7 +5430,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5432,7 +5440,7 @@ msgstr "" "{ph0}الثوابت:{ph1} الأرقام الثابتة المخزنة في البرنامج ، وقراءة بايت الخام " "وفك الشفرة." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "ثلاث أدلة ، حساب واحد" @@ -5443,7 +5451,7 @@ msgstr "ثلاث أدلة ، حساب واحد" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5460,7 +5468,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5478,7 +5486,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5488,14 +5496,14 @@ msgstr "" "{ph0}03 * بايت البيانات{ph1}{ph2}الثوابت الرقمية{ph3}{ph4}بايت المشار إليها " "فك شفرة ل {ph5}, {ph6} وقيمة مقياس.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " "interprets them together." msgstr "REA لوازم التعليمات ، والعلاقة الدعوة وبايت. الوكيل يفسر لهم معا." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "اسأل عن السلوك" @@ -5504,7 +5512,7 @@ msgstr "اسأل عن السلوك" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5514,19 +5522,19 @@ msgstr "" "بعد {ph0}الاتصال REA إلى وكيلك{ph1} و {ph2}إعداد أداة تحليل أصلية{ph3}، قدم " "الملف التنفيذي المحلي وسؤال:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "ما هي أداة التحليل التي يجب أن أستخدمها?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA يحتاج إلى واحد من هؤلاء لقراءة البرامج الأصلية:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5540,7 +5548,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5552,7 +5560,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5562,7 +5570,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5576,14 +5584,14 @@ msgstr "انظر {ph0}إعداد تحليل برامج رمز الجهاز{ph1} #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "نسخ" @@ -5594,7 +5602,7 @@ msgstr "نسخ" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5604,7 +5612,7 @@ msgstr "" "{ph0}›{ph1}{ph2}استخدام REA لمعرفة كيف DX-Ball يحسب بالغسل الصوت. شرح الحساب" " وإظهار التعليمات البرمجية.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5615,7 +5623,7 @@ msgstr "" "للتنفيذ. REA لا يشمل DX-Ball، لذا استخدم نسختك الخاصة ، أو اطرح نفس النوع من" " الأسئلة حول صغيرة أخرى Windows برنامج لديك." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "كيف يمكنني الحصول على المسار الكامل للملف?" @@ -5624,7 +5632,7 @@ msgstr "كيف يمكنني الحصول على المسار الكامل للم #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5639,7 +5647,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5651,7 +5659,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5659,17 +5667,17 @@ msgid "" "appears." msgstr "{ph0}أي نظام:{ph1} اسحب الملف إلى نافذة طرفية ويظهر مساره." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "قراءة REA النتائج" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "قراءة المدخلات" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5678,13 +5686,13 @@ msgstr "" "تقوم التعليمات بتحميل وسيطة عدد صحيح وتحويلها لحساب الفاصلة العائمة. هذا هو " "الإدخال الغائب عن عرض الكود الكاذب الأول." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "اتبع الدالة المستدعية" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5694,12 +5702,12 @@ msgstr "" "REA يحدد الدالة المستدعية ضرب الطوب. تعليماته السابقة تضاعف إحداثيات البلاط " "في 30 ؛ مضيفا {ph0} (20) يعطي موقف شاشة الطوب." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "قراءة الثوابت المشار إليها" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5708,12 +5716,12 @@ msgstr "" "يشير الحساب إلى هذه العناوين. قراءة وحدات البايت تزود القيم الفعلية ؛ يخبر " "ترتيب التعليمات الوكيل كيف يتم استخدامها." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "اكتب وتحقق من الوظيفة المستردة" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5723,7 +5731,7 @@ msgstr "" "بمقياس 1.0 ، مواضع الشاشة 0 و 320 و 640 خريطة إلى -500 و 0 و 500 قبل تحويل " "عدد صحيح. يضع الحساب وسط الشاشة في وسط حقل الاستريو." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5735,20 +5743,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}انظر التحقيق الكامل ومقارنة التجميع إلى ج{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "تحاول ذلك مع ثنائي الخاصة بك" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5761,7 +5769,7 @@ msgstr "" "مكتبة وميزة للتحقيق فيها. تتضمن أسئلة البداية المفيدة \"كيف يتم تحليل هذا " "الملف?\"أو\" ما هي الوظيفة التي تتعامل مع إجراء القائمة هذا?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5770,13 +5778,13 @@ msgstr "" "إذا كنت تعرف بالفعل اسم دالة أو عنوانا ، فيمكنك الاستعلام عنه من الجهاز. " "للحصول على تكوين Ghidra تركيب:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "تحليل الوظيفة" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5789,7 +5797,7 @@ msgstr "" "يستورد الاحتجاج ويحلل الثنائي ، ثم يغلق جلسته. وكيلك MCP استعلامات إعادة " "استخدام ثنائي المستوردة في حين أن الدورة مفتوحة." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5812,50 +5820,50 @@ msgstr "" "استعادة حساب الأصلي مع REA: فحص التعليمات ، اتبع الدالة المستدعية ، وقراءة " "الثوابت والتحقق من إعادة بنائها ج." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "تحليل برامج كود الآلة" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "نسخة مثال موجه" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "نسخ تحليل وظيفة" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "إعداد REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5863,7 +5871,7 @@ msgstr "{ph0}إعداد REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5871,7 +5879,7 @@ msgstr "{ph0}ما هو إعادة?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5879,7 +5887,7 @@ msgstr "{ph0}كيف يساعدك REA{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5887,7 +5895,7 @@ msgstr "{ph0}لعبة ديناصور{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5895,7 +5903,7 @@ msgstr "{ph0}آلة حاسبة{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5903,7 +5911,7 @@ msgstr "{ph0}حاول REA{ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5911,7 +5919,7 @@ msgstr "{ph0}تعمّق أكثر{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5919,25 +5927,25 @@ msgstr "{ph0}مساعدة وردود الفعل{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}المجتمع{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "الهندسة العكسية ، مع مساعدك البرمجي" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "اكتشف كيف{ph0}تعمل البرامج." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5946,7 +5954,7 @@ msgstr "يوفّر REA لمساعد البرمجة لديك أدوات لفحص #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5954,13 +5962,13 @@ msgstr "تعرف بالفعل إعادة? {ph0}تخطي إلى أدلة التح #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "تريد أن تذهب أعمق? {ph0}اقرأ المدونة Blog{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "انسخ هذا الطلب إلى مساعد البرمجة لديك:" @@ -5973,38 +5981,38 @@ msgstr "انسخ هذا الطلب إلى مساعد البرمجة لديك:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "نسخ" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "أو نفّذ هذا الأمر في الطرفية:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "راجع خطة الإعداد ووافق عليها، ثم أعد تشغيل المساعد." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "ما هي الهندسة العكسية؟" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6017,7 +6025,7 @@ msgstr "فهم طريقة عمل البرنامج من خلال {ph0}فحص ال #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6029,7 +6037,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6037,7 +6045,7 @@ msgstr "قبل REA · تبحث {ph0}بنفسك{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6045,7 +6053,7 @@ msgstr "{ph0}01{ph1} فك رموز الفروع" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6053,7 +6061,7 @@ msgstr "{ph0}02{ph1} تتبع المكالمات" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6063,20 +6071,20 @@ msgstr "{ph0}03{ph1} استعادة القاعدة" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}الأصل · 64 * تعليمات مختارة{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * أي فرع?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6085,29 +6093,29 @@ msgid "" msgstr "" "“{ph0}0/5 ب? 0 * 5 ج?{ph1} اثنين يقفز إلى نفس المكان. التي مشغلي هذه?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "ابحث عن معرفات الأوامر ، ثم قم بتسمية الفرع." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "تقسيم ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "ضرب ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · ماذا تفعل الدوال المستدعاة؟" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6117,24 +6125,24 @@ msgstr "" "\"100 واضح. المكالمات هي مجرد عناوين. {ph0}أي واحد يقسم? القيمة التي يذهب " "في?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "افحص وظائف المساعد وتتبع القيم المخزنة." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "تقسيم" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * ما هي القاعدة?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6144,19 +6152,19 @@ msgstr "" "\"يتضاعف هذا المسار من خلال المدخلات الأخرى. لذا {ph0}10 ٪ تعني 10 ٪ من " "200{ph1} بعد +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "قم بتسمية المعاملات وتحقق من كلا مساري المشغل." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "منطق الخبراء التوضيحي" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6167,20 +6175,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "مع REA · تسأل {ph0}مساعدك{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "طلب واحد فقط." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6194,49 +6202,49 @@ msgstr "اسأل المساعد {ph0}بكلمات بسيطة.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال موجه * آلة حاسبة" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "مثال على الإجابة * بناء على النتائج" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "بعد + ، يأخذ زر ٪ {ph0}نسبة مئوية من الرقم الأول.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "ما يوفّره REA" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "تعليمات المعالج ، رمز فك والمكالمات." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "ما يشرحه المساعد" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "أي فرع ينطبق ، ما يحسب وكيفية إعادة بنائه." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6248,7 +6256,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6258,37 +6266,37 @@ msgstr "" "{ph0}دعونا نحاول مثالين.{ph1} تغيير سرعة اللعبة ، ثم العودة إلى آلة حاسبة " "وإعادة بناء زر ٪ لها." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "مثال 01 · Chromeلعبة الديناصورات" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "لماذا يصبح الديناصور أسرع؟" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "الهدف" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "إعادة بناء اللعبة مع {ph0}سرعة قابلة للتعديل.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "لماذا عكس هندسة ذلك?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6298,47 +6306,47 @@ msgstr "" "لإعادة إنتاج تسارعها ، نحتاج إلى {ph0}القاعدة في لعبة الجري{ph1}: مدى سرعة " "يبدأ ، وكم يزيد وعندما يتوقف." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "جرّب اللعبة المعاد بناؤها" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "العب" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "اقفز ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "ابدأ من جديد" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "السرعة" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "استخدم قاعدة التسارع المستردة" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "القاعدة الأصلية: ابدأ من 6 ، ثم زد نحو 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "حرك شريط التمرير لضبط السرعة الخاصة بك. الفضاء أو القفز يزيل الصبار." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6346,14 +6354,14 @@ msgid "" msgstr "" "تمكين JavaScript للعب إعادة الإعمار. يظل الرمز والشرح أعلاه قابلا للقراءة." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "ما أعاده REA" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6371,7 +6379,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6383,7 +6391,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال موجه * لعبة د #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6397,7 +6405,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6409,7 +6417,7 @@ msgstr "الهدف الذي تم فحصه: {ph0}وايو Chromium- مستمد م #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6419,12 +6427,12 @@ msgstr "" "{ph0}تبدأ في 6.{ph1} إضافة {ph2}0.001{ph3} كل تحديث دون تصادم ، في حين أن " "السرعة أقل {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "افتح مختبر السرعة →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "ماذا يفعل كل جزء" @@ -6435,7 +6443,7 @@ msgstr "ماذا يفعل كل جزء" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6451,7 +6459,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6468,7 +6476,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6478,13 +6486,13 @@ msgstr "" "{ph0}03 * أنت{ph1}{ph2}تغيير السرعة واللعب{ph3}{ph4}جرب التسارع الأصلي ، ثم " "اختر وتيرتك الخاصة.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "راجع البرنامج النصي والشيكات وكيفية تجربة التحليل" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6494,7 +6502,7 @@ msgstr "" "REA تفقد إصدار متصفح هتب من خلال اتصال التصحيح المحلي وعاد تحميلها {ph0}، " "بما في ذلك مصدرها وهضمها." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6507,7 +6515,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6523,7 +6531,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6540,26 +6548,26 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" "{ph0}Inspected speed code{ph1} · {ph2}Chromium Authors · BSD license{ph3}" msgstr "{ph0}فحص رمز السرعة{ph1} · {ph2}Chromium الكتاب * رخصة بسد{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "مثال 02 · Windows آلة حاسبة" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "أعد بناء زر % في الآلة الحاسبة." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6568,7 +6576,7 @@ msgstr "بناء آلة حاسبة صغيرة أن يعالج {ph0}كلا + و c #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6578,29 +6586,29 @@ msgstr "" "يستخدم نفس الزر {ph0}قواعد مختلفة بعد + و ×.{ph1} نقوم بفحص التطبيق المثبت " "للعثور على الرقم الذي يتم تطبيق النسبة عليه." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "جرب الحساب" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "إعادة ضبط" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10 ٪ من 200 = 20. ثم 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "توضيح تفاعلي لقاعدة النسبة المئوية التي تم فحصها." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6612,7 +6620,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6626,7 +6634,7 @@ msgstr "لهذا المثال, {ph0} و {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6640,7 +6648,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال موجه * إعادة #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6651,7 +6659,7 @@ msgstr "" "{ph0}›{ph1}{ph2}استخدام REA لتفقد Windows زر ٪ آلة حاسبة. استعادة القواعد " "بعد + و × ، ثم بناء آلة حاسبة صغيرة تستخدم على حد سواء.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "مع +" @@ -6659,13 +6667,13 @@ msgstr "مع +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}خذ 10٪ من الرقم الأول.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "مع ×" @@ -6673,13 +6681,13 @@ msgstr "مع ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}تحويل 10 ٪ إلى 0.1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "من التطبيق المثبت إلى زر ٪ العمل" @@ -6691,7 +6699,7 @@ msgstr "من التطبيق المثبت إلى زر ٪ العمل" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6708,7 +6716,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6719,12 +6727,12 @@ msgstr "" "{ph0}03 * وكيلك يفسر ذلك{ph1}{ph2}شرح وإعادة إنتاج القواعد{ph3}{ph4}تحقق من " "الفرع مع مصدر مايكروسوفت ، ثم حاول + و × أعلاه.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "انظر الرمز الحقيقي وكيف تم التحقق من الإجابة" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6744,7 +6752,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6754,17 +6762,17 @@ msgstr "" "{ph0}النسبة المئوية للتنفيذ{ph1} · {ph2}حالات اختبار مايكروسوفت{ph3} · " "{ph4}دليل الإعداد الأصلي{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "التحقيق الأول الخاص بك" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "حاول REA على تطبيق صغير." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6773,12 +6781,12 @@ msgstr "" "تحميل ملاحظاتنا سبيل المثال ، تتبع لها CSV تصدير ، وتحقق من إدخال واحد تم " "تغييره." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "جرب المثال الإرشادي" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "هل تريد التعمّق أكثر؟" @@ -6787,7 +6795,7 @@ msgstr "هل تريد التعمّق أكثر؟" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6806,13 +6814,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال موجه * الموقع" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "نعم ، هذا واحد." @@ -6825,7 +6833,7 @@ msgstr "نعم ، هذا واحد." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6838,7 +6846,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال موجه * إعادة #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6851,23 +6859,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}انظر ال DX-Ball دراسة حالة case{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "لخطوات الإعداد والتحليل ، اختر هدفك:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "برامج كود الآلة" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -6876,17 +6884,17 @@ msgstr "" "فحص الوظائف والسلاسل والمراجع وعلاقات استدعاء الوظائف في الملفات التنفيذية " "والمكتبات." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "تحليل دليل برامج كود الآلة" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -6895,17 +6903,17 @@ msgstr "" "وحدات الخريطة ، والطرق ، والتصنيف الدولي للبراءات والتبعيات الأصلية من مجلد " "التطبيق أو ASAR أرشيف." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "سير عمل التطبيق" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "نشاط المتصفح ووقت التشغيل" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -6913,12 +6921,12 @@ msgid "" msgstr "" "التقط المتصفح المحدد أو نشاط العملية ، ثم قارن النتائج عبر عمليات التشغيل." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "دليل مراقبة المتصفح" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "لديك أسئلة؟" @@ -6929,7 +6937,7 @@ msgstr "لديك أسئلة؟" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6939,12 +6947,12 @@ msgstr "" "{ph0}قراءة التعليمات{ph1}, {ph2}الدردشة معنا على Discord{ph3}، أو {ph4}افتح " "أ GitHub القضية{ph5} لالبق وطلبات الميزة." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "انضم إلى المجتمع" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -6967,27 +6975,27 @@ msgstr "" "تطبيقات الهندسة العكسية والثنائيات وسلوك المتصفح مع مساعدك البرمجي. اتبع " "أدلة واضحة وجرب أمثلة تفاعلية مع REA." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "نسخ REA موجه التثبيت" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "نسخ أمر الإعداد" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "اتبع تحليل الآلة الحاسبة اليدوية" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "نسخة حاسبة النسبة المئوية السؤال" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -6995,37 +7003,37 @@ msgid "" msgstr "" "ديناصور لعبة صغيرة. استخدم زر القفز أو اضغط على الفضاء أثناء تركيز اللعبة." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "نسخة ديناصور تحليل موجه" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "اختر الحساب" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "نسخ حاسبة تحليل موجه" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "نسخ موجه مشروع موقع الويب" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "نسخة لعبة إعادة الإعمار موجه" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -7034,25 +7042,25 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}الرئيسية{ph1} / {ph2}يعرض{ph3} / أندرويد" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "دراسة حالة · Aegis الموثق" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "كيف يمكن للمصادق{ph0}إنشاء رمز تسجيل الدخول?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7061,17 +7069,17 @@ msgstr "" "يتغير الرمز المكون من ستة أرقام كل 30 ثانية. استخدام REA للعثور على الحساب " "في Android APK، ثم إعادة بنائه مع ساعة يمكنك التحكم." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 · أندرويد * الإصدار الرسمي APK * 6.9 ميغابايت" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "عرض Aegis على GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "من APK إلى رمز يمكنك إعادة إنتاجه" @@ -7082,7 +7090,7 @@ msgstr "من APK إلى رمز يمكنك إعادة إنتاجه" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7100,7 +7108,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7118,7 +7126,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7130,14 +7138,14 @@ msgstr "" "رمز.{ph3}{ph4}يستنسخ العرض التوضيحي الجديد للمتصفح القاعدة ويتحقق منها مقابل" " الحالات المرجعية العامة.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "في دراسة الحالة هذه" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7145,7 +7153,7 @@ msgstr "{ph0}اسأل وكيلك{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7153,7 +7161,7 @@ msgstr "{ph0}جرب مولد الكود{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7161,7 +7169,7 @@ msgstr "{ph0}العثور على رمز مع REA{ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7169,7 +7177,7 @@ msgstr "{ph0}قراءة الحساب{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7177,20 +7185,20 @@ msgstr "{ph0}تحقق من إعادة الإعمار{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}فحص APK نفسك{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "اسأل وكيلك" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7208,14 +7216,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "نسخ" @@ -7223,7 +7231,7 @@ msgstr "نسخ" # Reviewed for concrete meaning, software terminology and readable sentences. #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7233,7 +7241,7 @@ msgstr "" "هذا طلب نموذجي لتحليل ملف APK الذي نزّلته. اضبط تحليل Android في REA أولًا. " "{ph0}تنزيل APK وإعداد التحليل ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "جرب مولد الكود" @@ -7241,7 +7249,7 @@ msgstr "جرب مولد الكود" # Reviewed for concrete meaning, software terminology and readable sentences. #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7252,33 +7260,33 @@ msgstr "" "يقسّم التطبيق الوقت إلى {ph0}فترات من 30 ثانية.{ph1} يجمع رقم الفترة مع " "مفتاح الحساب لإنشاء الرمز. يعطي المفتاح نفسه والفترة نفسها الرمز نفسه." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "حرك الساعة عبر 60 ثانية" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "الوقت" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "ثواني" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "لدينا مثال قابل للتعديل على مدار الساعة" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "كتلة 30 ثانية" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "بلوك" @@ -7287,35 +7295,35 @@ msgstr "بلوك" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 ثانية{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "كود تم إنشاؤه" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "مفتاح الحساب + كتلة - ستة أرقام" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "مثال الوقت ، بالثواني" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 ثانية" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 ثانية" @@ -7324,7 +7332,7 @@ msgstr "60 ثانية" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7336,7 +7344,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7346,7 +7354,7 @@ msgstr "" "المفتاح ثابت ، عام {ph0}رك 6238 بيانات الاختبار{ph1}. يقوم العرض التوضيحي " "بتنفيذ الحساب المسترد من APK." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7354,18 +7362,18 @@ msgid "" msgstr "" "يوضح الرسم البياني النتيجة في 59 ثانية. تمكين JavaScript لتغيير الساعة." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "العثور على رمز مع REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "تضييق APK إلى ثلاث فئات" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7375,14 +7383,14 @@ msgstr "" "{ph0} هو مرشح الحساب ؛ يتعلق الاثنان الآخران بشريط التقدم والحسابات " "المستوردة. TOTP تعني كلمة مرور لمرة واحدة تستند إلى الوقت." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "قم بتوصيل المولد بشاشة التطبيق" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7393,7 +7401,7 @@ msgstr "" " التفتيش {ph0} ثم يظهر استدعاء العرض {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7402,14 +7410,14 @@ msgid "" msgstr "" "تظهر الطلبات مسار إدخال مختصر. أسماء فئة النتيجة حذف المشترك {ph0} بادئة." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "قراءة الحساب" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7423,7 +7431,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7431,7 +7439,7 @@ msgstr "{ph0}01{ph1} كتلة الوقت" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7439,7 +7447,7 @@ msgstr "{ph0}02{ph1} مفتاح + كتلة" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7447,7 +7455,7 @@ msgstr "{ph0}03{ph1} ستة أرقام" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7459,7 +7467,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7472,7 +7480,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7486,7 +7494,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7496,7 +7504,7 @@ msgstr "" "مقتطفات من عدة طرق تفتيشها ، مع التفاف خط للعرض. اللوحة اليمنى هي ملخص " "توضيحي. {ph0}Aegis الرمز هو غل-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "داخل المولد" @@ -7505,7 +7513,7 @@ msgstr "داخل المولد" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7515,7 +7523,7 @@ msgstr "" "المفرج عنهم APK يضع {ph0} في {ph1}. REA يتبع الاستدعاء دالة من {ph2} ويعيد " "هذا الجسم ؛ المصدر الأصلي يدعو المساعد {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7531,20 +7539,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}قارن مع مصدر الإصدار المطابق{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "تحقق من إعادة الإعمار" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7556,29 +7564,29 @@ msgstr "" " مع إعادة بناء مستقلة على {ph0}133 حالة اختبار{ph1}، بما في ذلك حدود كتلة " "الوقت والرموز التي تبدأ بالصفر." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "مثال الوقت" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "رمز مكون من ستة أرقام" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 ثانية" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 ثواني" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7588,17 +7596,17 @@ msgstr "" "يتطابق المولد أيضا مع الستة المنشورة SHA-1 الحالات المرجعية في {ph0}رك " "6238{ph1}. تحقق من تنفيذ المتصفح ضدهم:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "تشغيل الشيكات المرجعية" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "اقرأ حساب العرض التوضيحي" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7607,7 +7615,7 @@ msgstr "" "تستخدم الحالات المرجعية ثمانية أرقام. يتحقق الشيك أيضا من نتائجهم المكونة من" " ستة أرقام." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7616,14 +7624,14 @@ msgstr "" "يعمل التحقق استخراج أساليب جافا والتجريبي الجديد. Android APK تم تفتيشه بشكل" " ثابت." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "فحص APK نفسك" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7635,7 +7643,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7645,18 +7653,18 @@ msgstr "" "تحليل Android يحتاج جدك الكامل 17 أو في وقت لاحق. حدده مع {ph0} أو {ph1}. " "هذه الحالة تستخدم جدك 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "نقطة REA في ملف الموفر وفحص APK:" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7668,7 +7676,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7678,7 +7686,7 @@ msgstr "" "السؤال التالي: {ph0}ماذا يحدث عندما يستخدم الحساب ثمانية أرقام أو فاصل زمني " "مختلف?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "المصادر" @@ -7694,7 +7702,7 @@ msgstr "المصادر" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7708,14 +7716,14 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "" "{ph0}رك 6238 الحالات المرجعية{ph1} · {ph2}بيانات الاختبار التجريبي{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7740,37 +7748,37 @@ msgstr "" "فحص Aegis اندرويد APK مع REA، استعد حساب رمز تسجيل الدخول المكون من ستة " "أرقام وجرب إعادة الإعمار بساعة قابلة للتعديل." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK دراسة حالة" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "نسخ Aegis مثال موجه" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "اتبع حساب رمز تسجيل الدخول" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "نسخ APK قيادة التفتيش" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -7779,26 +7787,26 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}الرئيسية{ph1} / {ph2}يعرض{ph3} / فرقة العمل" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "دراسة حالة * أسفل 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "ابحث عن العلم في{ph0}ثنائي كتف." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7808,17 +7816,17 @@ msgstr "" "استخدام REA لفحص مدقق علم صغير ، حول قواعده إلى معادلات وابحث عن إدخال يجعل " "البرنامج الأصلي يطبع {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "مربعات ملثمين مدقق العلم * سهل · Linux إكس 86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "عرض التحدي الأصلي" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "من ثنائي إلى إجابة محددة" @@ -7829,7 +7837,7 @@ msgstr "من ثنائي إلى إجابة محددة" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7846,7 +7854,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7863,7 +7871,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7874,20 +7882,20 @@ msgstr "" "{ph0}03 * حل وتشغيل{ph1}{ph2}العلم المسترد-صحيح!{ph3}{ph4}نص بيثون يحل " "المعادلات. REA يلتقط البرنامج الأصلي قبول النتيجة.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "التحدي هو جوزيف ، الذي نشر في مستودع داوندركتف الرسمي." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "في دراسة الحالة هذه" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7895,7 +7903,7 @@ msgstr "{ph0}ابحث عن رمز التحقق{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7903,7 +7911,7 @@ msgstr "{ph0}قراءة قناع واحد{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7911,7 +7919,7 @@ msgstr "{ph0}الجمعية إلى رمز قابل للقراءة{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7919,7 +7927,7 @@ msgstr "{ph0}حل المعادلات{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7927,20 +7935,20 @@ msgstr "{ph0}تحقق من الجواب{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}انها محاولة لنفسك{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "ابحث عن رمز التحقق" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7958,17 +7966,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "نسخ" @@ -7979,7 +7987,7 @@ msgstr "نسخ" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7991,7 +7999,7 @@ msgstr "" "كيفية عمل الشيكات ، ثم تحقق من الإجابة باستخدام البرنامج " "الأصلي.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8000,12 +8008,12 @@ msgstr "" "مثال موجه ، مع التحدي الذي تم تنزيله متاح محليا وتحليل موفر برامج رمز الجهاز" " المتصل." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "اتبع موجه الإدخال إلى وظيفته" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8014,14 +8022,14 @@ msgstr "" "يعطي المرجع الوكيل مكانا للتحقيق ، على الرغم من إزالة أسماء الوظائف الأصلية " "القابلة للتنفيذ." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "قراءة المدقق واثنين من المساعدين" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8033,7 +8041,7 @@ msgstr "" "الرموز المحددة وتقارن النتيجة برقم مخزن. لها {ph0}- خطوات بايت عبر {ph1} " "بايت تعطي 26 أقنعة." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8042,12 +8050,12 @@ msgstr "" "يتم اختيار هذه النتائج من جديد REA تحليل. يتم تقصير مسار الهدف المحلي للعرض " "؛ تشير العناوين إلى REAالصورة المستوردة." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "شيك واحد يكشف عن حرف واحد" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8060,13 +8068,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "الاختيار السابع يختار موقف واحد فقط. {ph0}الشكل المفتوح{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "اقرأ القناع وهدفه من الثنائي" @@ -8075,7 +8083,7 @@ msgstr "اقرأ القناع وهدفه من الثنائي" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8087,12 +8095,12 @@ msgstr "" "الهدف هو عدد صحيح صغير. معا ، تخبر هذه البايتات الوكيل أن {ph2}، بحيث تكون " "هذه الشخصية {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "من التعليمات إلى فحص قابل للقراءة" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8102,7 +8110,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8110,7 +8118,7 @@ msgstr "{ph0}01{ph1} ابدأ" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8118,7 +8126,7 @@ msgstr "{ph0}02{ph1} اختر" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8126,7 +8134,7 @@ msgstr "{ph0}03{ph1} إضافة" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8134,18 +8142,18 @@ msgstr "{ph0}04{ph1} تقدم" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} قارن" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * تعليمات أصلية مختارة" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "قراءة ج * ملخص الاختيار واحد" @@ -8153,7 +8161,7 @@ msgstr "قراءة ج * ملخص الاختيار واحد" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8161,7 +8169,7 @@ msgstr "{ph0}01 * ابدأ من الصفر.{ph1} {ph2} يحمل المبلغ ا #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8173,7 +8181,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8185,7 +8193,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8199,7 +8207,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8209,7 +8217,7 @@ msgstr "" "{ph0}05 * مقارنة مع الهدف المخزن.{ph1} تتلقى وظيفة الاستدعاء المبلغ في " "{ph2}. عدم تطابق يقفز إلى {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8218,12 +8226,12 @@ msgstr "" "تأتي التعليمات من مساعد التلخيص ووظيفة الاتصال الخاصة به. ال ج هو ملخص " "توضيحي بأسماء وصفية وحلقة مسطحة من 36 خلية." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "حل المعادلات 26" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8234,13 +8242,13 @@ msgstr "" "للأحرف ويتطلب إجمالي 1441. تعطي التحديدات المتداخلة معادلات يمكن أن يحلها نص" " بايثون صغير معا." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "بيثون * حلالا مقتطفات" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8253,19 +8261,19 @@ msgstr "" "المستخرجة ويفترض أ {ph0} العلم مع الحروف والأرقام والشرطات السفلية والأقواس." " يشمل التنزيل الكامل جميع الأقنعة والأهداف الـ 26." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "تحميل حلالا كاملة" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "تحقق من الإجابة مع البرنامج الأصلي" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8277,47 +8285,47 @@ msgstr "" "محدد من {ph0} إلى {ph1} يجعل المبلغ الأول 1440 بدلا من 1441, والبرنامج يرفض " "ذلك." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "المدخلات" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "الإخراج المرصود" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "رمز الخروج" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "علم حلالا" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "تم تغيير حرف واحد" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "إظهار العلم المسترد والإخراج الملتقط" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * إخراج البرنامج الأصلي" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "نسخ العلم" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8326,12 +8334,12 @@ msgstr "" "تتطابق القيمة المستردة أيضا مع العلم في البيانات الوصفية للتحدي المنشورة " "للمنظمين ، والتي تم فحصها بعد حل الثنائي." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "المصدر والهوية المستهدفة وتفاصيل التحليل" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8341,7 +8349,7 @@ msgstr "" "تحليل جديد واثنين من عمليات الالتقاط في 8 أكتوبر 2026 ، باستخدام REA 4.1.0 " "مع Ghidra 12.1.4 على Linux 64. ثنائي هو جردت س 86-64 قزم ، 15 ، 248 بايت." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8363,7 +8371,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8373,12 +8381,12 @@ msgstr "" "{ph0}قارن مع مصدر المنظمين{ph1} · {ph2}تحدي البيانات الوصفية والعلم{ph3} · " "{ph4}REA ملاحظات الأدلة{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "انها محاولة لنفسك" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8387,13 +8395,13 @@ msgstr "" "تحميل التحدي الأصلي وحلالا في مجلد واحد. استخدم المطالبة أعلاه للتحقيق مع " "وكيلك ، أو قم بتشغيل البرنامج النصي المضمن." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "محطة * حل وتشغيل" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8404,7 +8412,7 @@ msgstr "" "يقوم البرنامج النصي بطباعة علامة مرشح ؛ الصقه في موجه البرنامج. حل يحتاج " "بيثون و {ph0}. تشغيل الاحتياجات القابلة للتنفيذ الأصلي Linux س86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "إعداد REA مع مساعدك البرمجي" @@ -8424,27 +8432,27 @@ msgstr "" "استخدام REA لحل المربعات ملثمين مدقق العلم. ابحث عن وظائف الفحص واستخرج " "الأقنعة وقارن العلم المسترد بالبرنامج الأصلي." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "دراسة حالة مدقق العلم" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "نسخة كتف مثال موجه" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "معادلة قناع كتف ؛ التمرير أفقيا على شاشات أصغر" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8454,42 +8462,42 @@ msgstr "" "يتخطى القناع السابع 21 خلية ، ويختار الموضع 21 ، ثم يتخطى 14. فقط تلك الخلية" " تساهم في المجموع. رمز الحرف المطلوب هو 55 ، مما يعني أن الحرف هو 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "اتبع الاختيار كتف" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "نسخ الجمعية كتف" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "نسخة قابلة للقراءة كتف الاختيار" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "نسخة كتف حلالا مقتطفات" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "نسخ العلم المسترد" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "نسخ كتف حلالا الأوامر" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -8498,26 +8506,26 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}الرئيسية{ph1} / {ph2}يعرض{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "دراسة حالة · DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "إعادة البناء DX-Ball{ph0}من قابل للتنفيذ." # Reviewed for concrete meaning, software terminology and readable sentences. -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8526,14 +8534,14 @@ msgstr "" "الهدف هو إعادة بناء لعبة Windows الصادرة عام 1996 بكود C يمكن صيانته. يساعد " "REA المساعد البرمجي على فحص دوال البرنامج الأصلي، دالة بعد أخرى." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows ط386 * ج · REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8545,14 +8553,14 @@ msgstr "" "وقراءة البيانات ؛ ينفذ مشروع إعادة الإعمار ويختبر النتيجة. {ph0}الشكل " "المفتوح{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "في دراسة الحالة هذه" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8560,7 +8568,7 @@ msgstr "{ph0}المشروع{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8568,7 +8576,7 @@ msgstr "{ph0}عموم الصوت{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8576,23 +8584,23 @@ msgstr "{ph0}التحقق من النتيجة{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}مواصلة العمل{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "وظائف جيم التي تمت صيانتها" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "مقارنات مع الكود الأصلي" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "وظائف مع مطابقة بايت المترجمة" @@ -8603,7 +8611,7 @@ msgstr "وظائف مع مطابقة بايت المترجمة" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8613,12 +8621,12 @@ msgstr "" "نقطة تفتيش المشروع: 7 أكتوبر 2026. {ph0}التقدم ليدجر{ph1} · {ph2}تغطية " "الاختبار{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "المشروع حتى الآن" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8632,12 +8640,12 @@ msgstr "" "يستمر العمل في اللعبة القابلة للعب مع فيزياء الكرة والمجداف ومعالجة الطاقة و" " Windows التكامل." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "العثور على حساب يسار / يمين موقف الصوت" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8655,17 +8663,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "نسخ" @@ -8676,7 +8684,7 @@ msgstr "نسخ" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8686,7 +8694,7 @@ msgstr "" "{ph0}›{ph1}{ph2}استخدام REA لمعرفة كيف DX-Ball يحسب بالغسل الصوت. شرح الحساب" " وإظهار التعليمات البرمجية.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8697,7 +8705,7 @@ msgstr "" "أدناه يوضح REA الاستفسارات والأدلة وراء الجواب." # Reviewed for concrete meaning, software terminology and readable sentences. -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8711,7 +8719,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8724,12 +8732,12 @@ msgstr "" "والدعوة {ph2}. أظهر عرض التعليمات الخاص به إدخال مكدس وعمليات الفاصلة " "العائمة. أعطى هذا التناقض الوكيل سببا ملموسا لمواصلة التحقيق." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "عرض فك التحويل الأول" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8738,18 +8746,18 @@ msgstr "" "يظهر الإخراج استدعاء دالة تحويل. قراءة التعليمات أدناه تكشف عن المدخلات " "والتغذية حساب تلك الدعوة." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "الإجابة على ثلاثة أسئلة من خلال REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "استعادة المدخلات المفقودة" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8760,14 +8768,14 @@ msgstr "" "هنا, {ph0} يعرض الإدخال الصحيح المفقود من طريقة عرض برنامج فك التحويل " "البرمجي." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "اتبع الدالة المستدعية لفهم المدخلات" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8777,12 +8785,12 @@ msgstr "" "REA حدد هذا الدالة المستدعية في النتيجة الأولى. مقياس التعليمات السابق {ph0}" " بواسطة 30 ؛ إضافة 20 يعطي تنسيق شاشة الطوب, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "قراءة القيم وراء عناوين الذاكرة" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -8791,12 +8799,12 @@ msgstr "" "البايتات التي تم إرجاعها تنشئ الثوابت الحسابية ومقياس عموم الأولي. يحتوي " "العامل الآن على القيم اللازمة للتعبير ج." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "من عند REAالنتائج إلى ج" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8807,7 +8815,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8815,7 +8823,7 @@ msgstr "{ph0}01{ph1} المدخلات" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8823,7 +8831,7 @@ msgstr "{ph0}02{ph1} اضرب" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8831,7 +8839,7 @@ msgstr "{ph0}03{ph1} طرح" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8839,18 +8847,18 @@ msgstr "{ph0}04{ph1} مقياس" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} العودة" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "الأصلي إكس 86 * مقتطفات" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "أعيد بناؤها ج" @@ -8860,7 +8868,7 @@ msgstr "أعيد بناؤها ج" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8879,7 +8887,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8895,7 +8903,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8912,7 +8920,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8929,7 +8937,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8941,7 +8949,7 @@ msgstr "" "REAنتائج المستدعي. ج يلقي النتيجة إلى {ph4} المقارنات الأصلية-86 تحقق من " "القيمة التي تم إرجاعها." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -8951,23 +8959,23 @@ msgstr "" "يختار مقتطف التجميع تعليمات الإدخال والحساب والإرجاع. تتضمن القائمة الكاملة " "أدناه أيضا المتاجر المتداخلة وإعداد الوظائف وتنظيفها." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "التجميع الكامل والأدلة الداعمة" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA النتيجة * 0 * 406400-0 * 40643 هـ" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "ما لوازم الدالة المستدعية" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8977,54 +8985,54 @@ msgstr "" "وظيفة ضرب الطوب في {ph0} موازين تنسيق البلاط من قبل 30 ، ويضيف 20 ، ثم يدفع " "به قبل الاستدعاء دالة:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "ما تقرأ البيانات إنشاء" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA يقرأ البايت ، يتم فك تشفيره على أنه زوجي صغير" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "العنوان" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "القيمة" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "تستخدم ل" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "الضرب الأول" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "الطرح" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} في البداية" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "مقياس عموم المخزنة" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9040,7 +9048,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9048,12 +9056,12 @@ msgid "" "references{ph3}" msgstr "{ph0}المصدر المحفوظ{ph1} · {ph2}ملاحظات التحقيق ومراجع الأدلة{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "التحقق من الوظيفة المستردة" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9062,12 +9070,12 @@ msgstr "" "تمر الدالة المستردة بفحصين: تتطابق قيم الإرجاع الخاصة بها مع الأصل ، وتتطابق" " وحدات البايت المترجمة مع الملف القابل للتنفيذ." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3,205 حالات السلوك" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9077,12 +9085,12 @@ msgstr "" "الاختبارات تنفيذ وظيفة س 86 الأصلي ومقارنة قيمة عودتها مع الحفاظ على ج. أنها" " تغطي كل موقف صحيح من 0 إلى 640 في خمسة جداول عموم: 0 ، 0.5 ، 1 ، 20 و -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 بايت مطابقة" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9093,7 +9101,7 @@ msgstr "" "مع الوظيفة الكاملة بعد تطبيق عمليات الترحيل التي تمت مراجعتها والتحقق من " "الثوابت المشار إليها." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9108,18 +9116,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}اقرأ تفاصيل إعادة تشغيل المترجم{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "مواصلة التحقيق" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9130,7 +9138,7 @@ msgstr "" "المكافآت: فحص الوظائف ذات الصلة ، واستعادة حالتها وتبعياتها ، ثم مقارنة " "التنفيذ بالأصل." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9139,7 +9147,7 @@ msgstr "" "لفحص وظيفة الصوت عموم نفسك ، اتبع DX-Ball تعليمات إعداد المشروع وتوفير الهدف" " الأصلي المطابق. ثم تشغيل:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "في ال DX-Ball الخروج" @@ -9148,7 +9156,7 @@ msgstr "في ال DX-Ball الخروج" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9161,7 +9169,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9177,7 +9185,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9201,13 +9209,13 @@ msgstr "" "اتبع أ DX-Ball إعادة الإعمار من التحليل الثنائي من خلال REA للحفاظ على ج ، " "الأصلي-س 86 الاختبارات ومطابقة بايت وظيفة المترجمة." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ball التحقيق عموم الصوت ؛ التمرير أفقيا على شاشات أصغر" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9222,70 +9230,70 @@ msgstr "" "بشكل مستقل ضد الأصلي 86 في 3 ، 205 الحالات و فك 4.0 مترجم إعادة مطابقة 63 " "بايت." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball دراسة حالة إعادة الإعمار" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "نسخة مثال موجه" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "اتبع حساب يسار / يمين موقف الصوت" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "نسخ مقتطفات الجمعية الأصلية" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "نسخ الصوت-وظيفة عموم" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "نسخ الصوت الكامل-تجميع عموم" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "نسخ DX-Ball أمر التحليل" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}الرئيسية{ph1} / المعارض" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA دراسات الحالة." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9294,17 +9302,17 @@ msgstr "" "Android, ألعاب, Electron وتحدي فرقة العمل المشتركة ، مع رمز والأرقام " "والنتائج فحص." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "اندرويد · APK التحليل" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "كيف يقوم المصدق بإنشاء رمز تسجيل الدخول" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9314,22 +9322,22 @@ msgstr "" "البحث Aegisحساب الرمز المكون من ستة أرقام في إصداره APK. تتبع طرق التوليد " "باستخدام REA، ثم انقل ساعة تجريبية لمعرفة سبب تغيير الرمز كل 30 ثانية." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "قراءة دراسة حالة Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "* تحليل برامج كود الآلة" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "حل مدقق العلم كتف" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9340,22 +9348,22 @@ msgstr "" " الأقنعة والمبالغ إلى معادلات ، ثم تحقق من العلم الذي تم حله باستخدام " "البرنامج الأصلي." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "اقرأ دراسة حالة لجنة مكافحة الإرهاب" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "مواطن * إعادة الإعمار" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ballحساب عموم الصوت" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9366,22 +9374,22 @@ msgstr "" "الدالة المستدعية والثوابت الرقمية تؤدي إلى دالة C صغيرة ، فحص ضد السلوك " "الأصلي وجميع 63 بايت المترجمة." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "قراءة DX-Ball دراسة حالة" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * ميزة تتبع" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "كيف Notion نسخ النص و هتمل" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9392,22 +9400,22 @@ msgstr "" " أغلفة إيبك إلى حافظة النظام ، ثم انظر كيف تحافظ علامة هتمل الصغيرة على " "بيانات كتلة غنية متصلة بنسخة." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "قراءة Notion دراسة حالة" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 دوس * إعادة الإعمار" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "كيف TH04 يهدف حلقة من الرصاص" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9417,17 +9425,17 @@ msgstr "" "افحص مساعد الزاوية الأصلي 16 بت باستخدام REA. تطابق عمليات الضرب والقسمة " "والتنسيق مع ج readable المقروء ، ثم انظر كيف ينتجون حلقة تستهدف اللاعب." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "قراءة TH04 دراسة حالة" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "أدلة خطوة بخطوة" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9436,7 +9444,7 @@ msgstr "" "أدلة المشي من خلال حساب الأصلي ، وهو Electron تصدير وطلب المتصفح. كل يبدأ مع" " موجه وهدف ملموس." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "اقرأ الأدلة" @@ -9455,12 +9463,12 @@ msgstr "" "اتبع REA التحقيقات من خلال الكود والأرقام والعروض التوضيحية: مصادق أندرويد, " "DX-Ball, Notion, TH04 ومدقق العلم دوونديركتف." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -9469,25 +9477,25 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}الرئيسية{ph1} / {ph2}يعرض{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "دراسة حالة · Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "كيف Notion نسخ{ph0}النص و هتمل." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9496,12 +9504,12 @@ msgstr "" "تتبع استدعاء دالة الحافظة من Notionواجهة برمجة تطبيقات الصفحة ، من خلال " "التحميل المسبق والعملية الرئيسية ، إلى Electronكاتب الحافظة." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion سطح المكتب 7.6.1 · JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "الجسر في الداخل Notionحزمة سطح المكتب" @@ -9513,7 +9521,7 @@ msgstr "الجسر في الداخل Notionحزمة سطح المكتب" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9530,7 +9538,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9547,7 +9555,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9564,7 +9572,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9575,13 +9583,13 @@ msgstr "" " هتمل.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "قناة واحدة تنضم إلى الجانبين: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9590,14 +9598,14 @@ msgstr "" "يستخدم الرمز المعبأ نفس القناة في التحميل المسبق والعملية الرئيسية. حل مغلفة" " يكشف عن Electron يدعو وراء تلك الأسماء." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "في دراسة الحالة هذه" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9605,7 +9613,7 @@ msgstr "{ph0}اتبع جسر الحافظة{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9613,19 +9621,19 @@ msgstr "{ph0}الحفاظ على هيكل الكتلة{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}المزيد من الأمثلة والمصادر{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "أين تذهب عملية النسخ?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9644,17 +9652,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "نسخ" @@ -9665,7 +9673,7 @@ msgstr "نسخ" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9675,19 +9683,19 @@ msgstr "" "{ph0}›{ph1}{ph2}استخدام REA لتتبع كيف Notion نسخ النص و هتمل إلى حافظة " "النظام. أظهر الرمز في كل خطوة.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " "coding agent." msgstr "مثال موجه مع Notionحزمة التطبيق المحلية المتاحة لمساعدك البرمجي." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA يجد من أين تبدأ القراءة" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9698,13 +9706,13 @@ msgstr "" "والاستدعاء دالة التي ترسل طلب إيبك. تأتي كلتا النتيجتين مع نطاقات المصدر في " "الحزمة المصغرة:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA النتائج places مكانين لفتح" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9717,7 +9725,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9730,12 +9738,12 @@ msgstr "" "، ويقرأ {ph0}. لوازم موقع الاتصال {ph1}. يعطي هذا الاسم الوكيل شيئا دقيقا " "للبحث عنه في الحزمة الرئيسية. تظهر المقتطفات الأربعة أدناه المسار الذي يربط." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "أربع قطع قصيرة من التعليمات البرمجية" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9744,13 +9752,13 @@ msgstr "" "مبسطة من تعبئتها JavaScript، مع أسماء المتغيرات القابلة للقراءة. تم حذف " "الأعضاء غير المرتبطين." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "ابدأ من واجهة برمجة التطبيقات المكشوفة للصفحة" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9759,13 +9767,13 @@ msgid "" msgstr "" "يوفر هذا العضو اسم القناة. تنفيذ {ph0} يخبرنا كيف يترك الطلب عملية الصفحة." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "حل غلاف التحميل المسبق" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9776,14 +9784,14 @@ msgstr "" "واستجابة التصنيف الدولي للبراءات. يمكننا الآن البحث عن {ph0} على الجانب " "الرئيسي-العملية." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "تحقق من كيفية تسجيل المتلقي" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9793,12 +9801,12 @@ msgstr "" "تستخدم العملية الرئيسية غلاف آخر. لها {ph0} الطريقة تسجل {ph1} استقبال لتلك " "القناة." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "ابحث عن الكتابة والتحقق من المرسل" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9809,13 +9817,13 @@ msgstr "" "إلى Electronواجهة برمجة تطبيقات الحافظة. تقوم القناة والأغلفة التي تم حلها " "بتوصيل الطريقة المكشوفة بهذه الاستدعاء دالة." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "كيف تحافظ الكتلة المنسوخة على هيكلها?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9825,27 +9833,27 @@ msgstr "" "Notionمحرر الويب يرسل النص و هتمل من خلال {ph0}. فإنه يحتفظ البيانات كتلة " "محليا ويضع معرف في هتمل نسخها لربطها." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "وصلات أتش تي أم أل إلى بيانات الكتلة المحفوظة" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "قراءة معرف هتمل" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "ابحث عن نفس المعرف المحلي" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "استعادة Notion كتلة البيانات" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -9854,7 +9862,7 @@ msgstr "" "نص توضيحي ومعرف. يستعيد اختبار الوحدة النمطية المسجلة بيانات الكتلة عند " "تطابق المعرفات ؛ يقوم إدخال قديم بإرجاع النص والأتش تي أم أل فقط." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -9863,22 +9871,22 @@ msgstr "" "على لصق, Notion يبحث عن معرف هتمل ويتحقق من ذلك ضد النسخة المحفوظة. معرفات " "مطابقة استعادة البيانات كتلة." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "تم تسجيل تنسيق الحافظة من أصول الويب المخزنة مؤقتا في 13 يوليو 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "المزيد من الأمثلة والمصادر" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "مثال آخر: جداول تخفيض السعر" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -9887,12 +9895,12 @@ msgstr "" "Notion يوزع تخفيض السعر في بيانات الكتلة. يوضح هذا المثال كيف يصبح الجدول " "رأس وصفوف البيانات." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "جدول من خلال Notionمحلل تخفيض السعر" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -9900,13 +9908,13 @@ msgid "" msgstr "" "الإخراج المسجل من محلل تخفيض السعر المستخرج. يصبح الجدول الصفوف والخلايا." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "مسار آخر: اتصال سكليتي غير متصل" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9919,7 +9927,7 @@ msgstr "" "بإنشاء قناة رسالة ويعطي منفذ واحد إلى العارض والآخر إلى عملية فائدة سكليتي. " "دفعات البيان اللاحقة والنتائج تنتقل عبر هذا المنفذ." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -9928,7 +9936,7 @@ msgstr "" "بعد هذا التحول يشرح أين يعمل عمل قاعدة البيانات ، ولماذا تتبع فقط طلب إيبك " "الأولي يفتقد المحادثة في وقت لاحق." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "المصادر وكيفية قراءة المقتطفات" @@ -9936,7 +9944,7 @@ msgstr "المصادر وكيفية قراءة المقتطفات" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9954,7 +9962,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9969,7 +9977,7 @@ msgstr "" "الأصول لها نسختها الخاصة. نفذت المجسات المحفوظة وحدات مستخرجة وأحزمة صغيرة ؛" " تصف مخرجاتها تلك المجسات بدلا من جلسة واجهة مستخدم سطح المكتب الملتقطة." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -9983,7 +9991,7 @@ msgstr "" " الغلاف الخاصة بهم في الحزمة." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10001,7 +10009,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10015,7 +10023,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10041,52 +10049,52 @@ msgstr "" "مغلفة إيبك والعملية الرئيسية،مع مقتطفات رمز قصيرة ونظرة على شكل الحافظة " "الغنية." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron دراسة حالة" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "نسخ Notion موجه التحليل" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "نسخ Notion التحميل المسبق مقتطفات" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "نسخ Notion استدعاء مقتطفات المجمع" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "نسخ Notion معالج المجمع مقتطفات" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "نسخ Notion الحافظة استقبال مقتطفات" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "استعادة البيانات الحافظة الغنية على لصق" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "العودة للأعلى" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "تخطي إلى المحتوى" @@ -10095,25 +10103,25 @@ msgstr "تخطي إلى المحتوى" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}الرئيسية{ph1} / {ph2}يعرض{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "دراسة حالة * توهو 4: قصة لوتس لاند" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "إعادة البناء TH04في{ph0}أنماط رصاصة." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10122,17 +10130,17 @@ msgstr "" "تبدأ حلقة من الرصاص بحساب زاوية قصير. استخدام REA لتفقد وظيفة دوس الأصلية ، " "ثم اتبع تعليماتها في قراءة ج++." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * 16 بت دوس * ج assembly والتجمع" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "عرض TH04 إعادة الإعمار" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "من التعليمات الأصلية إلى المصدر المحدد" @@ -10143,7 +10151,7 @@ msgstr "من التعليمات الأصلية إلى المصدر المحدد" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10159,7 +10167,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10176,7 +10184,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10192,7 +10200,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10203,7 +10211,7 @@ msgstr "" "{ph0}04 * تحقق من المصدر{ph1}{ph2}2,139 بايت مطابقة{ph3}{ph4}تغطي فحوصات " "المترجم المسجلة رمز إنشاء التعداد النقطي الذي يحتوي على هذا المساعد.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10212,14 +10220,14 @@ msgstr "" "REA إرجاع الرمز الأصلي وأدلة تحليله. ال TH04 يوفر المشروع شيكات المصدر " "والمترجم التي تم صيانتها." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "في دراسة الحالة هذه" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10227,7 +10235,7 @@ msgstr "{ph0}حلقة الرصاصة{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10235,7 +10243,7 @@ msgstr "{ph0}ماذا REA المرتجعات{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10243,7 +10251,7 @@ msgstr "{ph0}الجمعية إلى ج C{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10251,18 +10259,18 @@ msgstr "{ph0}التحقق من المصدر{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}المشروع الكامل{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "كيف تهدف الحلقة إلى اللاعب" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10280,16 +10288,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مساعدك البرمجي" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "نسخ" @@ -10300,7 +10308,7 @@ msgstr "نسخ" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10310,7 +10318,7 @@ msgstr "" "{ph0}›{ph1}{ph2}استخدام REA لمعرفة كيف TH04 يخلق حلقة من الرصاص ويهدف إلى " "لاعب. شرح الحساب وإظهار التعليمات البرمجية.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10319,7 +10327,7 @@ msgstr "" "مثال موجه ، مع الخروج الأصلي القابل للتنفيذ وإعادة الإعمار متاح محليا." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10333,7 +10341,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10343,12 +10351,12 @@ msgstr "" "رسم توضيحي للرياضيات الزاوية المستردة للعد 16 واتجاه اللاعب 40 ودوران القالب" " 0. {ph0}الشكل المفتوح{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "قالب إطلاق النار في المصدر المسترد" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "هجوم حلقة اللي · مقتطفات المصدر" @@ -10357,7 +10365,7 @@ msgstr "هجوم حلقة اللي · مقتطفات المصدر" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10366,13 +10374,13 @@ msgid "" msgstr "" "تحدد هذه الخطوط النمط قبل ضبط الصعوبة والأداء. {ph0}اقرأ مصدر الهجوم{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "ماذا REA المرتجعات" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10383,12 +10391,12 @@ msgstr "" "نحن نفحص {ph0}، الوظيفة التي تحدد سرعة وزاوية كل رصاصة. REA إرجاع تعليماته ،" " بسيودوكود والمراجع. ثلاثة أجزاء من هذه النتيجة تشرح النمط." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "تحقق من صورة دوس قبل قراءة رمزها" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10397,7 +10405,7 @@ msgstr "" "يربط الشيك الكود المحمل وسجلات النقل إلى الملف القابل للتنفيذ المرفق. يتم " "تقصير المسار أعلاه للعرض." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "قراءة الحلبة ضرب وتقسيم" @@ -10405,7 +10413,7 @@ msgstr "قراءة الحلبة ضرب وتقسيم" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10417,12 +10425,12 @@ msgstr "" "من {ph1}. أسماء المصدر المحتفظ بها هذا الحقل {ph2}. يظهر التسلسل الكامل " "أدناه." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "ابحث عن المكان الذي يتحول فيه النمط نحو المشغل" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10434,12 +10442,12 @@ msgstr "" "الإرجاع إلى زاوية الحلقة النسبية. أسماء المصدر تجعل هذه العناوين قابلة " "للقراءة; REA يتيح للوكيل التحقق من العمليات الأصلية خلفهم." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "من التجميع إلى القراءة ج C" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10452,7 +10460,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10460,7 +10468,7 @@ msgstr "{ph0}01{ph1} الفهرس" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10468,7 +10476,7 @@ msgstr "{ph0}02{ph1} الفضاء" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10476,7 +10484,7 @@ msgstr "{ph0}03{ph1} الهدف" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10484,18 +10492,18 @@ msgstr "{ph0}04{ph1} تدوير" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} متجر" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * تعليمات 16 بت الأصلية" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "قراءة ج · * تهدف حلقة ملخص" @@ -10503,7 +10511,7 @@ msgstr "قراءة ج · * تهدف حلقة ملخص" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10517,7 +10525,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10532,7 +10540,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10546,7 +10554,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10560,7 +10568,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10573,7 +10581,7 @@ msgstr "" " حقل تفرخ الزاوية. القيم التفاف بعد 255 ، تماما كما يفعل يلقي بايت غير " "موقعة. يحول المصدر المحيط أيضا هذه الزاوية والسرعة إلى سرعة." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10584,7 +10592,7 @@ msgstr "" "أعلاه هو ملخص مقروء. تنطبق عمليات التحقق من المترجم أدناه على المصدر المحفوظ" " في المشروع المرتبط." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "قراءة حلقة الحفاظ ومصدر الهدف" @@ -10601,7 +10609,7 @@ msgstr "قراءة حلقة الحفاظ ومصدر الهدف" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10611,12 +10619,12 @@ msgstr "" "{ph0}حلقة ماكرو{ph1} · {ph2}الهدف ومصدر السرعة{ph3} · {ph4}تمثيل " "الزاوية{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "التحقق من المصدر الذي تم صيانته" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10625,12 +10633,12 @@ msgstr "" "ال TH04 تقوم الشيكات المسجلة للمشروع بتجميع رمز إنشاء الرصاص ، بما في ذلك " "هذا المساعد ، مع سلسلة أدوات توربو سي J 4.0 ي." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 بايت مطابقة" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10639,12 +10647,12 @@ msgstr "" "يتطابق رمز إنشاء التعداد النقطي المجمع مع قسم 2139 بايت من الملف التنفيذي " "الأصلي." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "اثنين نظيفة يبني" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10657,65 +10665,65 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "تم تسجيله في 3 أكتوبر 2026. {ph0}قراءة الشيكات مترجم{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "تحديد الهدف ونطاق التحليل" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "الهدف الأصلي" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156 ، 258 بايت ، دوس ميجا هرتز" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "دخول المساعد" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} في REAالصورة المحملة" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "إزاحة الملف الأصلي" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}، عاد من قبل {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "فحص الكود المسجل" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 أكتوبر 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10725,7 +10733,7 @@ msgstr "" "أنها تقارن مساهمة الخريطة وإعادة التوطين المتداخلة." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10739,7 +10747,7 @@ msgstr "" "بايت ؛ التعليمات المحددة أعلاه تكمن في تلك النطاقات المبلغ عنها." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10754,7 +10762,7 @@ msgstr "" "REA التفتيش على نفس الهدف الأصلي. يتم تثبيت هوية اللعبة الموردة من خلال بيان" " المستودع الخاص بها ، مع استمرار فتح مصدر التفريغ الأصلي المستقل." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10764,12 +10772,12 @@ msgstr "" "يوضح الشكل حساب الزاوية. ضوابط اللعبة الكاملة والتوقيت و PC-98 سلوك الأجهزة " "لديها الشيكات وقت التشغيل منفصلة في مشروع إعادة الإعمار." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "كامل TH04 إعادة الإعمار" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10782,7 +10790,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10794,7 +10802,7 @@ msgstr "{ph0}استكشاف TH04 مستودع{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10810,7 +10818,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10826,7 +10834,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10851,28 +10859,28 @@ msgstr "" "فحص TH04رمز دوس الأصلي 16 بت مع REA. اتبع التجمع وتعافى ج to لنرى كيف " "متباعدة حلقة من الرصاص وتهدف إلى لاعب." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "في هذه الصفحة" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 دراسة حالة نمط رصاصة" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "نسخ TH04 مثال موجه" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "TH04 حلقات رصاصة ثابتة وموجهة ؛ التمرير أفقيا على شاشات أصغر" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10884,27 +10892,27 @@ msgstr "" "إضافة اتجاه لاعب 40 تدور كل اتجاه بنفس المقدار; النقاط الأولى المميزة تجاه " "اللاعب. كلاهما يحتفظ بمسافة 16 وحدة زاوية ، أو 22.5 درجة." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "نسخ TH04 قالب إطلاق النار" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "اتبع TH04 تهدف-حساب الدائري" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "نسخ TH04 مقتطفات الجمعية" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "نسخ حساب الحلقة المستهدفة المقروءة" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "العودة للأعلى" @@ -11013,7 +11021,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "سرعة ثابتة: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11022,7 +11030,7 @@ msgstr "" "ردت القاعدة المستردة. تتطابق جميع القيم الأربع مع فحص اللعبة الأصلية المتحكم" " فيه عند تقريبه إلى ثلاثة كسور عشرية." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11383,591 +11391,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "نفس التباعد: 256 1 16 = 16 وحدة زاوية = 22.5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "أمثلة عملية" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "المدونة" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "ابدأ هنا" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "الأدلة" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "الكود المصدري" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "رخصة MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "انضم إلى المجتمع" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "تابعنا على X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * مصدر البرنامج النصي المحدد" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "الكود المصدري" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "الناتج المنسق المتوقع" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "التعليمات" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "الدالة المستدعية" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "الثوابت" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "جيم وظيفة" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "زر" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "واجهة برمجة تطبيقات التحميل المسبق" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "التصنيف الدولي للبراءات" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV ملف" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "انقر فوق الخاص بك" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "طلب تم التقاطه" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "نص التصدير" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA النتيجة * ملخص.مقتطفات التصنيف الدولي للبراءات" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA مقتطفات التعليمات * 0 * 406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA مقتطف الدالة المستدعية · 0 * 411 أف 5 ب" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA نتائج البايت * تفسر على أنها زوجي صغير" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "تعافى ج * مقتطفات" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "شاهد كيف يعمل REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "يعرض →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "الإعدادات المحددة من البرنامج النصي الذي تم فحصه" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "ملخص مقروء لمعالج ٪" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * تعليمات أصلية مختارة" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "معرفات المشغل * مصدر مايكروسوفت" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "اتبع @رياتولس على س" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "وكيل → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA - وكيل * نتائج مختارة" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA - وكيل * طرق والدوال المستدعية" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * جافا مفككة مختارة" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "ملخص مقروء * تفسير الوكيل" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * جينيراتوتب ، كامل الجسم" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "تحميل Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "تحميل مزود تحليل Android" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "وكيل → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA - وكيل * نتائج مختارة" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA - وكيل * تعليمات مختارة" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "وكيل → REA * قراءة _ بايت" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA agent الوكيل * الإدخالات السابعة" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "قابل للتنفيذ الأصلي · SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "تحميل التحدي الأصلي" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "تحميل حلالا" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA النتيجة * مقتطفات من الكود الكاذب" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "وكيل → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA - وكيل * مقتطفات التعليمات" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA - وكيل * الدالة المستدعية مقتطفات" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "وكيل → REA * اثنان {ph0} الطلبات" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA نتائج بايت * فك كما الزوجي" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "ابدأ بالهدف الخاص بك" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "توليد التعليمات البرمجية" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "القاعدة المستردة" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "ساعة قابلة للتعديل" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "ثنائي" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "التحقق من التعليمات البرمجية" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "المعادلات" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "صحيح!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "قابل للتنفيذ" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA النتائج" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "تعافى ج" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "التحقق من الصحة" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "التطبيق المعبأ" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "واجهة برمجة تطبيقات مكشوفة" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "مغلفة التصنيف الدولي للبراءات" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "الحافظة" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "كود دوس الأصلي" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA التعليمات" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "حساب الزاوية" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "حلقة رصاصة" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "واجهة برمجة تطبيقات الصفحة المكشوفة" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "دعوة العارض إيبك" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "إرسالها إلى حافظة النظام" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "محفوظ محليا بواسطة Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "إدخال تخفيض السعر" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "منظم محلل الإخراج * مقتطفات" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "تحليل التطبيق الخاص بك" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "وكيل → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA agent وكيل * الحقول المحددة" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "وكيل → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA - وكيل * مقتطفات التعليمات" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "نفس النتيجة وظيفة * تهدف مقتطفات" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "المقابلة الحفاظ ج C" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "حلقة ماكرو · TH04 فرع ، مقتطفات" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "الزاوية والسرعة * مقتطفات المصدر" @@ -12000,7 +12016,7 @@ msgstr "يتم تحديث الترجمة. اقرأ هذه الصفحة بالل #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12017,7 +12033,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12037,7 +12053,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12057,7 +12073,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12075,7 +12091,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12093,7 +12109,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12104,7 +12120,7 @@ msgstr "" "لي.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" @@ -12112,7 +12128,7 @@ msgstr "إعادة الإعمار · {ph0}" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12123,7 +12139,7 @@ msgstr "" "المقترحة." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12132,7 +12148,7 @@ msgstr "مثال مقدم · {ph0} و npm * مساعدك البرمجي" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12150,7 +12166,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12166,7 +12182,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12185,7 +12201,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12196,7 +12212,7 @@ msgstr "" "الملف.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12211,7 +12227,7 @@ msgstr "{ph0} * خطوط 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12224,7 +12240,7 @@ msgstr "" "الفعلي.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12235,7 +12251,7 @@ msgstr "" "المنسق مباشرة مع {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12243,7 +12259,7 @@ msgstr "{ph0} · CSV المنسق" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12251,7 +12267,7 @@ msgid "" msgstr "سوف تحتاج {ph0} 22 (22.19+), 24 (24.11+) أو 26+. npm يأتي مع {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12259,7 +12275,7 @@ msgstr "ليس لديك {ph0}, أو لست متأكدا?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12272,7 +12288,7 @@ msgstr "" "فقم بالتثبيت {ph1} 24 لتر:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12286,7 +12302,7 @@ msgstr "{ph0} * مثال مقتطفات المصدر" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12295,9 +12311,9 @@ msgid "" msgstr "{ph0}افتح المثال{ph1} · {ph2}تحميل {ph3}{ph4} · {ph5}تحميل {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12305,7 +12321,7 @@ msgstr "{ph0} * مثال المصدر" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12319,7 +12335,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12332,7 +12348,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12345,7 +12361,7 @@ msgstr "مثلاً: {ph0}لماذا تعطي الآلة الحاسبة 220 عن #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12356,7 +12372,7 @@ msgstr "" "220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12365,7 +12381,7 @@ msgstr "REA * تحميل {ph0} * خطوط مختارة" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12383,7 +12399,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12401,7 +12417,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12414,28 +12430,28 @@ msgstr "" "تغيير الوقت.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "علامة التبويب_المتصفح_عرض/{ph0} * عضو واجهة برمجة التطبيقات" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "علامة التبويب_المتصفح_عرض/{ph0} * إيبك مساعد" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "الرئيسية/{ph0} * معالج مساعد" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12445,12 +12461,1351 @@ msgstr "الرئيسية/{ph0} * استقبال الحافظة" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "ابدأ هنا {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "التبديل إلى الوضع الفاتح" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "التبديل إلى الوضع الداكن" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"لفحص أجسام طلبات HTTP واستجاباتها، استخدم {ph0}Fiddler Everywhere: تسجيلات " +"SAZ وMCP والمهارات العامة{ph1}. صدّر بتنسيق SAZ ?? HAR 1.2 للحصول على أدلة " +"تسجيل في REA دون اتصال، أو اربط خادم MCP في Everywhere لفحص حركة المرور " +"المسجلة مع وكيلك." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "نماذج متخصصة{ph0}مقال" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "هل تحتاج الهندسة العكسية إلى نموذج أكبر؟" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"أفكار من إعادة بناء Touhou حول النماذج العامة والمتخصصة والتعلم من نتائج " +"المُصرّف." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "بواسطة N0zoM1z0 · 13 أكتوبر 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "تخطي إلى المحتوى" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" +"{ph0}الصفحة الرئيسية{ph1} / {ph2}المدونة{ph3} / النماذج والهندسة العكسية" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "مقال" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "هل تحتاج الهندسة العكسية إلى نموذج أكبر؟" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "بواسطة N0zoM1z0 · 13 أكتوبر 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "أهم الأفكار" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}تؤثر قدرة النموذج على الفرضيات التي يمكن أن يقترحها وكيل الذكاء " +"الاصطناعي.{ph1} قامت الجلسات اللاحقة بحل المشكلات التي تركها العمل السابق " +"دون حل." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}يقدم المترجم المألوف أنماطًا محددة لنموذج متخصص للتعلم.{ph1} تعتمد بعض " +"المطابقات الدقيقة لرمز الآلة على أنماط محددة من كود المصدر قابلة لإعادة " +"الاستخدام." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}قم بتضمين معرفة المستودع في مقارنة عادلة.{ph1} قد يحتوي النموذج الأصغر " +"الذي يتمتع باسترجاع جيد للمعرفة على معلومات كافية لإحراز تقدم." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}قم بتدريب النموذج على اختيار التجربة المفيدة التالية، واختبار أداة " +"التحقق الخاص به.{ph1} تكون التعليقات مفيدة فقط إلى الحد الذي يتحقق فيه " +"المدقق من الأشياء الصحيحة." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}قم بتقييم نتائج إعادة بناء الشيفرة التي تم التحقق منها جنبًا إلى جنب مع" +" الوقت والتكلفة.{ph1} هذا ما أريد قياسه لسير عمل وكيل الذكاء الاصطناعي " +"الكامل." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "في هذه المقالة" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}ما الذي غيّرته النماذج الأقوى؟{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}لماذا التخصص؟{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}أين ينبغي تخزين هذه التجربة؟{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}تعلم التجربة المفيدة التالية{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}الهندسة العكسية والتعلم المعزز{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}عندما يكون أداة التحقق خاطئًا{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}مقارنة تستحق التشغيل{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}ما هو نوع وكيل الذكاء الاصطناعي الذي يشير إليه هذا؟{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "ما الذي غيّرته النماذج الأقوى؟" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"منذ أغسطس 2026، كنت أستكشف مقدار الهندسة العكسية التي يمكن للوكيل تنفيذها من" +" خلال الوصول إلى البرنامج وطريقة التحقق من عمله. معظم خبرتي تأتي من إعادة " +"بناء الألعاب، وخاصة Touhou. وبما أنني قمت بتغيير النماذج، فقد احتفظت " +"المستودعات بسجل لما تمكنت كل جلسة من استعادته." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"يهدف كثير من هذا العمل إلى إعادة بناء دقيقة: نترجم الشيفرة المصدرية التي " +"نحتفظ بها باستخدام أدوات من تلك الحقبة بإصدارات ثابتة، ثم نتحقق من أنها تعيد" +" إنتاج الدالة المستهدفة. عندما يحل نموذج أحدث مشكلة تعثر عندها العمل السابق،" +" تكشف تغييرات الشيفرة ما الذي أتاح هذا التقدم." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "تحتاج المتغيرات المؤقتة إلى عمر متداخل" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"تمت إعادة بناء الكثير من منطق دالة الهجوم TH09 بالفعل، لكن المترجم ما زال " +"يخزن النتائج المؤقتة بشكل مختلف عن الأصل. وكانت المشكلة المتبقية هي المدة " +"التي تحتاجها تلك النتائج للبقاء على قيد الحياة، ومتى يمكن إعادة استخدام " +"مخزونها." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"أبلغ {ph0}GPT-6-Sol سجل الجلسة{ph1} عن عدم التطابق هذا بعد اختبار العديد من " +"ترتيبات كود المصدر العادية. عندما فحص {ph2}GPT-6.1-Sol المشكلة مرة " +"أخرى{ph3}، اقترح فرضية مفيدة حول عمر هذه المتغيرات المؤقتة." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"أنتجت الوظيفة نتائج مؤقتة ونسختها في مواضع الرسوم المتحركة. في لغة C++، تظل " +"النتيجة المؤقتة حية حتى انتهاء التعبير الذي يستخدمها. يؤدي تجميع العمليات " +"الحقيقية في تعبير واحد إلى إبقاء هذه النتائج حية معًا، لذلك لم يعد بإمكان " +"المترجم إعادة استخدام نفس وحدة التخزين لجميعها." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"لا تزال إحدى النتائج مشتركة في مساحة التخزين مع القيمة المستخدمة لاحقًا " +"للتحقق من التضارب. إن إعطاء هذه القيمة مدى الحياة الخاص بها أدى إلى حل " +"التداخل المتبقي. وبعد عدة تجارب مستهدفة، {ph0}أكدت إعادة الترجمة النظيفة من " +"المصدر أن الوظيفة الكاملة مطابقة{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"أنا مهتم بكيفية دعم الاكتشاف والاختبارات لبعضهما البعض. أعطت الفرضية " +"المتعلقة بعمر الكائنات المؤقتة لعامل الذكاء الاصطناعي اتجاهًا جديدًا. ساعدت " +"تعليقات المترجم في تحسين هذه الفرضية إلى ترتيب كود المصدر المطابق." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "رسم بياني مختلف للتحكم في التدفق" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"توضح وظيفة TH09 الثانية سبب أهمية هذا الاتجاه الجديد. وهنا، كانت العقبة هي " +"كيفية مشاركة العديد من الفروع لعملها النهائي. يحتوي العمل السابق لـ " +"{ph0}GPT-6.1-Sol{ph1} على أجزاء من الدالة متطابقة، ولكن لا تزال الفروع متصلة" +" بشكل مختلف عن الأصل." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}غيّر GPT-6-Astra الرسم البياني المحيط لتدفق التحكم{ph1}. أصبحت المسارات" +" الرئيسية تؤدي إلى تحديث أخير وعودة مشتركين. بهذه البنية، دمج المترجم " +"البرمجي الفروع كما في الأصل. تطابقت الدالة كاملة، وأكد ذلك {ph2}فحص مستقل " +"لإعادة البناء{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}أدى تغيير التمثيل إلى فتح مساحة بحث أكثر إنتاجية.{ph1} تمنحني كلتا " +"الحالتين سببًا لأخذ إمكانات النموذج العامة على محمل الجد: يمكن للوكيل " +"الاستمرار في تجربة الاختلافات المحلية لفترة طويلة قبل العثور على طريقة أفضل " +"للتعبير عن العمل المحيط." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"في الوقت نفسه، بدأت الجلسات اللاحقة بمصادر سابقة وإخفاقات مسجلة. وكان هذا " +"العمل المتراكم جزءًا من مصلحتهم. يتيح لنا التاريخ فحص الاكتشافات وفحصها؛ ومن" +" شأن المقارنة الخاضعة للرقابة أن تساعد في فصل تأثير النموذج عن الخبرة التي " +"ورثها." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"وهذا ما يجعل السؤال مثيرًا للاهتمام بالنسبة لي. جاء بعض التقدم من إيجاد " +"تمثيل جديد. تضمن الكثير من العمل المتبقي اختبار ترتيبات مختلفة لشفرة المصدر " +"مقابل مترجم مألوف. كم من هذا يتطلب قدرة تفكير واسعة النطاق؟ ما مقدار ما يمكن" +" أن يتعلمه النموذج من خلال العمل المتكرر مع هذا المترجم والكود؟" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "لماذا قد يكون نموذج الذكاء الاصطناعي المتخصص ناجحًا؟" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou يعطينا سببًا ملموسًا لتوقع أن تساعدنا هذه التجربة. الكثير من رموز " +"اللعبة تأتي من نفس المؤلف، ZUN، لذا فإن العادات المتكررة هي افتراض بداية " +"معقول. تدعم المستودعات ذلك بأمثلة مفيدة: الحلقات ذات الصلة والترتيبات " +"المساعدة قدمت فرضيات عبر الألعاب." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"تصبح أنماط المصدر هذه أكثر تحديدًا عندما نقوم بتضمين المترجم. ضمن إصدار معين" +" ومجموعة من الخيارات، يمكن أن تؤدي التغييرات الصغيرة في المصدر إلى اختلافات " +"متكررة في كود الجهاز. بعض هذه الاختلافات غامضة بشكل مدهش." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"في TH095، على سبيل المثال، {ph0}حتى اسم المتغير المحلي يمكن أن يؤثر على مكان" +" تخزينه VC7.1{ph1}. لم يؤدي نقل إعلانه إلى حل تخطيط التخزين. ومع ذلك، كشفت " +"وظيفة خلفية سابقة عن نمط تسمية أثر على اختيار المترجم. وقد اقترح ذلك فرضية " +"واعدة أكثر بشأن {ph2}إعادة بناء {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"أدت إعادة استخدام هذا النمط لمتغير حجم الملف إلى إنتاج التخطيط المطلوب دون " +"إضافة مساحة تخزين. ثم تمت مطابقة الوظيفة الكاملة." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"هذه تفاصيل محددة جدًا قد لا يعرفها نموذج الذكاء الاصطناعي للأغراض العامة " +"عندما يواجه المشكلة لأول مرة. يمكن للنموذج المتخصص لهذا المترجم أن يرى " +"العديد من هذه الحالات ويتعرف على اختلافات التعليمات البرمجية المصدر التي " +"تستحق الاختبار أولاً." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"تكون الفرصة واضحة بشكل خاص في مشاكل المطابقة النهائية حيث نفهم السلوك " +"بالفعل. ثم نسأل عن ترتيب التعليمات البرمجية المصدر العادي الذي يحوله هذا " +"المترجم إلى التعليمات المرصودة. يمكن أن يساعد التخصص النموذج على اقتراح تلك " +"الأشكال بشكل أكثر كفاءة، في حين أن الهدف لا يزال يحدد الفرضيات التي ستبقى." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"يجب أن تحتفظ الأنماط بسياقها. يستخدم TH08 إصدارًا من Visual C++ أقدم مما " +"يستخدمه TH095 وTH09. أما TH04 فيستخدم مُترجمًا برمجيًا آخر من حقبة DOS، وقد " +"احتاجت {ph0}إعادة بناء شيفرة اللاعب{ph1} إلى فرضيات مختلفة عن أنماط الشيفرة " +"وكيفية ربطها في ملف تنفيذي. وحدة المؤلف تعطينا توقعًا أوليًا، لكن كل هدف " +"يبين إن كان ينطبق. وعلى النموذج المتخصص تعلم هذه الفروق." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "أين ينبغي تخزين هذه التجربة؟" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"قبل أن أقرر تعليم هذه الأنماط للنموذج، سأراجع المعرفة التي نحفظها بالفعل في " +"المستودع. في {ph0}المقال السابق{ph1} كتبت عن المستودع وهو يصبح الذاكرة " +"العاملة للمشروع. تتضمن هذه الذاكرة ما تعلمناه عن سلوك المترجم البرمجي، مع " +"الشيفرة والتجارب الفاشلة التي جعلت تلك المعرفة مفيدة." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"من خلال استرداد هذا السجل، يمكن للوكيل البدء بنتيجة معروفة وفحص كيفية وصولنا" +" إليها. ويمكنه أيضًا تجنب البدائل التي فشلت بالفعل في نفس السياق. تتحسن نقطة" +" البداية دون تغيير معلمات النموذج المدربة." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"أثناء إعادة بناء وظيفة TH09 لإنشاء الأعداء، أخذت جلسة {ph0}GPT-6-Luna-" +"max{ph1} فرضية من كود مصدر TH08 ذي الصلة. اقترح هذا الكود السابق كيفية تنظيم" +" الحلقة والتعامل مع حالات الفشل بداخلها. قدمت أدلة TH09 الخاصة التفاصيل " +"الخاصة باللعبة. أكدت عمليات إعادة البناء من المصدر أن الوظيفة الكاملة " +"متطابقة." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"النموذج لم يكن يعرف هذه الخاصية المحددة للمترجم البرمجي\" و\"النموذج " +"لم يستطع استخدامها\" مشكلتان مختلفتان.{ph1} قد يحل استرجاع المعرفة المشكلة " +"الأولى، لكن تحويلها إلى شيفرة مرشحة مفيدة يحتاج إلى عمل. وإذا فشلت الشيفرة " +"المرشحة، فعلى النموذج أن يقرر ما تعنيه النتيجة لمحاولته التالية. معرفة النمط" +" المناسب هي بداية العملية فقط." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"لهذا السبب، سأقوم بتضمين نموذج ذكاء اصطناعي أصغر حجمًا للأغراض العامة مع " +"استرجاع جيد في أي مقارنة. إن منحها نفس مكتبة الخبرة من شأنه أن يساعدنا في " +"تحديد ما يضيفه التدريب: جيل أفضل للمرشحين، أو قرارات أفضل بعد التعليقات، أو " +"كليهما." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "تعلم التجربة المفيدة التالية" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"تلك القرارات بعد ردود الفعل هي أكثر ما أرغب في دراسته. في إعادة البناء " +"الوكيل، يقترح النموذج تفسيرًا ويختبره مقابل البرنامج. وحتى عندما يفشل الكود " +"المصدري المرشح، فإن النتيجة يمكن أن تضيق الاحتمالات المتبقية وتقترح تجربة " +"تالية أكثر فائدة." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"خذ بعين الاعتبار مثال النتائج المؤقتة مرة أخرى. يُظهر مصدره النهائي الترتيب " +"الذي نجح، لكن المسار إلى هذا المصدر يحتوي على مزيد من المعلومات. ساعدت كل " +"تجربة من التجارب التالية في تحديد ما لا يزال بحاجة إلى التغيير." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "تجربة" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "ماذا علمتنا نتيجته" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "جرب طريقة مختلفة لنسخ النتائج" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "يتغير رمز النسخ، لكن الوظيفة لا تزال مختلفة." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "استخدم القيم التي تم إرجاعها مباشرة" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "يتبع النسخ النمط الأصلي، لكن التخزين المؤقت لا يزال مختلفًا." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "إبقاء كافة المتغيرات المؤقتة صالحة في نفس الوقت" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"يحصلون على مساحة تخزين منفصلة، ولكن لا يزال هناك تداخل مع قيمة يتم استخدامها" +" لاحقًا للتحقق من التصادم." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "احتفظ بقيمة التحقق من التصادم منفصلة" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "تؤكد إعادة الترجمة النظيفة من المصدر التطابق الكامل." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"تجارب مختارة من إعادة بناء وظيفة الهجوم أعلاه، مجمعة حسب ما علمتنا إياه." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"يمكن لسجل التدريب الذي يحتفظ بهذا التسلسل أن يعلم أكثر من المصدر النهائي " +"وحده. فهو يربط كل تغيير مقترح بالنتيجة الملحوظة والقرار التالي. إن الاحتفاظ " +"بالتغيرات غير الفعالة أمر مهم أيضًا: فهي تخبر وكيلًا لاحقًا بالفرضيات التي " +"تم اختبارها بالفعل في هذا السياق." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}أريد أن يتعلم النموذج كيفية استخدام التعليقات.{ph1} النتيجة المحايدة هي" +" سبب لإعادة النظر في الشكل؛ قد يشير عدم التطابق المتغير إلى سبب آخر. عندما " +"تتوقف التعديلات المحلية عن تقديم المعلومات، يجب أن يكون الوكيل قادرًا على " +"إعادة النظر في تمثيل المصدر أو فحص الأدلة مرة أخرى." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"تعلم هذه الاختيارات يتطلب الاستقلالية. أحيانًا تكون الخطوة الأنسب فحص دالة " +"أخرى تستدعي هذه الدالة بدل ترجمة تعديل جديد. فرض سلسلة جامدة من إعادة " +"الكتابة يلغي هذا الاختيار ومعه جزءًا من السلوك الذي نريد أن يتعلمه النموذج." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "لماذا تعتبر الهندسة العكسية مثيرة للاهتمام للتعلم المعزز" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"توفر إعادة البناء ذات النطاق المحدد بيئة عملية لدراسة هذه القرارات. بعد " +"تثبيت إصدارات الهدف والمترجم البرمجي، تعطي تجارب كثيرة على الشيفرة ملاحظات " +"سريعة وقابلة للتكرار. يستطيع الوكيل ترجمة شيفرة مرشحة وفحص الفروق ثم اختيار " +"الخطوة التالية." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"يمكن للتعلم المعزز تدريب عملية صنع القرار من خلال ردود الفعل التي تتلقاها. " +"يمنحنا المرشح الذي يتم قبوله عن طريق فحص محدد نتيجة ملموسة، في حين يتيح لنا " +"تسلسل المحاولات ملاحظة مقدار العمل الذي استغرقه الوصول إلى هذه النتيجة." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"هناك أبحاث تدعم هذا الاتجاه بالفعل. يدرس {ph0}LLM4Decompile{ph1} نماذج " +"متخصصة في استعادة الشيفرة المصدرية من البرامج المترجمة. ويستخدم " +"{ph2}AutoDecompiler{ph3} نتائج الترجمة والتنفيذ لتدريب التحسين عبر جولات " +"متعددة. تركز هذه الدراسات على استعادة سلوك البرنامج. سأستخدمها نقطة بداية " +"لمهمة قريبة: إيجاد شيفرة تنتج مخرجات مطابقة لمترجم برمجي تاريخي." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"للوصول إلى مثل هذه المهمة المحددة جيدًا، قد نحتاج أولاً إلى تحديد الموارد " +"التي تمتلكها الوظيفة أو ابتكار طريقة جديدة لملاحظة سلوك البرنامج أثناء " +"تشغيله. في TH08، على سبيل المثال، {ph0}أدى اختلاف التصادم إلى كيفية تعامل " +"البرنامج الأصلي مع حسابات الفاصلة العائمة{ph1}. قبل أن يتمكن الوكيل من " +"اختبار تصحيح مفيد، كان عليه أن يحدد ما يجب قياسه." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"ويشير هذا إلى دور آخر لنموذج قادر على نطاق واسع: المساعدة في جعل المشكلة " +"قابلة للتحقق في المقام الأول. بمجرد وجود هذا الفحص، يمكننا التحقيق في المدى " +"الذي يمكن أن تصل إليه سياسة البحث المستفادة." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "عندما يكون أداة التحقق خاطئًا" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"عندما نستخدم فحصًا في التدريب، يصبح نطاقه جزءًا من بيئة التعلم. أسمي هذا " +"المرجع أو أداة التحقق oracle. حتى الإجابة القابلة للتكرار يجب فهمها في حدود " +"ما تتحقق منه فعلًا." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"أظهر TH08 مقدار ما يمكن إخفاءه خارج تلك التغطية. اجتازت بعض الوظائف المعاد " +"بناؤها مقارناتها الدقيقة مع ثوابت عائمة خاطئة. قامت أداة المقارنة بتعديل " +"العناوين المنقولة قبل التحقق من التعليمات، ولكنها لم تتحقق من القيم الموجودة" +" خلف تلك العناوين إلا عندما تم تسجيلها بشكل صريح للتحقق منها. يمكن أن تمر " +"المراجع الحرفية الأخرى دون فحص قيمها." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"لسد هذه الفجوة، كشف {ph0}تدقيق أوسع{ph1} ثوابت خاطئة في دوال كانت قد اجتازت " +"التحقق. في إحدى العمليات الحسابية، أضافت الشيفرة المعاد بناؤها {ph2}، بينما " +"أضاف الأصل {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}يمكن للنموذج الذي تمت مكافأته بفحص التحقق القديم أن يتعلم إنتاج إعادة " +"بناء غير صحيحة.{ph1} لم نقوم بتدريب نموذج RL باستخدام هذا المدقق. الفشل الذي" +" لاحظناه كان في الفحص نفسه. ولكن إذا استخدمناها كمكافأة، فإن نفس النقطة " +"العمياء ستصبح جزءًا من بيئة التعلم." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"يمكن أن يحتوي الاختبار الوظيفي على نقطة عمياء مماثلة. {ph0}وجدت الأبحاث التي" +" تستخدم التشويش التفاضلي في برامج فك التشفير LLM{ph1} وجود اختلافات سلوكية " +"خارج الاختبارات المتوفرة. لذلك نحن بحاجة إلى فهم اختبار النجاح من حيث " +"الحالات التي يمارسها. وبالمثل، يجب فهم مطابقة التعليمات من حيث البايتات " +"والبيانات التي تتحقق منها." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"قبل استخدام أي نوع من اختبارات التحقق كمكافأة، سأختبره بنتائج غير صحيحة " +"عمدًا. أود أيضًا أن أبقي القبول النهائي منفصلاً عن كود المصدر الذي يمكن " +"لعامل الذكاء الاصطناعي تحريره. يجب أن يجتاز النموذج التحقق من خلال إعادة " +"بناء البرنامج بشكل صحيح. وبخلاف ذلك، فإن مجرد نسخ مصفوفة بايت من الهدف يمكن " +"أن يخدع نظام تسجيل ساذج دون استعادة كود المصدر المفيد." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}إن تحسين المتعلم وتحسين أداة التحقق من الصحة ينتميان إلى نفس مشكلة " +"البحث.{ph1} ومع تحسن المتعلم في تحسين التعليقات التي نقدمها له، يصبح فهم هذه" +" التعليقات أكثر أهمية أيضًا." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "مقارنة تستحق التشغيل" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"مع إجراء عمليات التحقق هذه، سأبدأ المقارنة على مجموعة مهام VC7.1 ثابتة. " +"أولاً، أود أن أضع خطوط أساس لنموذج قوي للذكاء الاصطناعي للأغراض العامة " +"ونموذج أصغر. إن إضافة معرفة المستودع إلى النموذج الأصغر سيُظهر تغييرات " +"الاسترجاع. ومن هنا، فإن التخصص الخاضع للإشراف والنسخة المدربة RL ستسمح لنا " +"بفحص ما يضيفه التدريب." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"ولجعل هذه المقارنات مفيدة، سيحصل كل نموذج على نفس الأدلة والأدوات المستهدفة." +" بالنسبة للمقارنات الخاصة بالتدريب، سأبقي النموذج الأساسي والمعرفة المتاحة " +"ثابتة أيضًا. من شأن التجارب المتكررة أن تساعد في التمييز بين استراتيجية " +"البحث الموثوقة والحل المرشح الذي ينجح بالصدفة." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"سأفصل بعد ذلك شرطين للبدء: إعادة بناء دالة من تعليماتها، وإغلاق الاختلافات " +"القليلة الأخيرة في المصدر المحفوظ. قد يكون نموذج الذكاء الاصطناعي المتخصص " +"ممتازًا في المهمة الثانية، بينما يقوم نموذج الذكاء الاصطناعي للأغراض العامة " +"بالكثير من العمل اللازم للوصول إليه. وقياسها بشكل منفصل من شأنه أن يكشف عن " +"تقسيم العمل هذا." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"تحتاج كلتا المهمتين إلى أمثلة اختبارية مستثناة من التدريب والاسترجاع. ألعاب " +"Touhou ذات الصلة تشترك في رمز المحرك. قد يؤدي استبعاد لعبة واحدة من التدريب " +"إلى ترك وظائف متطابقة تقريبًا في مجموعة التدريب. بدلاً من ذلك، سأستبعد " +"مجموعات كاملة من أكواد المصدر ذات الصلة وأحتفظ بإجاباتها التي تم التحقق منها" +" خارج كل من بيانات التدريب ومكتبة الاسترجاع." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"بالنسبة لهذه الأمثلة، ستكون النتيجة تطابقات كاملة تم التحقق منها بشكل مستقل." +" من شأن الميزانيات المتساوية لمقترحات المرشحين أو محاولات التجميع أن تساعد " +"في مقارنة جودة البحث. إن قياس إجمالي الوقت والتكلفة، بما في ذلك التجميع، " +"سيُظهر ما إذا كانت هذه الجودة تنتج سير عمل فعالاً. وينبغي قياس تكاليف " +"التدريب بشكل منفصل." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"كلا القياسين مهمان. يمكن أن يؤدي الاقتراح الرخيص إلى سير عمل مكلف إذا تسبب " +"في المزيد من التجميعات التي لا تقدم معلومات مفيدة. وعلى العكس من ذلك، قد " +"يكون النموذج الأبطأ أكثر اقتصادا إذا وجد تجربة مفيدة في وقت أقرب. وينبغي أن " +"تشمل المقارنة هذه التكاليف." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"كما أن حساب النتائج المقبولة يحافظ على التقدم المتوسط في المنظور الصحيح. بدا" +" أحد مرشحات TH09 {ph0}replay-save{ph1} واعدًا لأن الدالة المترجمة لها الحجم " +"المتوقع، ولكن المقارنة الكاملة لا تزال تجد اختلافات جوهرية. إن التغييرات في " +"كيفية قيام المترجم بترتيب التعليمات يمكن أن تجعل المرشح يبدو أقرب دون حل " +"المشكلة الأساسية. يمكن لمثل هذه التشخيصات أن توجه التجربة التالية، لكنني " +"سأؤكد صحة أي مكافأة مقابل \"الاقتراب\" مقابل فحص القبول الكامل." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"سأكون مهتمًا بالنمط عبر هذه النتائج. إذا كان نموذج الذكاء الاصطناعي المتخصص " +"يعمل بشكل جيد ضمن عائلة المترجمات المألوفة، فهل ستصمد هذه الميزة بعد تغيير " +"سلسلة الأدوات؟ وبمجرد أن يتمتع كلا نموذجي الذكاء الاصطناعي بقدرة جيدة على " +"الاسترجاع، ما مقدار التدريب الذي سيضيفه؟ ستساعدنا الإجابات في تحديد المكان " +"الذي يكون فيه كل نوع من النماذج أكثر فائدة." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "ما هو نوع وكيل الذكاء الاصطناعي الذي يشير إليه هذا؟" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"إذا تبين أن النماذج تساعد في مراحل مختلفة، فقد يكون الترتيب المفيد هو وكيل " +"واسع النطاق لديه إمكانية الوصول إلى نموذج متخصص للذكاء الاصطناعي. بمجرد أن " +"تصبح المهمة عبارة عن بحث مألوف للمترجم، يمكن أن تطلب نموذج الذكاء الاصطناعي " +"المتخصص للمرشحين. إذا لم تعد النتائج منطقية، فيمكن للعامل الأوسع العودة إلى " +"الدليل المستهدف أو التحقيق في القياس نفسه." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"وفي هذا الترتيب، يصبح التخصص أداة يمكن للعميل اختيارها مع تطور التحقيق. " +"يحتفظ الوكيل بحرية تغيير الاتجاه الذي جعل الاختراقات السابقة ممكنة." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"ويأتي هذا بشكل طبيعي من التحول الصناعي الذي وصفته في المقالة السابقة. إن " +"القدرة على إجراء المزيد من التجارب تغير الطريقة التي ننظم بها العمل. كما أنه" +" يمنحنا سببًا للتساؤل عن القرارات التي تحتاج إلى حكم واسع النطاق وتلك التي " +"تتحسن من خلال الخبرة المتكررة في حرفة معينة." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"حتى الآن، استحق أقوى نموذج عام مكانه في سير عملي لأنه حل مشكلات كنت قد " +"تركتها دون حل. وهذه النجاحات تدفعني إلى دراسة العملية: كم منها اعتمد على " +"اتساع قدراته، وكم يمكن أن يتولاه نموذج مدرب على هذا النوع من إعادة البناء؟" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}توفر لنا المستودعات طريقة لاختبار السؤال.{ph1} أود استخدام هذا السجل " +"لإجراء المقارنة ومعرفة ما نتعلمه." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "الأدلة وإسناد النموذج" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"تصف الأمثلة المقارنات التاريخية على مستوى الوظيفة المسجلة في الالتزامات " +"المرتبطة. تعتبر عمليات التحقق من وقت تشغيل اللعبة بأكملها بمثابة مراحل " +"منفصلة. تمت مراجعة سجلات المصدر والمطابقة في 13 أكتوبر 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"التسمية TH09 {ph0} تعني GPT-6-Astra. تغير النموذج المرتبط بـ {ph1} بمرور " +"الوقت، لذا لا يمكن لهذه التسمية وحدها تحديد النموذج المستخدم في عملية تشغيل " +"معينة. توفر أسماء النماذج الصريحة في الكوميتات المذكورة الأخرى الإسناد " +"المسجل. لا تتضمن هذه السجلات قياسات متسقة للتكلفة أو الجهد لكل عملية تشغيل." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 عمر الكائن المؤقت:{ph1} تم التحقق من {ph2}مراجعة السياق " +"السابقة{ph3} و{ph4}إعادة البناء الكاملة من خلال إعادة تجميع نظيفة من " +"المصدر{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front رد الاتصال:{ph1} {ph2}مناطق التشخيص التي لم تتطابق مع{ph3}، " +"والرسم البياني الجديد لتدفق التحكم في {ph4}Astra{ph5} و{ph6}فحص إعادة " +"الترجمة المقبول{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}معرفة المترجم:{ph1} {ph2}TH095 إعادة استخدام سلوك مجموعة المعرفات{ph3}،" +" {ph4}TH04 شيفرة اللاعب وترتيب الرابط{ph5} و{ph6}Luna إعادة البناء الكاملة " +"لوظيفة إنشاء العدو لـ TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}عمليات الفحص والتشخيص:{ph1} {ph2}TH08 التدقيق الثابت للفاصلة " +"العائمة{ph3}، و{ph4}TH08 التحقيق الرقمي{ph5} و{ph6}TH09 إعادة البناء مع " +"توفير إعادة التشغيل{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"المقارنات المقترحة للنماذج المتخصصة والتدريب RL هي تجارب مستقبلية. تاريخ " +"المشروع يحفزهم. لم يتم تقييم أي نموذج متخصص مدرب لهذا المقال." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "هل تحتاج الهندسة العكسية إلى نموذج أكبر؟ | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"ما تعلمته من إعادة بناء Touhou عن النماذج العامة والمتخصصة، وعن تعلم اقتراح " +"فرضيات أفضل من ملاحظات المترجم البرمجي." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "في هذه الصفحة" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "النماذج والهندسة العكسية مقال" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "تجارب إعادة بناء الشيفرة المختارة" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "العودة للأعلى" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"تتضمن {ph0}ملاحظات الأدلة التفصيلية{ph1} المقارنات المسجلة وسياق التجارب." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "بقلم N0zoM1z0 · 13 أكتوبر 2026 · مسودة للمراجعة" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "دليل الإعداد" diff --git a/website/locales/de/messages.po b/website/locales/de/messages.po index 3a0ab1304..2b23bc4a3 100644 --- a/website/locales/de/messages.po +++ b/website/locales/de/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Startseite{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Gedanken zum Reverse Engineering." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Spielrekonstruktion{ph0}Essay" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Die industrielle Revolution im Reverse Engineering" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -53,34 +53,35 @@ msgstr "" "gelehrt, über Agenten, Überprüfung und Wissen, dass Verbindungen über " "Projekte hinweg." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Lesen Sie den Artikel" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Von N0zoM1z0 · 10. Oktober 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -101,6 +102,8 @@ msgstr "" "REA und KI-Agenten." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -136,112 +139,117 @@ msgstr "" "REA - Finden Sie heraus, wie Software funktioniert. Reverse Engineering mit " "Ihrem Codierungsagenten." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "REA-Startseite" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Hauptnavigation" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA auf GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "REA auf Discord beitreten" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "REA auf X folgen" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -250,35 +258,35 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Startseite{ph1} / {ph2}Blog{ph3} / Touhou Wiederaufbau" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Essay * Touhou-Rekonstruktion" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Die industrielle Revolution im Reverse Engineering." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Von N0zoM1z0 · 10. Oktober 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Das Wichtigste" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -291,7 +299,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -305,7 +313,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -318,7 +326,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -331,7 +339,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -342,65 +350,65 @@ msgstr "" "RE.{ph1} Die Methoden nehmen immer noch Gestalt an. Es gibt noch viel zu " "entdecken." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Wie erleben Sie Verbindungen" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Menschliche Richtung{ph1} * Ziel und Akzeptanzkriterien" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Autonomie" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agent" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Wähle ein Experiment.{ph0}Schlage eine Hypothese vor." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Prüfung" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Prüfreferenz" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Test gegen eine{ph0}konkreter Hinweis." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Repository" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Arbeitsgedächtnis" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -409,7 +417,7 @@ msgstr "Code, Beweise,{ph0}kontrollen und Unterricht." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -418,26 +426,26 @@ msgstr "Mismatch{ph0}{ph1}Überarbeiten Sie die Hypothese{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Best{ph0}{ph1}Ausgangspunkt{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Wiederverwendung" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Übergeben{ph1} * Bewahren Sie das Ergebnis und seine Beweise auf" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -446,14 +454,14 @@ msgstr "" "Jedes Projekt verlässt das nächste mit einem besseren Ausgangspunkt. Dazu " "gehört auch, die Prüfungen zu korrigieren, wenn wir eine Lücke entdecken." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "In diesem Artikel" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -461,7 +469,7 @@ msgstr "{ph0}Februar 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -469,7 +477,7 @@ msgstr "{ph0} TH08 : die Fortsetzung{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -477,7 +485,7 @@ msgstr "{ph0}Zwei Ansätze{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -485,7 +493,7 @@ msgstr "{ph0} TH095 : Aufbereitung{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -493,7 +501,7 @@ msgstr "{ph0} TH04 : architekturübergreifend{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -501,7 +509,7 @@ msgstr "{ph0}Von exakt zu lesbar{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -509,18 +517,18 @@ msgstr "{ph0}Der industrielle Wandel{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Was möglich wird{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Was hat sich im August 2026 geändert" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -535,7 +543,7 @@ msgstr "" "Zeit mit der nächsten Funktion zu verbringen. Es bedeutete auch, ein immer " "größeres Bild in meinem Kopf zu behalten." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -549,7 +557,7 @@ msgstr "" "Artikel. Die Methode kann an anderer Stelle nützlich sein, aber jedes Feld " "muss festlegen, was es anhand einer zuverlässigen Referenz überprüfen kann." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -562,7 +570,7 @@ msgstr "" "gewöhnliche Entwicklungstools kommen kann. Touhou Reconstruction gab mir ein" " umfangreiches Projekt, in dem ich es herausfinden konnte." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -581,7 +589,7 @@ msgstr "" "Richtung des Projekts richten und darauf, ob seine Überprüfungen " "vertrauenswürdig waren." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -592,7 +600,7 @@ msgstr "" "fragen, was über das aktuelle Projekt hinaus überleben würde. Würde das " "nächste Spiel von allem profitieren, was wir gerade gelernt hatten?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08 : auf menschlicher Arbeit aufbauen" @@ -601,7 +609,7 @@ msgstr "TH08 : auf menschlicher Arbeit aufbauen" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -615,7 +623,7 @@ msgstr "" "mir eine substanzielle Grundlage. Es kam mit Kenntnis des Builds und einer " "Geschichte von Beiträgen, die ich in der Fortsetzung aufbewahrt habe." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -627,7 +635,7 @@ msgstr "" "zeichnete das Ledger die Quelle für alle 1.107 identifizierten " "Spielfunktionen auf." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -638,7 +646,7 @@ msgstr "" "Tage nach Beginn der Fortsetzung, festgelegt. Eine Webausgabe folgte. Die " "native 64-Bit-Version Linux ist am 30.August eingetroffen." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -654,7 +662,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -673,12 +681,12 @@ msgstr "" "Erklärung vor und testet sie; Eine Nichtübereinstimmung gibt ihm etwas " "Spezifisches zu untersuchen." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Eine exakte Übereinstimmung mit der falschen Konstante" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -690,7 +698,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -703,7 +711,7 @@ msgstr "" "rekonstruierte Quelle überprüfte die Leistung des Spielers gegen {ph0}. Das " "Original verwendet {ph1}, der Schwellenwert für die maximale Leistung." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -719,14 +727,14 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "" "{ph0}Doch die Funktion hatte den genauen Vergleich bereits bestanden.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -742,7 +750,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -758,7 +766,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -773,7 +781,7 @@ msgstr "" "Referenzen untersucht. Es wurden weitere zwölf falsche Referenzen für fünf " "akzeptierte Funktionen gefunden." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -787,7 +795,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -797,7 +805,7 @@ msgstr "" "{ph0}Die Verifikationsreferenz (Oracle) musste ebenfalls rekonstruiert " "werden.{ph1} Das Reparieren war Teil der Reparatur des Spiels." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -816,7 +824,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -832,7 +840,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -842,7 +850,7 @@ msgstr "" "{ph0}Ein erfolgreicher Batch gab uns sowohl wiederhergestellten Code als " "auch eine bessere Umgebung für den nächsten Batch.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Zwei verschiedene Rekonstruktionsideen" @@ -851,7 +859,7 @@ msgstr "Zwei verschiedene Rekonstruktionsideen" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -864,7 +872,7 @@ msgstr "" " die weitere Entwicklung bis zur Fertigstellung privat erfolgen wird. Eine " "Passage lautet:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -874,7 +882,7 @@ msgstr "" "Bereich, die aus unserer Arbeit stammen, zeichnet ein schlechtes Bild für " "zukünftige Dekompilierungsbemühungen…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -892,7 +900,7 @@ msgstr "" "die ich diskutieren möchte, betrifft die Frage, wie der Wiederaufbau " "ablaufen soll und wie ein Beitrag zu bewerten ist." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -906,7 +914,7 @@ msgstr "" "Vertrauen in den Mitwirkenden war wichtig, weil so viele Überlegungen " "während der Arbeit stattfanden." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -917,7 +925,7 @@ msgstr "" "Werkzeuge. Was sich für mich geändert hat, war, dass ein Agent dieses Wissen" " nutzen konnte, um die nächste Untersuchung selbstständig durchzuführen." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -933,7 +941,7 @@ msgstr "" "uns für eine Implementierung entschieden haben, auch wenn ein Agent die " "meiste Arbeit erledigt hat." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -946,7 +954,7 @@ msgstr "" "Das wirft echte Fragen zum Kredit auf. Es ändert auch, was Betreuer wissen " "müssen, bevor sie einen Beitrag annehmen." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -962,7 +970,7 @@ msgstr "" "falsch ist. Verschiedene Gemeinschaften können wählen, wie viel von dieser " "Veränderung sie übernehmen möchten." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -987,7 +995,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1000,14 +1008,14 @@ msgstr "" "Auszug. Von TH08 {ph4}credits und Provenienz{ph5} notieren Sie die " "Fortsetzungsgrenze." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095 : Erfahrung beginnt sich zu vermehren" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1022,7 +1030,7 @@ msgstr "" "lernen. Aber wir wussten schon viel mehr darüber, wie man einen Wiederaufbau" " beginnt und wie man ihn in Bewegung hält." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1036,7 +1044,7 @@ msgstr "" "i386-Rekonstruktion wurde am 10.September, etwa zwölf Tage nach der " "Initialisierung, als spielbar markiert." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1048,7 +1056,7 @@ msgstr "" "Erfahrung war bereits in den Tools und in der Organisation des Projekts " "vorhanden." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1064,7 +1072,7 @@ msgstr "" " Lektion hat dazu beigetragen, wie wir uns dem gesamten Programmaufbau von " "TH095 näherten." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1078,7 +1086,7 @@ msgstr "" "das Ergebnis verwenden, ohne die Untersuchung zu wiederholen, die dazu " "geführt hat." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1093,7 +1101,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1105,7 +1113,7 @@ msgstr "" " Wir können mehr von den Anstrengungen des nächsten Projekts darauf " "verwenden, was an seinem Ziel tatsächlich neu ist." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1119,7 +1127,7 @@ msgstr "" "rekonstruieren, um herauszufinden, warum die Quelle so aussieht, wie sie " "aussieht." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04 : Der Workflow überlebt eine andere Architektur" @@ -1128,7 +1136,7 @@ msgstr "TH04 : Der Workflow überlebt eine andere Architektur" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1144,7 +1152,7 @@ msgstr "" "bei den Windows-Spielen erforderlich. Bestehenden {ph2}ReC98 Arbeit{ph3} gab" " uns auch hier wertvolles Wissen und Quellenmaterial." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1158,7 +1166,7 @@ msgstr "" "Einrichten einer funktionierenden DOS-Version gibt diesem Port zuerst eine " "Referenz." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1171,7 +1179,7 @@ msgstr "" "haben. Aber der Agent könnte immer noch einer Frage bis zu einem Ergebnis " "folgen und dieses Ergebnis das nächste Experiment leiten lassen." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1186,7 +1194,7 @@ msgstr "" " die Beweise und Überprüfungen verfügbar sind, kann ein Agent die Frage " "ähnlich wie bei einem Windows-Titel bearbeiten." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1198,7 +1206,7 @@ msgstr "" "vorne zu beginnen. Die Architektur definierte das Problem; Der Workflow gab " "uns immer noch einen Weg, es zu lösen." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1215,7 +1223,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1226,12 +1234,12 @@ msgstr "" "Testen{ph1} · {ph2}64-bit-Anschluss{ph3}. Der Hafen bleibt in der " "Entwicklung." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Vom exakten Code zum lesbaren Code" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1240,7 +1248,7 @@ msgstr "" "Sobald eine Rekonstruktion funktioniert, möchte ich, dass jemand anderes sie" " verstehen kann." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1255,7 +1263,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1273,7 +1281,7 @@ msgstr "" "Quelle, damit die nächste Person sehen kann, woher diese Interpretation " "stammt." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1288,14 +1296,14 @@ msgstr "" "diesen Status besitzen soll. Um das Verhalten sicher zu verschieben, müssen " "wir die Beziehung hinter dem alten Speicherzugriff wiederherstellen." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Die Reihenfolge, die ich jetzt benutze, ist:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1312,7 +1320,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1329,7 +1337,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1346,7 +1354,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1361,7 +1369,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1378,7 +1386,7 @@ msgstr "" "Die zweite überprüft, ob das rekonstruierte Programm auf den von uns " "ausgeübten Pfaden noch korrekt aufgebaut ist und sich korrekt verhält." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1392,7 +1400,7 @@ msgstr "" "Überprüfungen verfügbar halten, muss der Agent dies konkret untersuchen, " "bevor er einen Refactor weiterführt." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1410,7 +1418,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1429,7 +1437,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1440,12 +1448,12 @@ msgstr "" "Rekonstruktion macht das gewonnene Wissen nutzbar.{ph1} Ein Port kann dann " "auf beiden aufbauen." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Was macht diesen industriellen Wandel aus" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1459,7 +1467,7 @@ msgstr "" "nützlichsten Dinge, die ich tun konnte. Ein besseres Werkzeug könnte bei " "jeder späteren Funktion helfen, die es benötigt." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1473,7 +1481,7 @@ msgstr "" "dass ich jeden Schritt vorschreibe, bleibt ein Großteil der Arbeit an meine " "Aufmerksamkeit gebunden." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1487,7 +1495,7 @@ msgstr "" "erneut zu versuchen. Ich muss noch entscheiden, ob die gesammelten Beweise " "einen Projektmeilenstein unterstützen." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1502,7 +1510,7 @@ msgstr "" "Referenzprüfungen. Der Agent kann diese verwenden, um die von ihm " "vorgeschlagene Quelle zu testen und zu sehen, wo seine Erklärung steht." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1520,7 +1528,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1541,7 +1549,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1559,7 +1567,7 @@ msgstr "" "betroffenen Ergebnisse erneut überprüfen. Das nächste Projekt kann dann ein " "stärkeres Werkzeug erben." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1575,7 +1583,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1588,7 +1596,7 @@ msgstr "" "voranzutreiben. Die Arbeit an einem Spiel kann die Startbedingungen für ein " "anderes verbessern." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1600,12 +1608,12 @@ msgstr "" "ändert, wie viel die nächste Person — oder der nächste Agent - erledigen " "kann." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Die Projekte, die wir jetzt in Betracht ziehen können" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1617,7 +1625,7 @@ msgstr "" "meiner eigenen Aufmerksamkeit verlangen, als ich es realistisch geben " "könnte. Viele Projekte würden Ideen bleiben." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1635,7 +1643,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1646,7 +1654,7 @@ msgstr "" "Zugang, welches Feedback und welches gesammelte Wissen würden einen Agenten " "zuverlässig daran arbeiten lassen?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1658,12 +1666,12 @@ msgstr "" "nächsten nähern. Ich möchte weiter erforschen, wie weit uns das bringen " "kann." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Projektmeilensteine und Quellen" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1698,7 +1706,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1733,7 +1741,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1752,7 +1760,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1776,7 +1784,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1799,7 +1807,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1815,7 +1823,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1837,7 +1845,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1852,7 +1860,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1874,27 +1882,27 @@ msgstr "" "Rekonstruktion mit KI-Agenten und wie sich das Wissen in TH08 , TH095 und " "PC-98 TH04 zusammenfügt ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Erfahrungsaustausch zwischen Projekten" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Touhou Wiederaufbau Essay" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -1903,18 +1911,18 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Startseite{ph1}{ph2}/{ph3}Dinosaurier-Geschwindigkeitslabor" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Inspizieren → Neu erstellen → Ändern" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Baue die Geschwindigkeitsregel des Dinosauriers wieder auf." @@ -1923,7 +1931,7 @@ msgstr "Baue die Geschwindigkeitsregel des Dinosauriers wieder auf." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1936,15 +1944,15 @@ msgstr "" "zurückgegeben;{ph1} wir haben seine Regel verwendet, um dieses Minispiel mit" " zu bauen {ph2}einstellbare Geschwindigkeit.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Auf dieser Seite" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1952,7 +1960,7 @@ msgstr "{ph0}Spielen und die Geschwindigkeit ändern{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1960,7 +1968,7 @@ msgstr "{ph0}Lesen Sie die wiederhergestellte Regel{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1968,18 +1976,18 @@ msgstr "{ph0}Überprüfen Sie die Rekonstruktion{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Probieren Sie die Analyse aus{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Spielen und die Geschwindigkeit ändern" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1992,51 +2000,51 @@ msgstr "" "wiederhergestellte Regel aus, um bei 6 zu beginnen und schrittweise wieder " "zu beschleunigen." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Den Nachbau spielen" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Spielen" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Springen ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Neustart" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Geschwindigkeit" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Verwenden Sie die wiederhergestellte Beschleunigungsregel" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "" "Ursprüngliche Regel: Beginnen Sie bei 6 und erhöhen Sie sich dann in " "Richtung 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Bewegen Sie den Schieberegler, um Ihre eigene Geschwindigkeit einzustellen. " "Leertaste oder Sprung löscht einen Kaktus." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2045,7 +2053,7 @@ msgstr "" "Aktivieren Sie JavaScript, um die Rekonstruktion abzuspielen. Der Code und " "die obige Erklärung bleiben lesbar." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Lesen Sie das zurückgegebene Skript REA" @@ -2053,7 +2061,7 @@ msgstr "Lesen Sie das zurückgegebene Skript REA" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2068,7 +2076,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2078,18 +2086,18 @@ msgstr "" "Die Einstellungen sind {ph0}, {ph1} und {ph2}. Das Spiel führt diesen Zweig " "bei einem Update ohne Kollision aus." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Verwenden Sie die gleiche Regel im neuen Spiel" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Kopieren" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2107,7 +2115,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" @@ -2115,12 +2123,12 @@ msgstr "" "{ph0}Laden Sie die Geschwindigkeitsregel herunter{ph1} · {ph2}Lesen Sie den " "Spielcode{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Überprüfen Sie die Rekonstruktion" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2132,27 +2140,27 @@ msgstr "" " aufgezeichneten Geschwindigkeiten mit einer Wiedergabe der " "wiederhergestellten Regel." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Aktualisierungen" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Originalspiel" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Rekonstruierte Herrschaft" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Führen Sie den Geschwindigkeitscheck durch" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2162,14 +2170,14 @@ msgstr "" "sodass das letzte Inkrement eine Geschwindigkeit von knapp über 13 annehmen " "kann." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Probieren Sie die Analyse selbst aus" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2178,7 +2186,7 @@ msgstr "{ph0}Einrichten von REA {ph1} mit Ihrem Codierungsagenten." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2187,7 +2195,7 @@ msgstr "" "Folgen Sie dem {ph0}schritte zur Browser-Verbindung{ph1}, wobei {ph2} wie " "die Seiten-URL." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2204,7 +2212,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2216,7 +2224,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2231,7 +2239,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2246,7 +2254,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2274,12 +2282,12 @@ msgstr "" "Lies die Geschwindigkeitsregel des Dinosaurierspiels mit REA, baue sie neu " "auf, ändere dann die Geschwindigkeit und spiele." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Geschwindigkeitsrekonstruktion von Dinosauriern" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2288,52 +2296,52 @@ msgstr "" "Dinosaurier-Minispiel. Verwenden Sie die Sprungtaste oder drücken Sie die " "Leertaste, während das Spiel fokussiert ist." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Rekonstruierte Geschwindigkeitsregel kopieren" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Aufforderung zur Dinosaurieranalyse kopieren" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Startseite{ph1} / HÄUFIG GESTELLTE FRAGEN" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA HÄUFIG GESTELLTE FRAGEN." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Einrichtung, Updates, Analyse und Fehlerbehebung." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Themen" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2341,7 +2349,7 @@ msgstr "{ph0}Einrichtung und Updates{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2349,7 +2357,7 @@ msgstr "{ph0}Analyse{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2357,31 +2365,31 @@ msgstr "{ph0}Fehlerbehebung{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Daten und Weitergabe{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Einrichtung und Updates" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Wie installiere ich REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * Agenten-Einrichtung" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Kopieren" @@ -2389,7 +2397,7 @@ msgstr "Kopieren" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2404,12 +2412,12 @@ msgstr "" "{ph0}Einrichtungsanleitung{ph1} erklärt die Voraussetzungen und die erste " "Analyse." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Welche Codierungsmittel können REA verwenden?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2424,18 +2432,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Verbinden Sie Ihren Codierungsagenten{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Wie aktualisiere ich REA?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2444,13 +2452,13 @@ msgstr "" "REA wird häufig veröffentlicht, einschließlich Fehlerkorrekturen. Wenn Sie " "den CLI mit npm installiert haben :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * installiert CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2460,14 +2468,14 @@ msgstr "" "Befolgen Sie den Befehl Setup Refresh, der vom Update gedruckt wird. Wenn " "Sie Ihren Agenten über einrichten {ph0}, laufen:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * Einrichtung des Aktualisierungsagenten" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2480,14 +2488,14 @@ msgstr "" "Einrichtung erneut aus, damit er die neue Version nutzt. Für einen einzelnen" " CLI-Aufruf hängen Sie den Befehl an {ph0} an." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Installiert den Skill von skills.sh genug?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2500,24 +2508,24 @@ msgstr "" "installieren, starten Sie Ihren Agenten neu, damit er die Tools aufrufen " "kann." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Analyse" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Was kann ich mit REA analysieren?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Beginnen Sie mit der Art von Software, die Sie haben:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2529,7 +2537,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2541,7 +2549,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2550,7 +2558,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2562,12 +2570,12 @@ msgstr "" "Firmware und gepackte Ressourcen. {ph0}Sehen Sie sich die Fallstudien " "an{ph1} für durchgeführte Untersuchungen." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Benötige ich Hopper, Ghidra oder IDA?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2579,7 +2587,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2592,12 +2600,12 @@ msgstr "" "Ihr Ziel bestimmen, welcher Anbieter verwendet werden kann. {ph0}Analyse von" " Maschinencode-Programmen einrichten{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Kann ich REA ohne Codierungsmittel verwenden?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2606,14 +2614,14 @@ msgstr "" "Ja. Der CLI verwendet die gleichen Analyse-Workflows. Für eine lokale " "JavaScript- oder Electron-App:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * statische Anwendungsanalyse" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2624,13 +2632,13 @@ msgstr "" "ASAR-Datei. {ph0}Verwenden Sie den CLI {ph1} für Installationsoptionen." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Welchen Code liefert REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2645,7 +2653,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2658,12 +2666,12 @@ msgstr "" "Berechnung{ph1} und {ph2}CTF-Flaggenprüfer{ph3} zeigen Sie, wie dieser " "Prozess funktioniert." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Was soll ich meinen Agent fragen?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2680,7 +2688,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2688,7 +2696,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2698,18 +2706,18 @@ msgstr "" "Ersetzen Sie den Pfad durch Ihr Ziel. Der {ph0}Hilfslinien{ph1} geben Sie " "Eingabeaufforderungen für native, Electron- und Browserbeispiele an." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Fehlerbehebung" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Warum kann mein Agent die REA-Tools nicht sehen?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2719,7 +2727,7 @@ msgstr "" "Starten Sie Ihren Agenten nach der Einrichtung neu oder verbinden Sie ihn " "erneut. Überprüfen Sie die REA-Registrierung mit {ph0}; für Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * Überprüfen Sie einen Client" @@ -2727,7 +2735,7 @@ msgstr "Terminal * Überprüfen Sie einen Client" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2738,14 +2746,14 @@ msgstr "" "Wenn der Bericht eine fehlende oder veraltete Registrierung anzeigt, führen " "Sie Setup für diesen Client aus:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * Reparieren Sie das Setup eines Clients" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2758,14 +2766,14 @@ msgstr "" "Sie den Verbindungsfehler MCP des Clients. {ph0}Weitere Setup-" "Diagnosen{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Muss ich Hopper zuerst starten?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2778,14 +2786,14 @@ msgstr "" "unbeaufsichtigten Analyse ab. {ph0}Siehe Einrichtung des nativen " "Anbieters{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Was mache ich bei einem Fehler?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2798,7 +2806,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2811,17 +2819,17 @@ msgstr "" "Geben Sie den Anbieternamen an, wenn das Problem die Analyse von " "Maschinencodeprogrammen betrifft." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Daten und Weitergabe" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "Lädt REA meine App hoch?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2830,7 +2838,7 @@ msgstr "" "REA analysiert Ziele auf Ihrem Computer. Ihr Agent erhält die Ergebnisse, " "und die Datenrichtlinie seines Modellanbieters gilt für diese Ergebnisse." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Wie kann ich ein Beispiel teilen oder einen Beitrag leisten?" @@ -2839,7 +2847,7 @@ msgstr "Wie kann ich ein Beispiel teilen oder einen Beitrag leisten?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2855,7 +2863,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2880,77 +2888,77 @@ msgstr "" "Antworten auf häufig gestellte Fragen zum REA: Installation, Updates, " "Analysetools, Codierungsagenten, Fehlerbehebung und Beispiele zum Teilen." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Häufig gestellte Fragen zu REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "REA Setup-Befehl kopieren" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Kopieren Sie den Aktualisierungsbefehl REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Befehl zum Aktualisieren des Agenten-Setups kopieren" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Kopieren Sie den REA CLI-Analysebefehl" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Beispielanalyse-Eingabeaufforderung kopieren" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Clientdiagnosebefehl kopieren" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Befehl zum Kopieren des bereichsbezogenen Setups" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Startseite{ph1} / Ihre erste Untersuchung" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Finden Sie heraus, wo{ph0}exportierte Notizen gehen." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2959,14 +2967,14 @@ msgstr "" "Verwenden Sie REA, um eine kleine App zu überprüfen, folgen Sie der " "Schaltfläche Notizen exportieren und überprüfen Sie ein Detail selbst." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "In dieser Übung" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2974,7 +2982,7 @@ msgstr "{ph0}1. Einrichten{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2982,7 +2990,7 @@ msgstr "{ph0}2. Fragen Sie nach Export{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2990,7 +2998,7 @@ msgstr "{ph0}3. Folge der Antwort{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2998,13 +3006,13 @@ msgstr "{ph0}4. Überprüfen Sie eine Vorhersage{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Stellen Sie eine andere Frage{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Verbinden Sie Ihren Agenten mit REA" @@ -3017,29 +3025,29 @@ msgstr "1. Verbinden Sie Ihren Agenten mit REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Kopieren" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Oder führen Sie diesen Befehl in Ihrem Terminal aus:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3048,14 +3056,14 @@ msgstr "" "Überprüfen Sie den Plan, genehmigen Sie die Einrichtung und starten Sie dann" " Ihren Agenten neu. Bereits verbunden? Weiter unten." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Fragen Sie, wo der CSV geschrieben ist" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3067,7 +3075,7 @@ msgstr "" "exportieren{ph1} Schaltfläche. Ihr Agent kann seinen Code überprüfen, ohne " "Electron zu installieren oder zu starten." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3079,14 +3087,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Beispiel-ZIP herunterladen{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3096,12 +3104,12 @@ msgstr "" "Wenn Ihr Agent keine Dateien herunterladen kann, entpacken Sie dieses Archiv" " selbst. Gib ihm den Weg zum {ph0} ordner und die gleiche Exportfrage." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Folgen Sie der Antwort zurück zum Code" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "" @@ -3111,7 +3119,7 @@ msgstr "" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3123,12 +3131,12 @@ msgstr "" "die Notizen als CSV und schreibt {ph1} im Download-Ordner des Benutzers. Die" " Spalten sind {ph2} und {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Von der Schaltfläche zum Dateischreiber" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3137,7 +3145,7 @@ msgstr "" "Die statische Analyse von REA koppelt die Nachricht mit ihrem Handler. Das " "Ziel wird aus dem Code gelesen." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3149,7 +3157,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." @@ -3157,12 +3165,12 @@ msgstr "" "{ph0}Sehen Sie sich den vollständigen Code-Trace und das aufgezeichnete REA-" "Ergebnis an{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Überprüfen Sie eine Vorhersage" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3171,19 +3179,19 @@ msgstr "" "Die Spalten CSV werden durch ein Komma getrennt. Was passiert, wenn ein " "Notiztitel selbst ein Komma oder Anführungszeichen enthält?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Führen Sie den Check selbst durch" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Öffnen Sie ein Terminal im entpackten {ph0} Ordner:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3193,17 +3201,17 @@ msgstr "" "Bash oder Zsh. Ihr Agent kann denselben JavaScript in der Shell Ihrer " "Plattform ausführen." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Stellen Sie eine andere Frage" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Versuchen Sie ein Follow-up im selben Gespräch:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3212,7 +3220,7 @@ msgstr "" "Was passiert, wenn die Datei nicht geschrieben werden kann? Folgen Sie dem " "Fehler zurück zur Seite." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3225,7 +3233,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3239,7 +3247,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3253,7 +3261,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3278,65 +3286,65 @@ msgstr "" "Agenten ein, fragen Sie, wohin exportierte Notizen gehen, und überprüfen Sie" " den Formatierer CSV mit einem Beispieltitel." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Ihre erste REA-Untersuchung" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Installationsaufforderung für REA kopieren" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Setup-Befehl kopieren" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Aufforderung zur Untersuchung von Notizen kopieren" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Kopiere CSV Eingabeaufforderung prüfen" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Befehl Formatierungsprüfung kopieren" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Startseite{ph1} / Erste Schritte" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Richten Sie REA ein ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3344,49 +3352,49 @@ msgstr "" "Verbinden Sie REA mit Ihrem Codierungsagenten oder überprüfen Sie eine " "lokale App von Ihrem Terminal aus." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Öffnen Sie ein Terminal und überprüfen Sie:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminal" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Kopieren" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3400,7 +3408,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3411,17 +3419,17 @@ msgstr "" " System deaktiviert.\"{ph1} wenn du rennst {ph2}, führen Sie dies einmal aus" " und versuchen Sie es erneut:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Wenn Sie Homebrew verwenden :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Sonst:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Terminal schließen, wieder öffnen, dann:" @@ -3429,7 +3437,7 @@ msgstr "Terminal schließen, wieder öffnen, dann:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3441,7 +3449,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3453,7 +3461,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3463,14 +3471,14 @@ msgstr "" "Bevorzugen Sie einen regulären Installer? Laden Sie die LTS-Version herunter" " von {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Setup-Optionen" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3478,7 +3486,7 @@ msgstr "{ph0}Verbinden Sie Ihren Codierungsagenten{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3486,7 +3494,7 @@ msgstr "{ph0}Verwenden Sie den CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3494,18 +3502,18 @@ msgstr "{ph0}Analyse von Maschinencode-Programmen einrichten{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Hilfe bekommen{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Verbinden Sie Ihren Codierungsagenten" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3517,12 +3525,12 @@ msgstr "" " Grok Build und andere unterstützte MCP-Clients. Der Connector von Grok Bot " "wird aus seinem Chat hinzugefügt." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Neu bei Codierungsagenten?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3534,7 +3542,7 @@ msgstr "" "und fragt, bevor Änderungen vorgenommen werden. REA gibt es Werkzeuge für " "das Reverse Engineering." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3546,7 +3554,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3559,7 +3567,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3572,7 +3580,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3582,7 +3590,7 @@ msgstr "" "{ph0}{ph1} MODELL: OpenCode {ph2}{ph3}, OpenSource. Verbinden Sie den " "Modellanbieter Ihrer Wahl." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3600,18 +3608,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Oder führen Sie das Setup selbst aus" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Wie öffne ich ein Terminal?" @@ -3620,7 +3628,7 @@ msgstr "Wie öffne ich ein Terminal?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3636,7 +3644,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3650,7 +3658,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3665,7 +3673,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3675,7 +3683,7 @@ msgstr "" "Fügen Sie einen Befehl mit ein {ph0} {ph1} ( macOS ) : {ph2} {ph3}; Linux " "Anschlussklemmen: {ph4} {ph5} {ph6}), und drücken Sie dann die Eingabetaste." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3687,12 +3695,12 @@ msgstr "" " die vorhandene Konfiguration. Es fragt nach, bevor die Änderungen " "übernommen werden." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Starten Sie Ihren Client neu, wenn das Setup abgeschlossen ist." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Wie starte ich meinen Client neu?" @@ -3701,7 +3709,7 @@ msgstr "Wie starte ich meinen Client neu?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3717,7 +3725,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3727,7 +3735,7 @@ msgstr "" "{ph0}Terminalagenten{ph1} ( Claude Code , Codex , Gemini CLI ): Beenden Sie " "die Sitzung und starten Sie sie erneut." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3737,7 +3745,7 @@ msgstr "" "JavaScript- oder Electron-App können Sie mit beginnen:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3748,12 +3756,12 @@ msgstr "" "Sie die Einstiegspunkte, Aufrufe und Abhängigkeiten mit den " "Quellspeicherorten für Ihre Ergebnisse an." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Ersetzen Sie den Pfad durch Ihr lokales Ziel." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Wie erhalte ich den vollständigen Pfad eines Ordners?" @@ -3762,7 +3770,7 @@ msgstr "Wie erhalte ich den vollständigen Pfad eines Ordners?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3778,7 +3786,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3791,7 +3799,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3801,19 +3809,19 @@ msgstr "" "{ph0}Jedes System:{ph1} ziehen Sie den Ordner in ein Terminalfenster und " "sein Pfad wird angezeigt." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "Setzen Sie in einem Terminal Anführungszeichen um einen Pfad, der " "Leerzeichen enthält." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Verwenden Sie den CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3822,14 +3830,14 @@ msgstr "" "Analysieren Sie einen JavaScript- oder Electron-Anwendungsordner oder ein " "ASAR-Archiv, ohne die App auszuführen:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Statische Anwendungsanalyse" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3839,13 +3847,13 @@ msgstr "" "Ersetzen Sie den Pfad durch Ihr extrahiertes App-Verzeichnis oder {ph0} " "Datei. Auf Windows ein Pfad wie {ph1} arbeitet hier." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Wo finde ich eine App .asar-Datei?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3856,7 +3864,7 @@ msgstr "Electron Apps halten es normalerweise in einem {ph0} Ordner:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3868,7 +3876,7 @@ msgstr "{ph0} MODELL: Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3881,14 +3889,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} MODELL: Linux :{ph1} oft {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3896,7 +3904,7 @@ msgstr "" "Einige Apps werden an anderer Stelle installiert. Durchsuchen Sie den Ordner" " der App nach {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3908,31 +3916,31 @@ msgstr "" "Ergebnis markiert." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Wenn Sie eine dauerhafte {ph0} befehl in Ihrer Shell:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Installieren Sie den CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Fahren Sie mit dem JavaScript-Anwendungshandbuch fort{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Analyse von Maschinencode-Programmen einrichten" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3942,12 +3950,12 @@ msgstr "" "konfigurieren Sie eine unten, dann geben Sie REA Ihre ausführbare Datei oder" " Bibliothek." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Wählen Sie ein Werkzeug: Ghidra , Hopper oder IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3959,17 +3967,17 @@ msgstr "" "Installation benötigt einen nativen Dekompiler für Ihre Host-Architektur. " "Legen Sie die Pfade fest, bevor Sie Setup ausführen:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Verbinden Sie Ihre Ghidra-Installation" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra-Anschluss · macOS / Linux-Anschluss" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3981,12 +3989,12 @@ msgstr "" "Client auf. Auf Linux arm64 müssen Sie möglicherweise den nativen Dekompiler" " von Ghidra separat erstellen." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Verbinden Sie Ghidra mit Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3998,12 +4006,12 @@ msgstr "" "Verwenden Sie einen vorhandenen Ghidra 12.1.x-Installation und ein 64-Bit-" "JDK 21 oder neuer:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra-Verbindung * Windows-PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -4011,7 +4019,7 @@ msgstr "" "Ersetzen Sie die beiden Pfade durch Ihre Installationen und überprüfen Sie " "dann den Setup-Plan." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -4021,7 +4029,7 @@ msgstr "" "Befehl aus. Es erkennt eine vorhandene Installation oder bietet einen " "Installationsplan zur Genehmigung an." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -4031,7 +4039,7 @@ msgstr "" "Lizenzaktivierung des Hopper aus, bevor Sie eine unbeaufsichtigte Analyse " "durchführen." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -4042,7 +4050,7 @@ msgstr "" "Registrierung für eine angehängte GUI oder eine Headless-Datenbank. Die " "kopflose Analyse von Linux und macOS bleibt ungeprüft." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Verbinden Sie ein vorhandenes IDA MCP Registrierung" @@ -4052,7 +4060,7 @@ msgstr "Verbinden Sie ein vorhandenes IDA MCP Registrierung" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4065,13 +4073,13 @@ msgstr "" "wird ebenfalls akzeptiert. Zeigen Sie vor dem Einrichten mit REA auf diese " "Datei:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA-Verbindung * Windows-PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4089,7 +4097,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4101,18 +4109,18 @@ msgstr "" "Abfrage. Für einen Agenten, einschließen {ph1} in der Umgebung der REA-" "Registrierung und wählen Sie IDA beim Öffnen der Binärdatei." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Überprüfen Sie für ein vorhandenes Ghidra-Setup eine Funktion mit:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Funktionsanalyse" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." @@ -4120,12 +4128,12 @@ msgstr "" "Ersetzen {ph0} mit dem Funktionsnamen oder der Adresse, die Sie überprüfen " "möchten." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Wie die Analyse von Maschinencode-Programmsitzungen funktioniert" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4138,7 +4146,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4149,18 +4157,18 @@ msgstr "" "zu sehen, wie das Funktionsergebnis zu einer wiederhergestellten Berechnung " "führt." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Hilfe bekommen" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Wenn Ihr Agent REA nicht sieht" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4170,27 +4178,27 @@ msgstr "" "Starten Sie den Client nach dem Setup neu oder verbinden Sie ihn erneut. " "Überprüfen Sie die REA-Verbindung mit {ph0}; für Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Überprüfen Sie einen Client" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Wenn ein Anbieter Aufmerksamkeit braucht" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Überprüfen Sie den Anbieter, den Sie verwenden. Für Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Überprüfen Sie einen Anbieter" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4201,7 +4209,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4214,7 +4222,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4228,7 +4236,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4242,7 +4250,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4267,112 +4275,112 @@ msgstr "" "lokale JavaScript- oder Electron-App vom Terminal aus. Einrichtung, erste " "Fragen und Anleitungen für native Anbieter." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Node.js Versionsprüfung kopieren" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Kopieren Sie den Node.js-Installationsbefehl für Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Befehl zum Kopieren der PowerShell-Ausführungsrichtlinie" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Kopieren Homebrew Node.js Installationsbefehl" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Kopieren Sie den fnm-Installationsbefehl für macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Kopieren Sie Node.js 24 Befehle für macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Kopieren Sie den fnm-Installationsbefehl für Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Kopieren Sie Node.js 24 Befehle für Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA Anleitung für die ersten Schritte" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Installationsaufforderung für REA kopieren" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Befehl Agent-Setup kopieren" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Kopieren Sie den JavaScript-Analysebefehl" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Kopieren Sie den Installationsbefehl CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Ghidra-Verbindungsbefehl für macOS und Linux kopieren" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Kopieren Sie die Ghidra-Verbindung für die Windows-PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Kopieren Sie die IDA-Verbindung für die Windows-PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Befehl zur Analyse der nativen Funktion kopieren" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Clientdiagnosebefehl kopieren" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Provider-Diagnosebefehl kopieren" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -4381,20 +4389,20 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Startseite{ph1} / {ph2}Hilfslinien{ph3} / Browser-Beobachtung" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Sehen Sie, was passiert{ph0}wenn Sie klicken." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4404,14 +4412,14 @@ msgstr "" "Netzwerkanforderung und den JavaScript, der einen Download erstellt, zu " "verbinden." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "In diesem Handbuch" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4419,7 +4427,7 @@ msgstr "{ph0}Beispiel{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4427,7 +4435,7 @@ msgstr "{ph0}Öffnen Sie den Browser{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4435,7 +4443,7 @@ msgstr "{ph0}Fragen Sie Ihren Agenten{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4443,13 +4451,13 @@ msgstr "{ph0}Aufnahme von CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Lesen Sie die Anfrage und das Skript{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Was passiert, wenn Sie auf Exportieren klicken?" @@ -4459,7 +4467,7 @@ msgstr "Was passiert, wenn Sie auf Exportieren klicken?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4471,7 +4479,7 @@ msgstr "" "exportieren{ph3} Schaltfläche. Wenn Sie darauf klicken, wird geladen {ph4}, " "formatiert die beiden Notizen als CSV und startet einen Download." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Vom Klick zum CSV Download" @@ -4482,7 +4490,7 @@ msgstr "Vom Klick zum CSV Download" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4499,7 +4507,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4518,7 +4526,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4528,17 +4536,17 @@ msgstr "" "{ph0}03 · Ihr Agent{ph1}{ph2}Lesen Sie den Exportcode{ph3}{ph4}Verbinden Sie" " die beobachtete Anforderung mit {ph5} in {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Starten Sie die Aufnahme, bevor Sie auf Notizen exportieren klicken." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Öffnen Sie Chrome mit Remote-Debugging" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4547,21 +4555,21 @@ msgstr "" "Öffnen Sie das gehostete Notes-Beispiel mit einem separaten Browserprofil " "und einem lokalen Debugging-Port. Auf Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Starten Sie den Beispielbrowser" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Kopieren" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4571,7 +4579,7 @@ msgstr "" "oder Windows . Sie können die Seiten-URL durch eine andere Seite ersetzen, " "die Sie überprüfen möchten." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4581,7 +4589,7 @@ msgstr "" "die Kontrolle über die Seite, führen die Aktion aus und schließen den " "Browser, wenn Sie fertig sind." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Bitten Sie Ihren Agenten, eine Aktion zu sehen" @@ -4594,7 +4602,7 @@ msgstr "Bitten Sie Ihren Agenten, eine Aktion zu sehen" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4606,7 +4614,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4618,7 +4626,7 @@ msgstr "" "CSV aufgebaut?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4629,7 +4637,7 @@ msgstr "" "Endpunkt, {ph0} und die Seiten-URL. Lassen Sie die Aufnahme starten, bevor " "Sie klicken." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4640,23 +4648,23 @@ msgstr "" " die resultierenden Beweise. Es kann dann das Skript hinter dem Export " "überprüfen." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Oder vom Terminal aus erfassen" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Suchen Sie die Ziel-ID der Seite:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Finden Sie die Seite" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4666,14 +4674,14 @@ msgstr "" "Wählen Sie das Ziel mit der Beispiel-URL für Notizen aus. Ersetzen {ph0} " "unten mit seiner ID, dann lauf:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Erfassen Sie die nächsten zehn Sekunden" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4684,7 +4692,7 @@ msgstr "" "auf {ph0}Notizen exportieren{ph1} in diesem Browser. Das Ergebnis kommt nach" " dem Ende des Beobachtungsfensters an." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4695,49 +4703,49 @@ msgstr "" "während dieses Fensters und die Form der JSON-Antwort. Frühere Anfragen " "liegen außerhalb dieser Erfassung." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Lesen Sie das Anforderungs- und Exportskript" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Aufgenommen mit REA 4.1.0 am Beispiel lokaler Notizen" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Erfasste Tatsache" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Wert" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Anfrage" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Antwort" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Initiator der Anfrage" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} · Skript" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Antwortstruktur" @@ -4745,19 +4753,19 @@ msgstr "Antwortstruktur" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} mit {ph1} und {ph2} Datenfelder" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Lesen Sie die geladenen Skripte" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4769,7 +4777,7 @@ msgstr "" "Daten verwendet werden:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4782,7 +4790,7 @@ msgstr "" " fest, dass dieser Klick angefordert wurde {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4794,7 +4802,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4819,65 +4827,65 @@ msgstr "" "erfassen Sie einen Klick, überprüfen Sie die Anforderung und folgen Sie dem " "Exportskript." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Browser-Beobachtung" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Kopieren Starten Sie den Beispielbrowser" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Beispiel-Eingabeaufforderung kopieren" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Kopieren finden Sie die Seite" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Kopieren Erfassen Sie die nächsten zehn Sekunden" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Kopieren Lesen Sie die geladenen Skripte" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Startseite{ph1} / Hilfslinien" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA Anleitungen." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4887,40 +4895,40 @@ msgstr "" "Browseranforderung. Jede Anleitung enthält eine Eingabeaufforderung, einen " "Code und Ergebnisse." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Erste Untersuchung" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Einrichten von REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "" "Schließen Sie Ihren Codierungsagenten an oder verwenden Sie REA vom Terminal" " aus." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Erste Schritte mit REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Maschinencode-Programme" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "" "Stellen Sie eine Berechnung der linken / rechten Klangposition wieder her" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4930,22 +4938,22 @@ msgstr "" "Sie die Anweisungen, folgen Sie einem Aufrufer, lesen Sie numerische " "Konstanten und überprüfen Sie das wiederhergestellte C." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Handbuch zur Analyse von Maschinencode-Programmen" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "Modell: JavaScript und Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Einem CSV-Export folgen" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4955,14 +4963,14 @@ msgstr "" "und Hauptprozess. Verwenden Sie REA, um die API, den IPC-Kanal und den " "Dateischreiber zu verbinden." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Anleitung für JavaScript und Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4970,17 +4978,17 @@ msgstr "" "Für eine größere gepackte App folgen Sie {ph0} Zwischenablage-Brücke von " "Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Browserverhalten" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Beobachten Sie einen Klick" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4990,7 +4998,7 @@ msgstr "" "Exportanforderung und suchen Sie den Code, der die Antwort in einen Download" " umwandelt." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Anleitung zur Browserbeobachtung" @@ -5009,12 +5017,12 @@ msgstr "" "Lernen Sie REA anhand kurz gearbeiteter Beispiele: eine native Berechnung, " "einen Electron CSV Export und eine Browseranforderung." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -5023,7 +5031,7 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" @@ -5032,13 +5040,13 @@ msgstr "" "Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Verfolgen Sie einen Electron {ph0} CSV exportieren." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -5047,14 +5055,14 @@ msgstr "" "Folgen Sie einem Knopfdruck von der Seiten-API über den Electron IPC zum CSV" " File Writer." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "In diesem Handbuch" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -5062,7 +5070,7 @@ msgstr "{ph0}Beispiel{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5070,7 +5078,7 @@ msgstr "{ph0}Fragen Sie Ihren Agenten{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5078,7 +5086,7 @@ msgstr "{ph0}Verfolgen Sie den Exportcode{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5086,20 +5094,20 @@ msgstr "{ph0}Probieren Sie das Beispiel aus{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Überprüfen Sie den CSV-Schreiber{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Wohin geht \"Notizen exportieren\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5112,7 +5120,7 @@ msgstr "" "Hauptprozess und schreibt einen CSV . Das Verhalten ist auf mehrere Dateien " "verteilt." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "Der CSV-Export über Electron-Prozesse hinweg" @@ -5126,7 +5134,7 @@ msgstr "Der CSV-Export über Electron-Prozesse hinweg" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5143,7 +5151,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5160,7 +5168,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5173,13 +5181,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} formatiert die Notizen → {ph1} schreibt {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5190,14 +5198,14 @@ msgstr "" "exponierte API. Der Pfad wird aus dem Code abgeleitet; Eine " "Laufzeiterfassung kann überprüfen, was ausgeführt wird." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Fragen Sie nach dem CSV Export" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5215,14 +5223,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Kopieren" @@ -5233,7 +5241,7 @@ msgstr "Kopieren" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5244,7 +5252,7 @@ msgstr "" " Notizen in diese App exportiere. Wo wird der CSV erstellt?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5254,7 +5262,7 @@ msgstr "" "Beispiel Eingabeaufforderung. Geben Sie den absoluten Pfad zum " "Anwendungsordner an oder {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5265,17 +5273,17 @@ msgstr "" "Einstiegspunkten, Modulen und Prozessgrenzen. Ihr Agent verwendet diese " "Karte, um die Untersuchung auf die Exportfunktion einzugrenzen." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Verfolgen Sie den Exportcode" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Die Seite ruft eine kleine API auf" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5286,7 +5294,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5298,7 +5306,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5309,7 +5317,7 @@ msgstr "" " die Notizen und der Hauptprozess schreibt {ph1} in den Download-Ordner des " "Benutzers." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5318,7 +5326,7 @@ msgstr "" "Aufgenommen von REA 4.1.0 im unten stehenden herunterladbaren Beispiel. " "Quellorte begleiten die API-, Kanal- und Handler-Ergebnisse." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Analysieren Sie das Beispiel selbst" @@ -5326,25 +5334,25 @@ msgstr "Analysieren Sie das Beispiel selbst" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Beispiel-ZIP herunterladen{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Durchsuchen Sie die sechs Quelldateien" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Statische Anwendungsanalyse" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5355,7 +5363,7 @@ msgstr "" "einen IPC-Kanal und einen passenden Handler in finden {ph0}. Quellstandorte " "sind in {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5366,13 +5374,13 @@ msgstr "" "oder ASAR-Pfad. Ein Agent kann mit den Feature-Tracing-Tools von REA einer " "Literalzeichenfolge, einem API-Namen oder einem IPC-Kanal folgen." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Überprüfen Sie den CSV-Schreiber" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5382,7 +5390,7 @@ msgstr "" "Folgen {ph0} zu seinem Handler. Welche Eingänge erreichen den CSV Writer und" " was passiert, wenn das Schreiben der Datei fehlschlägt?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5398,7 +5406,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5412,7 +5420,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5426,7 +5434,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5452,32 +5460,32 @@ msgstr "" "IPC-Handler mit REA. Enthält herunterladbare Beispieldateien und ein " "verifiziertes Analyseergebnis." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "Modell: JavaScript und Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Beispiel-Eingabeaufforderung kopieren" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Statische Anwendungsanalyse kopieren" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -5486,7 +5494,7 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5495,7 +5503,7 @@ msgstr "" "Programmen" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." @@ -5503,7 +5511,7 @@ msgstr "" "Wiederherstellen von DX-BallS{ph0}berechnung der linken / rechten " "Klangposition." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5512,14 +5520,14 @@ msgstr "" "Überprüfen Sie die Originalanweisungen, identifizieren Sie die Eingabe und " "die Konstanten und überprüfen Sie dann das wiederhergestellte C." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "In diesem Handbuch" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5527,7 +5535,7 @@ msgstr "{ph0}Beispiel{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5535,7 +5543,7 @@ msgstr "{ph0}Fragen Sie Ihren Agenten{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5543,7 +5551,7 @@ msgstr "{ph0}Lesen Sie die REA-Ergebnisse{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5551,18 +5559,18 @@ msgstr "{ph0}Wiederherstellen und überprüfen{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Verwenden Sie Ihre eigene Binärdatei{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Berechnen Sie die linke / rechte Stereoklangpositionierung" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5575,7 +5583,7 @@ msgstr "" # Reviewed for grammatical function-call terminology. #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5587,7 +5595,7 @@ msgstr "" "{ph1}. REA liefert auch die Maschinenbefehle und die aufrufenden Funktionen." " Damit kann der Agent die fehlenden Rechenschritte untersuchen." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Neu bei diesen Bedingungen?" @@ -5596,7 +5604,7 @@ msgstr "Neu bei diesen Bedingungen?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5608,7 +5616,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5622,7 +5630,7 @@ msgstr "" # Reviewed for grammatical function-call terminology. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5635,7 +5643,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5647,7 +5655,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5657,7 +5665,7 @@ msgstr "" "{ph0}Konstant:{ph1} feste Zahlen, die im Programm gespeichert, als Rohbytes " "gelesen und dekodiert werden." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Drei Beweise, eine Rechnung" @@ -5668,7 +5676,7 @@ msgstr "Drei Beweise, eine Rechnung" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5687,7 +5695,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5706,7 +5714,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5717,7 +5725,7 @@ msgstr "" "Konstanten{ph3}{ph4}Referenzierte Bytes dekodieren zu {ph5}, {ph6} und einen" " Skalenwert.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5726,7 +5734,7 @@ msgstr "" "REA liefert die Anweisungen, die Funktionsaufrufbeziehung und die Bytes. Der" " Agent interpretiert sie zusammen." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Fragen Sie nach dem Verhalten" @@ -5735,7 +5743,7 @@ msgstr "Fragen Sie nach dem Verhalten" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5746,19 +5754,19 @@ msgstr "" "Tools zur Analyse von Maschinencode-Programmen{ph3}, geben Sie die lokale " "ausführbare Datei und eine Frage an:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Welches Analysetool soll ich verwenden?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA benötigt eines davon, um native Programme zu lesen:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5773,7 +5781,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5786,7 +5794,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5797,7 +5805,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5813,14 +5821,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Kopieren" @@ -5831,7 +5839,7 @@ msgstr "Kopieren" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5842,7 +5850,7 @@ msgstr "" "Stereoklangpositionierung berechnet. Erklären Sie die Berechnung und zeigen " "Sie den Code.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5854,7 +5862,7 @@ msgstr "" "Verwenden Sie also Ihre eigene Kopie oder stellen Sie die gleiche Frage zu " "einem anderen kleinen Windows-Programm, das Sie haben." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Wie erhalte ich den vollständigen Pfad einer Datei?" @@ -5863,7 +5871,7 @@ msgstr "Wie erhalte ich den vollständigen Pfad einer Datei?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5879,7 +5887,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5892,7 +5900,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5902,17 +5910,17 @@ msgstr "" "{ph0}Jedes System:{ph1} ziehen Sie die Datei in ein Terminalfenster und ihr " "Pfad wird angezeigt." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Lesen Sie die REA-Ergebnisse" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Lesen Sie die Eingabe" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5923,14 +5931,14 @@ msgstr "" "Ansicht fehlt." # Reviewed for grammatical function-call terminology. -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Die aufrufende Funktion verfolgen" # Reviewed for grammatical function-call terminology. #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5941,12 +5949,12 @@ msgstr "" "multipliziert sie die Gitterkoordinate mit 30 und addiert {ph0} (20). So " "ergibt sich die Bildschirmposition des Ziegels." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Lesen Sie die referenzierten Konstanten" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5956,12 +5964,12 @@ msgstr "" "tatsächlichen Werte; Die Befehlsreihenfolge teilt dem Agenten mit, wie sie " "verwendet werden." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Schreiben und überprüfen Sie die wiederhergestellte Funktion" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5972,7 +5980,7 @@ msgstr "" " der Ganzzahlumwandlung auf -500, 0 und 500 abgebildet. Bei der Berechnung " "wird die Bildschirmmitte in die Mitte des Stereofelds gesetzt." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5985,7 +5993,7 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" @@ -5993,14 +6001,14 @@ msgstr "" "{ph0}Sehen Sie sich die vollständige Untersuchung und den Assembly-to-C-" "Vergleich an{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Probieren Sie es mit Ihrer eigenen Binärdatei aus" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -6015,7 +6023,7 @@ msgstr "" " “Wie wird diese Datei analysiert?\" oder \"Welche Funktion behandelt diese " "Menüaktion?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -6024,13 +6032,13 @@ msgstr "" "Wenn Sie bereits einen Funktionsnamen oder eine Adresse kennen, können Sie " "diese vom Terminal abfragen. Für eine konfigurierte Ghidra-Installation:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Funktionsanalyse" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -6045,7 +6053,7 @@ msgstr "" "verwenden die importierte Binärdatei wieder, während diese Sitzung geöffnet " "ist." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -6070,50 +6078,50 @@ msgstr "" "Anweisungen, folgen Sie einem Aufrufer, lesen Sie Konstanten und überprüfen " "Sie rekonstruiertes C." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Analyse von Maschinencode-Programmen" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Beispiel-Eingabeaufforderung kopieren" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Analyse der Kopierfunktion" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Einrichten von REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6121,7 +6129,7 @@ msgstr "{ph0}Einrichten von REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6129,7 +6137,7 @@ msgstr "{ph0}Was ist RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6137,7 +6145,7 @@ msgstr "{ph0}Wie REA hilft{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6145,7 +6153,7 @@ msgstr "{ph0}Dinosaurier-Spiel{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6153,7 +6161,7 @@ msgstr "{ph0}Rechner{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6161,7 +6169,7 @@ msgstr "{ph0}Probieren Sie REA aus {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6169,7 +6177,7 @@ msgstr "{ph0}Tiefer einsteigen{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6177,25 +6185,25 @@ msgstr "{ph0}Hilfe & Feedback{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Gemeinschaft{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Reverse Engineering mit Ihrem Codierungsagenten" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Finde heraus,{ph0}wie Software funktioniert." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6206,7 +6214,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6214,13 +6222,13 @@ msgstr "Kennen Sie RE schon? {ph0}Zu den Analysehandbüchern springen →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Willst du tiefer gehen? {ph0}Lesen Sie den Blog →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Kopiere diesen Prompt in deinen Coding-Agent:" @@ -6233,40 +6241,40 @@ msgstr "Kopiere diesen Prompt in deinen Coding-Agent:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Kopieren" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Oder führe diesen Befehl im Terminal aus:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "" "Prüfe und bestätige die geplanten Änderungen. Starte danach deinen Agent " "neu." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Was ist Reverse Engineering?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6281,7 +6289,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6293,7 +6301,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6301,7 +6309,7 @@ msgstr "Vor REA · Du untersuchst es {ph0}selbst{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6309,7 +6317,7 @@ msgstr "{ph0}01{ph1} Zweige dekodieren" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6317,7 +6325,7 @@ msgstr "{ph0}02{ph1} Anrufe verfolgen" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6327,20 +6335,20 @@ msgstr "{ph0}03{ph1} Wiederherstellen der Regel" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Original x64 * ausgewählte Anleitung{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * Welche Branche?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6350,29 +6358,29 @@ msgstr "" "“{ph0}0x5b? 0x5 Grad?{ph1} Zwei Sprünge an die gleiche Stelle. Welche " "Betreiber sind das?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Suchen Sie nach den Befehls-IDs und beschriften Sie den Zweig." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Teilen ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Multiplizieren ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Was machen die aufgerufenen Funktionen?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6382,26 +6390,26 @@ msgstr "" "“100 ist klar. Die Anrufe sind nur Adressen. {ph0}Welcher teilt sich? " "Welcher Wert geht ein?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "" "Überprüfen Sie die Hilfsfunktionen und verfolgen Sie die gespeicherten " "Werte." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Teilen" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 · Was ist die Regel?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6411,19 +6419,19 @@ msgstr "" "“Dieser Pfad multipliziert sich mit der anderen Eingabe. So {ph0}10% " "bedeutet 10% von 200{ph1} nach +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Benennen Sie die Operanden und überprüfen Sie beide Operatorpfade." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Anschauliche Argumentation von Experten" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6435,20 +6443,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Mit REA · Du fragst {ph0}deinen Agent{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Ein einziger Prompt." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6462,7 +6470,7 @@ msgstr "Frag deinen Agent {ph0}in ganz normalen Worten.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" @@ -6470,43 +6478,43 @@ msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Beispiel Eingabeaufforderung * " "Rechner" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Beispielantwort * basierend auf den Ergebnissen" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "Nach + nimmt die% -Taste {ph0}ein Prozentsatz der ersten Zahl.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA liefert" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Die Anweisungen des Handlers, dekompilierter Code und Aufrufe." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Dein Agent erklärt" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Welcher Zweig gilt, was er berechnet und wie er neu erstellt wird." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6519,7 +6527,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6530,37 +6538,37 @@ msgstr "" " Spiels, kehre dann zum Taschenrechner zurück und baue die%-Schaltfläche neu" " auf." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Beispiel 01 * Dinosaurier-Spiel von Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Warum wird der Dinosaurier schneller?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Ziel" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Baue das Spiel mit neu auf {ph0}einstellbare Geschwindigkeit.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Warum es zurückentwickeln?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6571,51 +6579,51 @@ msgstr "" "laufenden Spiel{ph1}: wie schnell es beginnt, wie stark es zunimmt und wann " "es aufhört." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Den Nachbau spielen" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Spielen" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Springen ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Neustart" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Geschwindigkeit" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Verwenden Sie die wiederhergestellte Beschleunigungsregel" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "" "Ursprüngliche Regel: Beginnen Sie bei 6 und erhöhen Sie sich dann in " "Richtung 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Bewegen Sie den Schieberegler, um Ihre eigene Geschwindigkeit einzustellen. " "Leertaste oder Sprung löscht einen Kaktus." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6624,14 +6632,14 @@ msgstr "" "Aktivieren Sie JavaScript, um die Rekonstruktion abzuspielen. Der Code und " "die obige Erklärung bleiben lesbar." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA hat zurückgegeben" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6650,7 +6658,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6663,7 +6671,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6678,7 +6686,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6692,7 +6700,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6702,12 +6710,12 @@ msgstr "" "{ph0}Beginnen Sie bei 6.{ph1} Hinzufügen {ph2}0.001{ph3} jedes Update ohne " "Kollision, während die Geschwindigkeit darunter liegt {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Öffnen Sie das Geschwindigkeitslabor →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Was jeder Teil tut" @@ -6718,7 +6726,7 @@ msgstr "Was jeder Teil tut" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6735,7 +6743,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6752,7 +6760,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6763,7 +6771,7 @@ msgstr "" "Sie{ph3}{ph4}Probieren Sie die ursprüngliche Beschleunigung aus und wählen " "Sie dann Ihr eigenes Tempo.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "" @@ -6771,7 +6779,7 @@ msgstr "" "Analyse an" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6782,7 +6790,7 @@ msgstr "" "Verbindung und gab das geladene zurück {ph0}, einschließlich seiner Quelle " "und Verdauung." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6797,7 +6805,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6814,7 +6822,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6832,7 +6840,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6841,19 +6849,19 @@ msgstr "" "{ph0}Geprüfter Geschwindigkeitscode{ph1} · {ph2} Chromium Autoren * BSD-" "Lizenz{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Beispiel 02 * Windows Rechner" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Die %-Taste des Rechners nachbauen." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6864,7 +6872,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6875,29 +6883,29 @@ msgstr "" "×.{ph1} Wir überprüfen die installierte App, um herauszufinden, auf welche " "Zahl der Prozentsatz angewendet wird." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Probieren Sie die Berechnung aus" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Zurücksetzen" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% von 200 = 20. Dann ist 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Interaktive Darstellung der geprüften Prozentregel." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6910,7 +6918,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6924,7 +6932,7 @@ msgstr "Für dieses Beispiel, {ph0} und {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6940,7 +6948,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6953,7 +6961,7 @@ msgstr "" "erstellen Sie dann einen kleinen Taschenrechner, der beide " "verwendet.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Mit +" @@ -6961,13 +6969,13 @@ msgstr "Mit +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Nimm 10% der ersten Zahl.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Mit ×" @@ -6975,13 +6983,13 @@ msgstr "Mit ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Verwandle 10% in 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Von der installierten App zu einer funktionierenden% -Schaltfläche" @@ -6993,7 +7001,7 @@ msgstr "Von der installierten App zu einer funktionierenden% -Schaltfläche" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7011,7 +7019,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7023,12 +7031,12 @@ msgstr "" " die Regeln{ph3}{ph4}Überprüfen Sie den Zweig mit der Quelle von Microsoft " "und versuchen Sie dann oben + und ×.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Sehen Sie sich den echten Code an und wie die Antwort überprüft wurde" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -7049,7 +7057,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7059,17 +7067,17 @@ msgstr "" "{ph0}Prozentuale Umsetzung{ph1} · {ph2}Testfälle von Microsoft{ph3} · " "{ph4}Anleitung zur nativen Einrichtung{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Ihre erste Untersuchung" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Probieren Sie REA mit einer kleinen App aus." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -7078,12 +7086,12 @@ msgstr "" "Laden Sie unser Notizbeispiel herunter, verfolgen Sie den Export von CSV und" " überprüfen Sie eine geänderte Eingabe." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Probieren Sie das geführte Beispiel aus" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Möchtest du tiefer einsteigen?" @@ -7092,7 +7100,7 @@ msgstr "Möchtest du tiefer einsteigen?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7112,7 +7120,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" @@ -7120,7 +7128,7 @@ msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Beispiel Eingabeaufforderung * " "Website" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Ja, das hier." @@ -7133,7 +7141,7 @@ msgstr "Ja, das hier." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7148,7 +7156,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7162,23 +7170,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Siehe die Fallstudie DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Wählen Sie für Einrichtungs- und Analyseschritte Ihr Ziel aus:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Maschinencode-Programme" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7187,17 +7195,17 @@ msgstr "" "Überprüfen Sie Funktionen, Zeichenfolgen, Referenzen und " "Funktionsaufrufbeziehungen in ausführbaren Dateien und Bibliotheken." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Handbuch zur Analyse von Maschinencode-Programmen" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "Modell: JavaScript und Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7206,17 +7214,17 @@ msgstr "" "Ordnen Sie Module, Routen, IPC und native Abhängigkeiten aus einem " "Anwendungsordner oder einem ASAR-Archiv zu." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Anwendungs-Workflows" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Browser- & Laufzeit-Aktivität" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7225,12 +7233,12 @@ msgstr "" "Erfassen Sie ausgewählte Browser- oder Prozessaktivitäten und vergleichen " "Sie dann die Ergebnisse über Läufe hinweg." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Anleitung zur Browserbeobachtung" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Noch Fragen?" @@ -7241,7 +7249,7 @@ msgstr "Noch Fragen?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7252,12 +7260,12 @@ msgstr "" "oder {ph4}öffnen Sie eine GitHub-Ausgabe{ph5} für Fehler und " "Funktionswünsche." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Zur Community" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7281,27 +7289,27 @@ msgstr "" "Codierungsagenten. Befolgen Sie klare Anleitungen und probieren Sie " "interaktive Beispiele mit REA aus." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Installationsaufforderung für REA kopieren" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Setup-Befehl kopieren" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Befolgen Sie die manuelle Taschenrechneranalyse" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Kopierrechner Prozentfrage" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7310,37 +7318,37 @@ msgstr "" "Dinosaurier-Minispiel. Verwenden Sie die Sprungtaste oder drücken Sie die " "Leertaste, während das Spiel fokussiert ist." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Aufforderung zur Dinosaurieranalyse kopieren" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Wählen Sie die Berechnung" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Aufforderung zur Analyse des Kopierrechners" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Aufforderung zum Kopieren des Website-Projekts" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Aufforderung zur Wiederherstellung des Spiels kopieren" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -7349,25 +7357,25 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Startseite{ph1} / {ph2}Präsentieren{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Fallstudie * Aegis Authentifikator" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Wie funktioniert ein Authentifikator{ph0}einen Login-Code generieren?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7377,17 +7385,17 @@ msgstr "" "die Berechnung in einem Android APK zu finden, und erstellen Sie sie dann " "mit einer Uhr neu, die Sie steuern können." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * Offizielle Veröffentlichung APK · 6,9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Sehen Sie sich Aegis auf GitHub an" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Von einem APK zu einem Code, den Sie reproduzieren können" @@ -7398,7 +7406,7 @@ msgstr "Von einem APK zu einem Code, den Sie reproduzieren können" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7416,7 +7424,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7434,7 +7442,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7446,14 +7454,14 @@ msgstr "" " Code.{ph3}{ph4}Eine neue Browserdemo reproduziert die Regel und vergleicht " "sie mit öffentlichen Referenzfällen.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "In dieser Fallstudie" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7461,7 +7469,7 @@ msgstr "{ph0}Fragen Sie Ihren Agenten{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7469,7 +7477,7 @@ msgstr "{ph0}Probieren Sie den Codegenerator aus{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7477,7 +7485,7 @@ msgstr "{ph0}Finden Sie den Code mit REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7485,7 +7493,7 @@ msgstr "{ph0}Lesen Sie die Berechnung{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7493,20 +7501,20 @@ msgstr "{ph0}Überprüfen Sie die Rekonstruktion{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Überprüfen Sie den APK selbst{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Fragen Sie Ihren Agenten" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7524,21 +7532,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Kopieren" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7549,14 +7557,14 @@ msgstr "" "Android-Analyse von REA. {ph0}Holen Sie sich das APK und das Analyse-Setup " "↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Probieren Sie den Codegenerator aus" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7568,33 +7576,33 @@ msgstr "" "die Blocknummer mit dem Kontoschlüssel, um einen Code zu generieren. " "Derselbe Schlüssel und derselbe Block erzeugen denselben Code." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Bewegen Sie die Uhr über 60 Sekunden" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Zeit" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "Sekundenschnelle" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Unsere verstellbare Beispieluhr" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30-sekunden-Block" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Block" @@ -7603,35 +7611,35 @@ msgstr "Block" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 sekunden{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Generierter Code" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Kontoschlüssel + Sperre → sechs Ziffern" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Beispielzeit in Sekunden" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 sekunden" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 sekunden" @@ -7640,7 +7648,7 @@ msgstr "60 sekunden" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7652,7 +7660,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7662,7 +7670,7 @@ msgstr "" "Der Schlüssel ist fest, öffentlich {ph0}RFC 6238-Testdaten{ph1}. Die Demo " "implementiert die vom APK wiederhergestellte Berechnung." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7671,18 +7679,18 @@ msgstr "" "Das Diagramm zeigt das Ergebnis bei 59 Sekunden. Aktivieren Sie JavaScript, " "um die Uhr zu ändern." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Finden Sie den Code mit REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Grenzen Sie den APK auf drei Klassen ein" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7693,14 +7701,14 @@ msgstr "" "Fortschrittsbalken und importierte Konten. TOTP bedeutet ein zeitbasiertes " "Einmalpasswort." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Verbinden Sie den Generator mit dem Display der App" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7711,7 +7719,7 @@ msgstr "" "Basismethode. Inspizieren {ph0} zeigt dann das Display an, das anruft {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7721,14 +7729,14 @@ msgstr "" "Anfragen zeigen einen verkürzten Eingabepfad. Ergebnisklassennamen lassen " "das Gemeinsame weg {ph0} Präfix." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Lesen Sie die Berechnung" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7743,7 +7751,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7751,7 +7759,7 @@ msgstr "{ph0}01{ph1} Zeitblock" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7759,7 +7767,7 @@ msgstr "{ph0}02{ph1} Schlüssel + Block" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7767,7 +7775,7 @@ msgstr "{ph0}03{ph1} Sechs Ziffern" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7779,7 +7787,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7793,7 +7801,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7808,7 +7816,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7819,7 +7827,7 @@ msgstr "" "rechte Feld ist eine erläuternde Zusammenfassung. {ph0} Der Code von Aegis " "ist GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Im Inneren des Generators" @@ -7828,7 +7836,7 @@ msgstr "Im Inneren des Generators" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7839,7 +7847,7 @@ msgstr "" "und gibt diesen Körper zurück; Die ursprüngliche Quelle ruft den Helfer auf " "{ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7856,20 +7864,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Vergleichen Sie mit der passenden Release-Quelle{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Überprüfen Sie die Rekonstruktion" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7882,29 +7890,29 @@ msgstr "" "unabhängigen Rekonstruktion auf {ph0}133 testfälle{ph1}, einschließlich " "Zeitblockgrenzen und Codes, die mit Null beginnen." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Beispiel zeit" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Sechsstelliger Code" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 sekunden" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 sekunden" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7915,17 +7923,17 @@ msgstr "" "SHA-1-Referenzfällen in {ph0}RFC6238{ph1}. Überprüfen Sie die Browser-" "Implementierung gegen sie:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Referenzprüfungen durchführen" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Lesen Sie die Berechnung der Demo" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7934,7 +7942,7 @@ msgstr "" "Die Referenzfälle verwenden acht Ziffern. Die Überprüfung überprüft auch " "ihre sechsstelligen Ergebnisse." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7943,14 +7951,14 @@ msgstr "" "Die Überprüfung führt extrahierte Java-Methoden und die neue Demo aus. Das " "Android APK wurde statisch inspiziert." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Überprüfen Sie den APK selbst" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7963,7 +7971,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7973,18 +7981,18 @@ msgstr "" "Android Analysis benötigt ein vollständiges JDK 17 oder höher. Wählen Sie es" " mit {ph0} oder {ph1}. In diesem Fall wurde JDK 21 verwendet." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Zeigen Sie mit REA auf die Providerdatei und überprüfen Sie den APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "MODELL: macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7997,7 +8005,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -8007,7 +8015,7 @@ msgstr "" "Eine nächste Frage: {ph0}was passiert, wenn ein Konto acht Ziffern oder ein " "anderes Zeitintervall verwendet?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Hauptquellen" @@ -8023,7 +8031,7 @@ msgstr "Hauptquellen" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -8037,13 +8045,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}Referenzfälle zu RFC 6238{ph1} · {ph2}Demo-Testdaten{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -8069,37 +8077,37 @@ msgstr "" "Login-Code-Berechnung wieder her und versuchen Sie eine Rekonstruktion mit " "einer einstellbaren Uhr." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK Fallstudie" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Beispiel-Eingabeaufforderung Aegis kopieren" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Folgen Sie der Login-Code-Berechnung" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Inspektionsbefehl APK kopieren" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -8108,26 +8116,26 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Startseite{ph1} / {ph2}Präsentieren{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Fallstudie * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Finde die Flagge in{ph0}eine CTF-Binärdatei." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8138,17 +8146,17 @@ msgstr "" "Regeln in Gleichungen umzuwandeln und eine Eingabe zu finden, die das " "ursprüngliche Programm drucken lässt {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "maskierte Quadrate Flaggenprüfer · Einfach · Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Sehen Sie sich die ursprüngliche Herausforderung an" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Von einer binären zu einer geprüften Antwort" @@ -8159,7 +8167,7 @@ msgstr "Von einer binären zu einer geprüften Antwort" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8177,7 +8185,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8195,7 +8203,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8207,7 +8215,7 @@ msgstr "" "Korrekt!{ph3}{ph4}Ein Python-Skript löst die Gleichungen. REA erfasst das " "ursprüngliche Programm, das das Ergebnis akzeptiert.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." @@ -8215,14 +8223,14 @@ msgstr "" "Die Herausforderung stammt von Joseph und wurde im offiziellen Repository " "von DownUnderCTF veröffentlicht." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "In dieser Fallstudie" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8230,7 +8238,7 @@ msgstr "{ph0}Finden Sie den Prüfcode{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8238,7 +8246,7 @@ msgstr "{ph0}Lesen Sie eine Maske{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8246,7 +8254,7 @@ msgstr "{ph0}Assemblierung zu lesbarem Code{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8254,7 +8262,7 @@ msgstr "{ph0}Löse die Gleichungen{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8262,20 +8270,20 @@ msgstr "{ph0}Überprüfen Sie die Antwort{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Probieren Sie es selbst aus{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Finden Sie den Prüfcode" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8294,17 +8302,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Kopieren" @@ -8315,7 +8323,7 @@ msgstr "Kopieren" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8327,7 +8335,7 @@ msgstr "" " Flag zu finden. Erklären Sie, wie die Prüfungen funktionieren, und " "überprüfen Sie dann die Antwort mit dem Originalprogramm.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8337,12 +8345,12 @@ msgstr "" "Herausforderung lokal verfügbar ist und eine Analyse des Maschinencode-" "Programmanbieters verbunden ist." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Folgen Sie der Eingabeaufforderung zu ihrer Funktion" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8351,14 +8359,14 @@ msgstr "" "Die Referenz gibt dem Agenten einen Ort zum Untersuchen, obwohl die " "ursprünglichen Funktionsnamen der ausführbaren Datei entfernt wurden." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Lesen Sie den Checker und seine beiden Helfer" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8371,7 +8379,7 @@ msgstr "" " gespeicherten Nummer. Seiner {ph0}-byte-Schritte über {ph1} bytes ergeben " "26 Masken." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8381,12 +8389,12 @@ msgstr "" "Zielpfad wird für die Anzeige gekürzt; Adressen beziehen sich auf das " "importierte Bild von REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Ein Häkchen zeigt einen Charakter" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8400,14 +8408,14 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "" "Die siebte Prüfung wählt nur eine Position aus. {ph0}Offene Figur{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Lesen Sie die Maske und ihr Ziel aus der Binärdatei" @@ -8416,7 +8424,7 @@ msgstr "Lesen Sie die Maske und ihr Ziel aus der Binärdatei" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8429,12 +8437,12 @@ msgstr "" "Zusammen sagen diese Bytes dem Agenten, dass {ph2}, also ist dieser " "Charakter {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Von der Anleitung zum lesbaren Scheck" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8445,7 +8453,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8453,7 +8461,7 @@ msgstr "{ph0}01{ph1} Beginnen" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8461,7 +8469,7 @@ msgstr "{ph0}02{ph1} Wählen" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8469,7 +8477,7 @@ msgstr "{ph0}03{ph1} Hinzufügen" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8477,18 +8485,18 @@ msgstr "{ph0}04{ph1} Voraus" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Vergleichen" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * ausgewählte Originalanleitung" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Lesbare C · One-Check-Zusammenfassung" @@ -8496,7 +8504,7 @@ msgstr "Lesbare C · One-Check-Zusammenfassung" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8504,7 +8512,7 @@ msgstr "{ph0}01 * Bei Null beginnen.{ph1} {ph2} enthält die laufende Summe." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8516,7 +8524,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8528,7 +8536,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8543,7 +8551,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8554,7 +8562,7 @@ msgstr "" "Funktion erhält die Summe in {ph2}. Bei einer Abweichung springt sie zu " "{ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8564,12 +8572,12 @@ msgstr "" "eine erklärende Zusammenfassung mit beschreibenden Namen und einer " "abgeflachten 36-Zellen-Schleife." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Löse die 26 Gleichungen" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8581,13 +8589,13 @@ msgstr "" "überlappenden Auswahlen ergeben Gleichungen, die ein kleines Python-Skript " "zusammen lösen kann." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * Löser Auszug" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8601,19 +8609,19 @@ msgstr "" "mit Buchstaben, Ziffern, Unterstrichen und geschweiften Klammern. Der " "vollständige Download enthält alle 26 Masken und Ziele." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Laden Sie den vollständigen Solver herunter" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Überprüfen Sie die Antwort mit dem Originalprogramm" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8626,47 +8634,47 @@ msgstr "" " {ph0} zu {ph1} macht die erste Summe 1440 anstelle von 1441, und das " "Programm lehnt sie ab." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Eingang" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Beobachteter Output" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Ausstiegscode" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Flagge des Lösers" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Ein Charakter wurde geändert" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Zeigen Sie das wiederhergestellte Flag und die erfasste Ausgabe an" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * ursprüngliche Programmausgabe" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Flagge kopieren" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8676,12 +8684,12 @@ msgstr "" " Challenge-Metadaten der Organisatoren überein, das nach dem Lösen der " "Binärdatei überprüft wurde." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Quelle, Zielidentität und Analysedetails" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8692,7 +8700,7 @@ msgstr "" "mit Ghidra 12.1.4 auf Linux x64. Die Binärdatei ist eine gestrippte x86-64 " "ELF, 15.248 Byte." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8715,7 +8723,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8725,12 +8733,12 @@ msgstr "" "{ph0}Vergleiche mit der Quelle des Veranstalters{ph1} · {ph2}Metadaten und " "Flag abfragen{ph3} · {ph4} REA Hinweise zum Nachweis{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Probieren Sie es selbst aus" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8740,13 +8748,13 @@ msgstr "" "herunter. Verwenden Sie die obige Eingabeaufforderung, um mit Ihrem Agenten " "Nachforschungen anzustellen, oder führen Sie das mitgelieferte Skript aus." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * lösen und ausführen" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8759,7 +8767,7 @@ msgstr "" "Zum Ausführen der ursprünglichen ausführbaren Datei ist Linux x86-64 " "erforderlich." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Richten Sie REA mit Ihrem Codierungsagenten ein" @@ -8781,27 +8789,27 @@ msgstr "" "Masken und vergleichen Sie ein wiederhergestelltes Flag mit dem " "Originalprogramm." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTF flag-checker Fallstudie" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "CTF-Beispiel-Eingabeaufforderung kopieren" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "CTF-Maskengleichung; auf kleineren Bildschirmen horizontal scrollen" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8812,42 +8820,42 @@ msgstr "" "überspringt dann 14. Nur diese Zelle trägt zur Summe bei. Der erforderliche " "Zeichencode ist 55, was bedeutet, dass das Zeichen 7 ist." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Befolgen Sie den CTF-Check" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "CTF-Baugruppe kopieren" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Kopierlesbare CTF-Prüfung" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Auszug aus dem CTF-Löser kopieren" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Wiederhergestelltes Flag kopieren" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Kopieren von CTF-Solver-Befehlen" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -8856,25 +8864,25 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Startseite{ph1} / {ph2}Präsentieren{ph3} Modell: DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Fallstudie * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Umbau DX-Ball {ph0}von seiner ausführbaren Datei." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8883,14 +8891,14 @@ msgstr "" "Das Ziel ist eine wartbare C-Version des 1996er Windows-Spiels. REA hilft " "dem Agenten, das Original Funktion für Funktion zu inspizieren." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Modell: Windows i386 · C · REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8902,14 +8910,14 @@ msgstr "" "Aufrufer und Datenlesungen; Das Rekonstruktionsprojekt implementiert und " "testet das Ergebnis. {ph0}Offene Figur{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "In dieser Fallstudie" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8917,7 +8925,7 @@ msgstr "{ph0}Projekt{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8925,7 +8933,7 @@ msgstr "{ph0}Ton schwenken{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8933,23 +8941,23 @@ msgstr "{ph0}Überprüfung des Ergebnisses{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Setzen Sie die Arbeit fort{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "beibehaltene C-Funktionen" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "vergleiche mit Originalcode" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "funktionen mit übereinstimmenden kompilierten Bytes" @@ -8960,7 +8968,7 @@ msgstr "funktionen mit übereinstimmenden kompilierten Bytes" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8970,12 +8978,12 @@ msgstr "" "Projekt-Checkpoint: 7. Oktober 2026. {ph0}Fortschrittsbuch{ph1} · " "{ph2}Testabdeckung{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Das Projekt bisher" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8990,12 +8998,12 @@ msgstr "" " spielbaren Spiel wird mit Ball- und Paddelphysik, Power-Up-Handling und " "Windows-Integration fortgesetzt." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Ermittlung der Berechnung der linken / rechten Schallposition" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -9014,17 +9022,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Kopieren" @@ -9035,7 +9043,7 @@ msgstr "Kopieren" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9046,7 +9054,7 @@ msgstr "" "Stereoklangpositionierung berechnet. Erklären Sie die Berechnung und zeigen " "Sie den Code.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -9057,7 +9065,7 @@ msgstr "" "ausführbare Datei verfügbar ist. Die folgende Untersuchung zeigt die REA-" "Abfragen und Beweise hinter der Antwort." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -9072,7 +9080,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9086,12 +9094,12 @@ msgstr "" "Gleitkommaoperationen. Diese Diskrepanz gab dem Agenten einen konkreten " "Grund, weiter zu ermitteln." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "Die erste Decompiler-Ansicht" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -9101,18 +9109,18 @@ msgstr "" "Anweisungen lesen, werden die Eingabe und die Berechnung angezeigt, die " "diesen Aufruf einspeisen." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Drei Fragen beantwortet durch REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Stellen Sie die fehlende Eingabe wieder her" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9124,7 +9132,7 @@ msgstr "" "Dekompilierungsansicht fehlt." # Reviewed for grammatical function-call terminology. -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Die aufrufende Funktion erklärt die Eingabe" @@ -9132,7 +9140,7 @@ msgstr "Die aufrufende Funktion erklärt die Eingabe" # Reviewed for grammatical function-call terminology. #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9143,12 +9151,12 @@ msgstr "" "Aufruf multipliziert sie {ph0} mit 30 und addiert 20. Das ergibt die " "Bildschirmkoordinate des Ziegels, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Lesen Sie die Werte hinter den Speicheradressen" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9158,12 +9166,12 @@ msgstr "" " anfängliche Schwenkskala fest. Der Agent hat jetzt die Werte, die für den " "C-Ausdruck benötigt werden." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Von den Erkenntnissen von REA zu C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9174,7 +9182,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9182,7 +9190,7 @@ msgstr "{ph0}01{ph1} Eingang" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9190,7 +9198,7 @@ msgstr "{ph0}02{ph1} Multiplizieren" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9198,7 +9206,7 @@ msgstr "{ph0}03{ph1} Subtrahieren" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9206,18 +9214,18 @@ msgstr "{ph0}04{ph1} Skala" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Zurückgeben" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Original x86 * Auszug" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Rekonstruiertes C" @@ -9227,7 +9235,7 @@ msgstr "Rekonstruiertes C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9247,7 +9255,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9264,7 +9272,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9282,7 +9290,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9299,7 +9307,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9312,7 +9320,7 @@ msgstr "" " Ergebnis auf {ph4}; original-x86-Vergleiche überprüfen den zurückgegebenen " "Wert." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9323,24 +9331,24 @@ msgstr "" "aus. Die vollständige Liste unten enthält auch die dazwischenliegenden " "Speicher sowie die Einrichtung und Bereinigung von Funktionen." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Vollständige Versammlung und unterstützende Beweise" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA Ergebnis · 0x406400–0x40643e" # Reviewed for grammatical function-call terminology. -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Was die aufrufende Funktion übergibt" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9350,54 +9358,54 @@ msgstr "" "Die Brick-Hit-Funktion bei {ph0} skaliert die Kachelkoordinate um 30, " "addiert 20 und schiebt sie dann vor den Anruf:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Was die Daten lesen, stellen Sie fest" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA Byte liest, dekodiert als Little-Endian-Doubles" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Anschrift" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Wert" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Verwendet für" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Erste Multiplikation" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Subtraktion" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} zunächst" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Gespeicherte Pfannenwaage" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9413,7 +9421,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9423,12 +9431,12 @@ msgstr "" "{ph0}Gepflegte Quelle{ph1} · {ph2}Ermittlungsnotizen und " "Beweisreferenzen{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Überprüfen der wiederhergestellten Funktion" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9438,12 +9446,12 @@ msgstr "" "stimmen mit dem Original überein und ihre kompilierten Bytes stimmen mit der" " ausführbaren Datei überein." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 Verhaltensfälle" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9454,12 +9462,12 @@ msgstr "" "Rückgabewert mit dem gepflegten C. Sie decken jede ganzzahlige Position von " "0 bis 640 auf fünf Pan-Skalen ab: 0, 0,5, 1, 20 und -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 übereinstimmende Bytes" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9471,7 +9479,7 @@ msgstr "" "die überprüften Verschiebungen angewendet und die referenzierten Konstanten " "überprüft wurden." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9487,18 +9495,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Lesen Sie die Compiler-Wiedergabedetails{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Setzen Sie die Untersuchung fort" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9510,7 +9518,7 @@ msgstr "" "relevanten Funktionen, stellen Sie ihren Zustand und ihre Abhängigkeiten " "wieder her und vergleichen Sie dann die Implementierung mit dem Original." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9520,7 +9528,7 @@ msgstr "" "Einrichtungsanweisungen des DX-Ball-Projekts und geben Sie das passende " "Originalziel an. Dann lauf:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "In der Kasse des DX-Ball" @@ -9529,7 +9537,7 @@ msgstr "In der Kasse des DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9543,7 +9551,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9559,7 +9567,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9583,7 +9591,7 @@ msgstr "" "Folgen Sie einer DX-Ball-Rekonstruktion von der Binäranalyse über REA zu " "gepflegten C-, Original-x86-Tests und passenden kompilierten Funktionsbytes." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9591,7 +9599,7 @@ msgstr "" "DX-Ball Sound-Pan-Untersuchung; auf kleineren Bildschirmen horizontal " "scrollen" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9607,70 +9615,70 @@ msgstr "" "ursprüngliche x86 und durch VC4.0-Compiler-Wiedergabe mit 63 Bytes " "überprüft." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball Rekonstruktion Fallstudie" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Beispiel-Eingabeaufforderung kopieren" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Befolgen Sie die Berechnung der linken / rechten Klangposition" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Original-Montageauszug kopieren" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Ton kopieren-Pan-Funktion" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Komplette Sound-Pan-Baugruppe kopieren" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Kopieren Sie den DX-Ball-Analysebefehl" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Startseite{ph1} / Präsentieren" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA Fallstudien." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9679,17 +9687,17 @@ msgstr "" "Android, Spiele, Electron und eine CTF-Herausforderung mit Code, Zahlen und " "geprüften Ergebnissen." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Androide * APK Analyse" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Wie ein Authentifikator einen Anmeldecode generiert" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9701,22 +9709,22 @@ msgstr "" "bewegen Sie dann eine Demo-Uhr, um zu sehen, warum sich der Code alle 30 " "Sekunden ändert." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Lesen Sie die Android-Fallstudie" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Analyse von Maschinencode-Programmen" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Lösen Sie einen CTF-Flag-Checker" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9727,22 +9735,22 @@ msgstr "" "Sie die Prüffunktionen, verwandeln Sie Masken und Summen in Gleichungen und " "überprüfen Sie dann das gelöste Flag mit dem Originalprogramm." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Lesen Sie die CTF-Fallstudie" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Einheimische * Rekonstruktion" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-BallS Berechnung der linken / rechten Klangposition" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9754,22 +9762,22 @@ msgstr "" " numerische Konstanten führen zu einer kleinen C-Funktion, die mit dem " "ursprünglichen Verhalten und allen 63 kompilierten Bytes verglichen wird." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Lesen Sie die DX-Ball-Fallstudie" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Merkmalsverfolgung" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Wie Notion Text und HTML kopiert" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9781,22 +9789,22 @@ msgstr "" "Sie dann, wie ein kleiner HTML-Marker umfangreiche Blockdaten mit einer " "Kopie verknüpft." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Lesen Sie die Notion-Fallstudie" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * Rekonstruktion" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Wie TH04 einen Kugelring zielt" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9808,17 +9816,17 @@ msgstr "" " und sehen Sie dann, wie sie einen auf den Spieler gerichteten Ring " "erzeugen." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Lesen Sie die TH04-Fallstudie" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Schritt-für-Schritt-Anleitungen" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9828,7 +9836,7 @@ msgstr "" "und eine Browseranforderung. Jeder beginnt mit einer Aufforderung und einem " "konkreten Ziel." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Lesen Sie die Anleitungen" @@ -9848,12 +9856,12 @@ msgstr "" "einem Android-Authentifikator, DX-Ball, Notion, TH04 und einem DownUnderCTF-" "Flag-Checker." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -9862,25 +9870,25 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Startseite{ph1} / {ph2}Präsentieren{ph3} Modell: Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Fallstudie * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Wie Notion kopiert{ph0}text und HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9889,12 +9897,12 @@ msgstr "" "Verfolgen Sie einen Aufruf der Zwischenablage von der Seiten-API von Notion " "über den Preload- und den Hauptprozess zum Clipboard Writer von Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Arbeitsfläche 7.6.1 * JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Die Brücke im Desktop-Paket des Notion" @@ -9906,7 +9914,7 @@ msgstr "Die Brücke im Desktop-Paket des Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9923,7 +9931,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9940,7 +9948,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9957,7 +9965,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9968,13 +9976,13 @@ msgstr "" " den mitgelieferten Text und HTML.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Ein Kanal verbindet die beiden Seiten: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9984,14 +9992,14 @@ msgstr "" " Beim Auflösen der Wrapper werden die Electron-Aufrufe hinter diesen Namen " "angezeigt." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "In dieser Fallstudie" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9999,7 +10007,7 @@ msgstr "{ph0}Folgen Sie der Klemmbrett-Brücke{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -10007,19 +10015,19 @@ msgstr "{ph0}Die Struktur eines Blocks beibehalten{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Weitere Beispiele und Quellen{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Wohin geht der Kopiervorgang?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10039,17 +10047,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Kopieren" @@ -10060,7 +10068,7 @@ msgstr "Kopieren" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10071,7 +10079,7 @@ msgstr "" " in die Systemzwischenablage kopiert. Zeigen Sie den Code bei jedem Schritt " "an.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -10080,12 +10088,12 @@ msgstr "" "Eine Beispiel-Eingabeaufforderung mit dem lokalen Anwendungspaket von " "Notion, das Ihrem Codierungsagenten zur Verfügung steht." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA findet, wo mit dem Lesen begonnen werden soll" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -10096,13 +10104,13 @@ msgstr "" "verfügbar ist, und den Aufruf, der eine IPC-Anforderung sendet. Beide " "Befunde werden mit Quellbereichen im minimierten Bündel geliefert:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA Erkenntnisse → zwei Orte zum Öffnen" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10116,7 +10124,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10130,12 +10138,12 @@ msgstr "" "{ph1}. Dieser Name gibt dem Agenten etwas Genaues, nach dem er im Hauptpaket" " suchen kann. Die vier folgenden Auszüge zeigen die Route, die es verbindet." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Vier kurze Code-Stücke" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -10144,13 +10152,13 @@ msgstr "" "Vereinfacht aus dem verpackten JavaScript mit lesbaren Variablennamen. Nicht" " verwandte Mitglieder werden weggelassen." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Beginnen Sie bei der API, die der Seite angezeigt wird" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10160,13 +10168,13 @@ msgstr "" "Dieses Mitglied liefert den Kanalnamen. Die Umsetzung von {ph0} sagt uns, " "wie die Anfrage den Prozess der Seite verlässt." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Lösen Sie den Wrapper des Preloads auf" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10177,14 +10185,14 @@ msgstr "" "Antwort-IPC von Electron weiter. Wir können jetzt suchen nach {ph0} auf der " "Hauptprozesseite." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Überprüfen Sie, wie der Empfänger registriert ist" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10194,12 +10202,12 @@ msgstr "" "Der Hauptprozess verwendet einen anderen Wrapper. Seiner {ph0} methode " "registriert eine {ph1} empfänger für diesen Kanal." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Finden Sie den Schreib- und Absendercheck" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10211,13 +10219,13 @@ msgstr "" "beiden aufgelösten Wrapper verbinden die exponierte Methode mit diesem " "Aufruf." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Wie behält ein kopierter Block seine Struktur bei?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10228,27 +10236,27 @@ msgstr "" "Blockdaten lokal und fügt eine ID in den kopierten HTML-Code ein, um sie zu " "verbinden." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "HTML-Links zu gespeicherten Blockdaten" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Lesen Sie die HTML-ID" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Finden Sie die gleiche lokale ID" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Wiederherstellen von Notion-Blockdaten" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10258,7 +10266,7 @@ msgstr "" "Blockdaten wieder her, wenn die IDs übereinstimmen. Ein veralteter Eintrag " "gibt nur Text und HTML zurück." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10267,24 +10275,24 @@ msgstr "" "Beim Einfügen sucht Notion nach der HTML-ID und vergleicht sie mit der " "gespeicherten Kopie. Übereinstimmende IDs stellen die Blockdaten wieder her." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Format der Zwischenablage, aufgezeichnet aus Web-Assets, die am 13.Juli 2026" " zwischengespeichert wurden." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Weitere Beispiele und Quellen" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Ein weiteres Beispiel: Markdown-Tabellen" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10293,12 +10301,12 @@ msgstr "" "Notion analysiert Markdown in Blockdaten. Dieses Beispiel zeigt, wie aus " "einer Tabelle Kopf- und Datenzeilen werden." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Eine Tabelle durch den Markdown-Parser von Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10307,13 +10315,13 @@ msgstr "" "Aufgezeichnete Ausgabe von einem extrahierten Markdown-Parser. Die Tabelle " "wird zu Zeilen und Zellen." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Ein anderer Pfad: die Offline-SQLite-Verbindung" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10327,7 +10335,7 @@ msgstr "" "an einen SQLite-Dienstprogrammprozess weiter. Nachfolgende Anweisungsstapel " "und Ergebnisse werden über diesen Port übertragen." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10337,7 +10345,7 @@ msgstr "" "ausgeführt wird und warum bei der Verfolgung nur der anfänglichen IPC-" "Anforderung die spätere Konversation übersehen wird." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Quellen und wie man die Auszüge liest" @@ -10345,7 +10353,7 @@ msgstr "Quellen und wie man die Auszüge liest" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10363,7 +10371,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10380,7 +10388,7 @@ msgstr "" "Kabelbäume aus; Ihre Ausgaben beschreiben diese Sonden und nicht eine " "erfasste Desktop-UI-Sitzung." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10395,7 +10403,7 @@ msgstr "" "Wrapper-Implementierungen im Paket verbunden." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10413,7 +10421,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10427,7 +10435,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10453,53 +10461,53 @@ msgstr "" "Wrapper und den Hauptprozess von Electron mit kurzen Codeauszügen und einem " "Blick auf das umfangreiche Zwischenablage-Format." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron Fallstudie" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Notion Analyseaufforderung kopieren" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Kopieren Notion Vorspannung Auszug" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Kopieren Notion Wrapper-Auszug aufrufen" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Kopieren Sie den Auszug aus dem Notion-Handler-Wrapper" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Kopieren Notion Zwischenablage Empfänger Auszug" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "" "Wiederherstellen reichhaltiger Daten aus der Zwischenablage beim Einfügen" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Nach oben" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Zum Inhalt springen" @@ -10508,25 +10516,25 @@ msgstr "Zum Inhalt springen" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Startseite{ph1} / {ph2}Präsentieren{ph3} Modell: TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Fallstudie * Touhou 4: Lotus Land Geschichte" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Rekonstruktion des TH04{ph0}aufzählungsmuster." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10536,17 +10544,17 @@ msgstr "" "um die ursprüngliche DOS-Funktion zu überprüfen, und folgen Sie dann den " "Anweisungen in lesbares C ++." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 · 16-Bit-DOS · C++ und Assemblierung" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Sehen Sie sich die Rekonstruktion des TH04 an" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Von der Originalanleitung zur geprüften Quelle" @@ -10557,7 +10565,7 @@ msgstr "Von der Originalanleitung zur geprüften Quelle" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10573,7 +10581,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10591,7 +10599,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10608,7 +10616,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10620,7 +10628,7 @@ msgstr "" "Bytes{ph3}{ph4}Aufgezeichnete Compilerprüfungen decken den Code zur " "Aufzählungszeichengenerierung ab, der diesen Helfer enthält.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10629,14 +10637,14 @@ msgstr "" "REA gibt den Originalcode und seine Analysebeweise zurück. Das Projekt TH04 " "liefert die gepflegten Quell- und Compilerprüfungen." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "In dieser Fallstudie" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10644,7 +10652,7 @@ msgstr "{ph0}Der Kugelring{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10652,7 +10660,7 @@ msgstr "{ph0}Was REA zurückgibt{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10660,7 +10668,7 @@ msgstr "{ph0}Assemblierung nach C ++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10668,18 +10676,18 @@ msgstr "{ph0}Überprüfen der Quelle{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Das vollständige Projekt{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Wie ein Ring auf den Spieler zielt" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10698,16 +10706,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ihr Codierungsagent" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Kopieren" @@ -10718,7 +10726,7 @@ msgstr "Kopieren" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10729,7 +10737,7 @@ msgstr "" "Kugelring erstellt und auf den Spieler richtet. Erklären Sie die Berechnung " "und zeigen Sie den Code.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10739,7 +10747,7 @@ msgstr "" "Datei und der Rekonstruktions-Checkout lokal verfügbar sind." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10753,7 +10761,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10763,12 +10771,12 @@ msgstr "" "Eine Illustration der wiederhergestellten Winkelmathematik für Zählung 16, " "Spielerrichtung 40 und Schablonendrehung 0. {ph0}Offene Figur{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Die Zündvorlage in der wiederhergestellten Quelle" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Ellys Ringangriff * Quellenauszug" @@ -10777,7 +10785,7 @@ msgstr "Ellys Ringangriff * Quellenauszug" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10787,13 +10795,13 @@ msgstr "" "Diese Linien wählen das Muster vor der Schwierigkeits- und " "Leistungsabstimmung aus. {ph0}Lesen Sie die Quelle des Angriffs{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Was REA zurückgibt" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10805,12 +10813,12 @@ msgstr "" " Geschosses festlegt. REA gibt seine Anweisungen, Pseudocode und Referenzen" " zurück. Drei Teile dieses Ergebnisses erklären das Muster." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Überprüfen Sie das DOS-Image, bevor Sie den Code lesen" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10819,7 +10827,7 @@ msgstr "" "Die Prüfung bindet den geladenen Code und die Umzugsdatensätze an die " "gelieferte ausführbare Datei. Der obige Pfad ist für die Anzeige verkürzt." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Lesen Sie die Multiplikation und Division des Rings" @@ -10827,7 +10835,7 @@ msgstr "Lesen Sie die Multiplikation und Division des Rings" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10840,12 +10848,12 @@ msgstr "" "gepflegte Quelle benennt dieses Feld {ph2}. Die vollständige Sequenz " "erscheint unten." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Finde heraus, wo sich das Muster dem Spieler zuwendet" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10858,12 +10866,12 @@ msgstr "" "addiert. Quellennamen machen diese Adressen lesbar; Mit REA kann der Agent " "die ursprünglichen Vorgänge dahinter überprüfen." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Von Assembly zu lesbarem C ++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10876,7 +10884,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10884,7 +10892,7 @@ msgstr "{ph0}01{ph1} Index" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10892,7 +10900,7 @@ msgstr "{ph0}02{ph1} Raum" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10900,7 +10908,7 @@ msgstr "{ph0}03{ph1} Ziel" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10908,18 +10916,18 @@ msgstr "{ph0}04{ph1} Drehen" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Speichern" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * originale 16-Bit-Anleitung" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Lesbare C ++ * zielgerichtete Ring-Zusammenfassung" @@ -10927,7 +10935,7 @@ msgstr "Lesbare C ++ * zielgerichtete Ring-Zusammenfassung" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10942,7 +10950,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10958,7 +10966,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10974,7 +10982,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10989,7 +10997,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11003,7 +11011,7 @@ msgstr "" " wie bei der Umwandlung ohne Vorzeichen. Die umgebende Quelle wandelt diesen" " Winkel und diese Geschwindigkeit ebenfalls in Geschwindigkeit um." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -11015,7 +11023,7 @@ msgstr "" "folgenden Compiler-Prüfungen gelten für die gepflegte Quelle im verknüpften " "Projekt." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Lesen Sie die gepflegte Ring- und Zielquelle" @@ -11032,7 +11040,7 @@ msgstr "Lesen Sie die gepflegte Ring- und Zielquelle" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11042,12 +11050,12 @@ msgstr "" "{ph0}Ringmakro{ph1} · {ph2}Ziel- und Geschwindigkeitsquelle{ph3} · " "{ph4}Winkeldarstellung{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Überprüfen der gepflegten Quelle" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -11057,12 +11065,12 @@ msgstr "" " Bullet-Generierung, einschließlich dieses Helpers, mit seiner angehefteten " "Turbo C ++ 4.0J-Toolchain." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2.139 übereinstimmende Bytes" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -11071,12 +11079,12 @@ msgstr "" "Der kompilierte Code zur Aufzählungszeichengenerierung entspricht einem " "2.139 Byte großen Abschnitt der ursprünglichen ausführbaren Datei." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Zwei saubere Builds" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -11090,66 +11098,66 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "" "Aufgenommen am 3. Oktober 2026. {ph0}Lesen Sie die Compiler-Prüfungen{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Zielidentität und Analyseumfang" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Ursprüngliches Ziel" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156.258 bytes, ZWEI MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Hilfseintrag" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} im geladenen Bild von REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Versatz der ursprünglichen Datei" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, zurückgegeben von {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Inspektion aufgezeichneter Codes" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 · 7. Oktober 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11160,7 +11168,7 @@ msgstr "" "vergleichen auch den Kartenbeitrag und die überlappende Verlagerung." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11175,7 +11183,7 @@ msgstr "" "ausgewählten Anweisungen liegen in diesen gemeldeten Bereichen." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11192,7 +11200,7 @@ msgstr "" "sein Repository-Manifest festgelegt, wobei die unabhängige Herkunft des " "unberührten Dumps noch offen ist." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11203,12 +11211,12 @@ msgstr "" "vollständigen Spiels, Timing und Verhalten der PC-98-Hardware haben separate" " Laufzeitprüfungen im Rekonstruktionsprojekt." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "Die vollständige TH04-Rekonstruktion" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11221,7 +11229,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11233,7 +11241,7 @@ msgstr "{ph0}Erkunden Sie das TH04-Repository{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11249,7 +11257,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11265,7 +11273,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11291,22 +11299,22 @@ msgstr "" "Sie der Assembly und dem wiederhergestellten C ++, um zu sehen, wie ein " "Kugelring beabstandet und auf den Spieler gerichtet ist." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Auf dieser Seite" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 bullet-Muster Fallstudie" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Beispiel-Eingabeaufforderung TH04 kopieren" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11314,7 +11322,7 @@ msgstr "" "TH04 feste und zielgerichtete Geschossringe; auf kleineren Bildschirmen " "horizontal scrollen" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11328,27 +11336,27 @@ msgstr "" "Spieler. Beide halten einen Abstand von 16 Winkeleinheiten oder 22,5 Grad " "ein." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Kopieren Sie die TH04-Zündschablone" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Befolgen Sie die TH04 Zielringberechnung" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Auszug aus der TH04-Baugruppe kopieren" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Kopierlesbare Zielringberechnung" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Nach oben" @@ -11461,7 +11469,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Feste Geschwindigkeit: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11471,7 +11479,7 @@ msgstr "" "kontrollierten Originalspielprüfung überein, wenn sie auf drei " "Dezimalstellen gerundet werden." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11844,595 +11852,603 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Gleicher Abstand: 256 ÷ 16 = 16 Winkeleinheiten = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Fallstudien" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Erste Schritte" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Anleitungen" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Quellcode" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "MIT-Lizenz" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Zur Community" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Auf X folgen" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * ausgewählte Skriptquelle" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Quellcode" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Erwartete Formatierungsausgabe" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Anweisung" # Reviewed for grammatical function-call terminology. -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Aufrufende Funktion" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Konstant" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "C-Funktion" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Schaltfläche" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API vorladen" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Dateiendung.CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Ihr Klick" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Erfasste Anfrage" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Skript exportieren" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA Ergebnis * Zusammenfassung.ipc Auszug" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA Auszug aus der Anleitung · 0x406409" # Reviewed for grammatical function-call terminology. -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA · Aufrufende Funktion bei 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA Byte-Ergebnisse * interpretiert als Little-Endian-Doubles" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Wiederhergestellter C · -Auszug" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "So funktioniert REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Präsentieren →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Ausgewählte Einstellungen aus dem überprüften Skript" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Lesbare Zusammenfassung des % -Handlers" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * ausgewählte Originalanleitung" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Betreiber-IDs * Quelle von Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Folge @reatools auf X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Vertreter → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → Agent * ausgewählte Ergebnisse" # Reviewed for grammatical function-call terminology. -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → Agent · Methoden und aufrufende Funktionen" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * ausgewähltes dekompiliertes Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Lesbare Zusammenfassung * Interpretation des Agenten" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, kompletter Körper" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Laden Sie Aegis APK herunter" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Android-Analyse-Anbieter herunterladen" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Vertreter → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → Agent * ausgewählte Ergebnisse" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → Agent * ausgewählte Anweisungen" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agent → REA · Byte lesen" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → Agent * siebte Einträge" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Ursprüngliche ausführbare Datei * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Laden Sie die ursprüngliche Herausforderung herunter" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Löser herunterladen" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA Ergebnis * Pseudocode-Auszug" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Vertreter → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → Agent * Anweisungsauszug" # Reviewed for grammatical function-call terminology. -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → Agent · Auszug der aufrufenden Funktion" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Vertreter → REA * zwei {ph0} Antr" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA Byte-Ergebnisse * dekodiert als Doppel" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Beginnen Sie mit Ihrem eigenen Ziel" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "MODELL: APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Code generieren" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Wiederhergestellte Regel" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Einstellbare Uhr" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Binär" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Code überprüfen" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Gleichung" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Richtig!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Ausführbar" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA Ergebnisse" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Wiederhergestelltes C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Validierung" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Verpackte App" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Exponierte API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "IPC-Verpackungen" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Zwischenablage" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Ursprünglicher DOS-Code" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA Anleitung" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Winkelberechnung" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Kugelring" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "API für exponierte Seiten" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Renderer-IPC-Aufruf" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "An die Zwischenablage des Systems gesendet" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Lokal gespeichert von Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Markdown-Eingabe" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Strukturierte Parser-Ausgabe * Auszug" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analysieren Sie Ihre eigene App" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Vertreter → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → Agent * ausgewählte Felder" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Vertreter → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → Agent * Anweisungsauszug" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Gleiches Funktionsergebnis * Zielauszug" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Entsprechendes gepflegtes C ++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Ringmakro * TH04 Zweig, Auszug" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Winkel und Geschwindigkeit * Quellenauszug" @@ -12466,7 +12482,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12484,7 +12500,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12505,7 +12521,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12527,7 +12543,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12546,7 +12562,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12565,7 +12581,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12576,14 +12592,14 @@ msgstr "" "Website für mich.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Wiederaufbau · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12594,7 +12610,7 @@ msgstr "" "Codierungsagenten aus und überprüfen Sie die vorgeschlagenen Änderungen." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12603,7 +12619,7 @@ msgstr "Ein mitgeliefertes Beispiel * {ph0} und npm · Ihr Codierungsagent" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12622,7 +12638,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12637,7 +12653,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12656,7 +12672,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12667,7 +12683,7 @@ msgstr "" "auf {ph7} und schreibt die Datei.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12682,7 +12698,7 @@ msgstr "{ph0} * linien 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12696,7 +12712,7 @@ msgstr "" "an.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12707,7 +12723,7 @@ msgstr "" "verdoppelt. Dies überprüft den Formatierer direkt mit {ph0} ." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12715,7 +12731,7 @@ msgstr "{ph0} * CSV Formatierer" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12724,7 +12740,7 @@ msgstr "" "Du brauchst {ph0} 22 (22.19+), 24 (24.11+) oder 26+. npm kommt mit {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12732,7 +12748,7 @@ msgstr "Sie haben {ph0} nicht oder sind sich nicht sicher?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12745,7 +12761,7 @@ msgstr "" " wird, installieren Sie {ph1} 24 LITER:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12759,7 +12775,7 @@ msgstr "{ph0} * beispiel Quellenauszug" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12770,9 +12786,9 @@ msgstr "" "{ph5}Herunterladen {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12780,7 +12796,7 @@ msgstr "{ph0} * beispielquelle" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12795,7 +12811,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12808,7 +12824,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12821,7 +12837,7 @@ msgstr "Zum Beispiel: {ph0}Warum ergibt {ph1} im Rechner 220?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12832,7 +12848,7 @@ msgstr "" "{ph3} 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12841,7 +12857,7 @@ msgstr "REA * geladen {ph0} * ausgewählte Linien" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12859,7 +12875,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12878,7 +12894,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12892,28 +12908,28 @@ msgstr "" "kann.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_ansicht/{ph0} * API-Mitglied" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_ansicht/{ph0} * IPC-Helfer" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "Haupt{ph0} * Handler-Helfer" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12923,12 +12939,1446 @@ msgstr "Haupt{ph0} * Zwischenablage-Empfänger" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Erste Schritte {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Zum hellen Modus wechseln" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Zum dunklen Modus wechseln" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Für HTTP-Anfrage- und Antwortinhalte verwenden Sie {ph0}Fiddler Everywhere: " +"SAZ-Aufzeichnungen, MCP und öffentliche Skills{ph1}. Exportieren Sie SAZ " +"oder HAR 1.2 für die Offline-Auswertung der Aufzeichnung als REA Evidence, " +"oder verbinden Sie den MCP-Server von Everywhere, um aufgezeichneten " +"Datenverkehr mit Ihrem Agenten zu untersuchen." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Spezialisierte Modelle{ph0}Essay" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Braucht Reverse Engineering ein größeres Modell?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Was die Rekonstruktion von Touhou über allgemeine und spezialisierte Modelle" +" sowie das Lernen aus Compiler-Rückmeldungen zeigt." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Von N0zoM1z0 · 13. Oktober 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Zum Inhalt springen" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Home{ph1} / {ph2}Blog{ph3} / Modelle und Reverse Engineering" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Aufsatz" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Braucht Reverse Engineering ein größeres Modell?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Von N0zoM1z0 · 13. Oktober 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Das Wichtigste" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Die Modellfähigkeit beeinflusst, welche Hypothesen ein KI-Agent " +"vorschlagen kann.{ph1} Spätere Sitzungen lösten Probleme, die in früheren " +"Arbeiten ungelöst geblieben waren." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Ein bekannter Compiler bietet konkrete Muster für ein spezielles Modell" +" zum Lernen.{ph1} Einige genaue Maschinencode-Übereinstimmungen hängen von " +"bestimmten, wiederverwendbaren Quellcodemustern ab." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Beziehen Sie das Repository-Wissen in einen fairen Vergleich ein.{ph1} " +"Ein kleineres Modell mit gutem Wissensabruf verfügt möglicherweise bereits " +"über genügend Informationen, um Fortschritte zu erzielen." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Trainieren Sie das Modell, um das nächste nützliche Experiment " +"auszuwählen, und testen Sie seinen Prüfer.{ph1} Feedback ist nur insoweit " +"nützlich, als der Prüfer die richtigen Dinge überprüft." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Bewerten Sie verifizierte Rekonstruktionsergebnisse neben Zeit und " +"Kosten.{ph1} Das ist es, was ich für den gesamten KI-Agent-Workflow messen " +"möchte." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "In diesem Artikel" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Was leistungsfähigere Modelle verändert haben{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Warum spezialisieren?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Wo sollte diese Erfahrung gespeichert werden?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Lernen Sie das nächste nützliche Experiment{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Reverse Engineering und verstärkendes Lernen{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Wenn der Prüfer falsch ist{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Ein Vergleich, der sich lohnt{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Was für einen KI-Agenten lässt dies vermuten?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Was leistungsfähigere Modelle verändert haben" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Seit August 2026 erforsche ich, wie viel Reverse Engineering ein Agent mit " +"Zugriff auf ein Programm und einer Möglichkeit zur Überprüfung seiner Arbeit" +" durchführen kann. Der größte Teil meiner Erfahrung stammt aus der " +"Rekonstruktion von Spielen, insbesondere Touhou. Da ich die Modelle geändert" +" habe, haben die Repositorys aufgezeichnet, was jede Sitzung " +"wiederherstellen konnte." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Ein Großteil dieser Arbeit zielt auf eine exakte Rekonstruktion ab: Wir " +"kompilieren die gepflegte Quelle unter einer historischen Toolchain mit " +"festen Versionen und prüfen, ob sie die Zielfunktion reproduziert. Wenn ein " +"späteres Modell erfolgreich ist, wo frühere Arbeiten ins Stocken geraten " +"sind, zeigen die Quelländerungen, was diesen Fortschritt ermöglicht hat." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Die temporären Variablen benötigten überlappende Lebensdauern" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Ein Großteil der Logik einer TH09-Angriffsfunktion war bereits " +"rekonstruiert, aber der Compiler speicherte temporäre Ergebnisse immer noch " +"anders als das Original. Das verbleibende Problem bestand darin, wie lange " +"diese Ergebnisse am Leben bleiben mussten und wann ihr Speicher " +"wiederverwendet werden konnte." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Ein {ph0}GPT-6-Sol-Sitzungsdatensatz{ph1} hat diese Nichtübereinstimmung " +"gemeldet, nachdem mehrere gewöhnliche Quellcode-Anordnungen getestet wurden." +" Als {ph2}GPT-6.1-Sol das Problem erneut untersuchte{ph3}, schlug es eine " +"nützliche Hypothese über die Lebensdauer dieser temporären Variablen vor." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"Die Funktion erzeugte temporäre Ergebnisse und kopierte sie in " +"Animationspositionen. In C++ bleibt ein temporäres Ergebnis bestehen, bis " +"der Ausdruck, der es verwendet, beendet ist. Durch die Gruppierung der " +"realen Operationen in einem Ausdruck blieben diese Ergebnisse zusammen " +"erhalten, sodass der Compiler nicht mehr denselben Speicher für alle " +"wiederverwenden konnte." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Ein Ergebnis wird weiterhin gemeinsam mit einem Wert gespeichert, der später" +" für Kollisionsprüfungen verwendet wird. Indem man diesem Wert seine eigene " +"Lebensdauer zuordnete, wurde die verbleibende Überlappung behoben. Nach " +"mehreren gezielten Experimenten bestätigte {ph0}eine saubere Neukompilierung" +" aus dem Quellcode, dass die vollständige Funktion übereinstimmte{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Mich interessiert, wie sich Entdeckung und Tests gegenseitig unterstützten. " +"Die Hypothese über die temporäre Lebensdauer von Objekten gab dem KI-Agenten" +" eine neue Richtung. Das Feedback des Compilers half dabei, diese Hypothese " +"in eine passende Quellcode-Anordnung zu verfeinern." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Ein anderes Kontrollflussdiagramm" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Eine zweite TH09-Funktion zeigt, warum eine neue Richtung wichtig sein kann." +" Hier ging es darum, wie mehrere Verzweigungen dieselben abschließenden " +"Operationen nutzen. {ph0}GPT-6.1-Sols frühere Arbeit{ph1} brachte Teile der " +"Funktion zur Übereinstimmung, doch die Verzweigungen liefen noch anders " +"zusammen als im Original." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra hat das umgebende Kontrollflussdiagramm{ph1} geändert. Die " +"Hauptwege führten nun zu einer gemeinsamen finalen Aktualisierung und " +"Rückkehr. In dieser Quellstruktur kombinierte der Compiler die Zweige auf " +"die gleiche Weise wie im Original. Die vollständige Funktion stimmte überein" +" und eine {ph2}separate Neuerstellungsprüfung bestätigte dies{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Durch die Änderung der Darstellung wurde ein produktiverer Suchraum " +"eröffnet.{ph1} Beide Fälle geben mir einen Grund, die allgemeine " +"Modellfähigkeit ernst zu nehmen: Ein Agent kann lange Zeit lokale " +"Variationen ausprobieren, bevor er eine bessere Möglichkeit findet, die " +"umgebende Arbeit auszudrücken." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Die späteren Sitzungen übernahmen allerdings auch früheren Quellcode und " +"aufgezeichnete Fehlversuche. Diese Vorarbeit war Teil ihres Vorteils. Die " +"Historie macht die Entdeckungen und ihre Prüfungen nachvollziehbar. Ein " +"kontrollierter Vergleich würde helfen, den Beitrag des Modells vom Beitrag " +"der übernommenen Erfahrung zu trennen." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Das macht die Frage für mich interessant. Einige Fortschritte wurden durch " +"die Suche nach einer neuen Vertretung erzielt. Ein Großteil der " +"verbleibenden Arbeit bestand darin, verschiedene Quellcode-Anordnungen mit " +"einem vertrauten Compiler zu testen. Wie viel davon erfordert ein breites " +"Denkvermögen? Wie viel könnte ein Modell lernen, wenn es wiederholt mit " +"diesem Compiler und Code arbeitet?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Warum könnte ein spezialisiertes KI-Modell gut funktionieren?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou gibt uns einen konkreten Grund zu der Annahme, dass diese Erfahrung " +"hilfreich sein wird. Ein Großteil des Spielcodes stammt vom selben Autor, " +"ZUN, daher sind wiederkehrende Gewohnheiten eine vernünftige " +"Ausgangsannahme. Die Repositories untermauern dies mit nützlichen " +"Beispielen: Verwandte Schleifen und Hilfsanordnungen haben spielübergreifend" +" Hypothesen geliefert." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Diese Quellmuster werden spezifischer, wenn wir den Compiler einbeziehen. " +"Unter einer bestimmten Version und einem bestimmten Optionssatz können " +"kleine Änderungen in der Quelle zu wiederholbaren Unterschieden im " +"Maschinencode führen. Einige dieser Unterschiede sind überraschend unklar." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"In TH095 beispielsweise könnte {ph0}sogar der Name einer lokalen Variablen " +"Einfluss darauf haben, wo VC7.1 sie gespeichert hat{ph1}. Das Verschieben " +"der Deklaration hat das Speicherlayout nicht gelöst. Allerdings hatte eine " +"frühere Hintergrundfunktion ein Namensmuster offenbart, das die Wahl des " +"Compilers beeinflusste. Das legte eine vielversprechendere Hypothese für die" +" {ph2}Rekonstruktion von {ph3}{ph4} nahe." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Durch die Wiederverwendung dieses Musters für die Dateigrößenvariable wurde " +"das erforderliche Layout erstellt, ohne dass Speicherplatz hinzugefügt " +"werden musste. Die gesamte Funktion stimmte dann überein." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Dies ist ein sehr spezifisches Detail, das einem allgemeines KI-Modell " +"möglicherweise nicht bekannt ist, wenn es zum ersten Mal auf das Problem " +"stößt. Ein auf diesen Compiler spezialisiertes Modell könnte viele solcher " +"Fälle erkennen und herausfinden, welche Quellcodevarianten es wert sind, " +"zuerst getestet zu werden." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Die Chance wird besonders deutlich bei finalen Matching-Problemen, bei denen" +" wir das Verhalten bereits verstehen. Wir fragen uns dann, welche " +"gewöhnliche Quellcodeanordnung dieser Compiler in die beobachteten " +"Anweisungen umwandelt. Durch die Spezialisierung könnte das Modell diese " +"Formen effizienter vorschlagen, während das Ziel weiterhin bestimmt, welche " +"Hypothesen bestehen bleiben." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Nützliche Muster müssen ihren Kontext behalten. TH08 verwendet eine frühere " +"Visual C++-Version als TH095 und TH09. TH04 verwendet einen anderen Compiler" +" aus der DOS-Ära. Für die {ph0}Rekonstruktion des Spielercodes{ph1} waren " +"unterschiedliche Hypothesen über Quellcodemuster und die Art und Weise " +"erforderlich, wie kompilierter Code mit einer ausführbaren Datei verknüpft " +"wurde. Wenn wir denselben Autor haben, haben wir zunächst eine Erwartung, " +"aber jedes Ziel sagt uns, ob es zutrifft. Ein spezielles Modell müsste diese" +" Kontexte unterscheiden." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Wo sollte diese Erfahrung gespeichert werden?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Bevor ich mich entscheide, diese Muster durch Modelltraining zu lehren, " +"würde ich mir das Wissen ansehen, das wir bereits im Repository speichern. " +"Im {ph0}vorherigen Aufsatz{ph1} habe ich darüber geschrieben, dass es zum " +"Arbeitsgedächtnis des Projekts wird. Dieser Speicher umfasst Compiler-" +"Lektionen sowie die Quelle und fehlgeschlagene Experimente, die sie nützlich" +" gemacht haben." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Durch das Abrufen dieses Datensatzes kann ein Agent mit einem bekannten " +"Ergebnis beginnen und prüfen, wie wir zu diesem Ergebnis gelangt sind. Es " +"können auch Alternativen vermieden werden, die im gleichen Kontext bereits " +"gescheitert sind. Der Ausgangspunkt verbessert sich, ohne die trainierten " +"Parameter des Modells zu ändern." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Bei der Rekonstruktion der Funktion von TH09 zum Erstellen von Feinden hat " +"eine {ph0}GPT-6-Luna-max-Sitzung{ph1} eine Hypothese aus dem zugehörigen " +"TH08-Quellcode übernommen. Dieser frühere Code schlug vor, wie die Schleife " +"organisiert und Fehler darin behandelt werden sollten. Die eigenen Beweise " +"von TH09 lieferten die spielspezifischen Details. Neuaufbauten aus der " +"Quelle bestätigten, dass die vollständige Funktion übereinstimmte." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}„Das Modell kannte diese Compiler-Eigenart nicht“ und „Das Modell " +"konnte sie nicht verwenden“ sind unterschiedliche Probleme.{ph1} Das erste " +"Problem kann durch das Abrufen gelöst werden, aber die Umwandlung dieser " +"Tatsache in einen nützlichen Kandidaten erfordert noch Arbeit. Und wenn der " +"Quellcode des Kandidaten fehlschlägt, muss das Modell entscheiden, was das " +"Ergebnis für seinen nächsten Versuch bedeutet. Die Kenntnis des relevanten " +"Musters ist nur der Anfang dieses Prozesses." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Aus diesem Grund würde ich in jeden Vergleich ein kleineres allgemeines KI-" +"Modell mit gutem Abruf einbeziehen. Wenn wir ihm die gleiche " +"Erfahrungsbibliothek zur Verfügung stellen, können wir herausfinden, was die" +" Schulung bringt: bessere Kandidatengenerierung, bessere Entscheidungen nach" +" Feedback oder beides." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Lernen Sie das nächste nützliche Experiment" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Diese Entscheidungen nach Feedback sind das, was ich am liebsten studieren " +"würde. Bei der Agentenrekonstruktion schlägt das Modell eine Erklärung vor " +"und testet sie anhand des Programms. Selbst wenn der Quellcode des " +"Kandidaten fehlschlägt, kann das Ergebnis die verbleibenden Möglichkeiten " +"einschränken und ein nützlicheres nächstes Experiment vorschlagen." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Das Beispiel der temporären Ergebnisse zeigt auch das. Der endgültige " +"Quellcode enthält die Anordnung, die funktioniert hat. Der Weg dorthin " +"enthält jedoch zusätzliche Informationen: Jedes der folgenden Experimente " +"zeigte, was noch geändert werden musste." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Experimentieren" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Was uns das Ergebnis lehrte" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "" +"Versuchen Sie es mit einer anderen Möglichkeit, die Ergebnisse zu kopieren" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "" +"Der Kopiercode ändert sich, aber die Funktion unterscheidet sich immer noch." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Verwenden Sie die zurückgegebenen Werte direkt" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"Das Kopieren erfolgt nach dem ursprünglichen Muster, die temporäre " +"Speicherung unterscheidet sich jedoch noch." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Halten Sie alle temporären Variablen gleichzeitig gültig" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Sie erhalten einen separaten Speicher, aber einer überlappt immer noch einen" +" Wert, der später für Kollisionsprüfungen verwendet wird." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Halten Sie den Wert für die Kollisionsprüfung getrennt" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Eine saubere Neukompilierung aus dem Quellcode bestätigt die vollständige " +"Übereinstimmung." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Ausgewählte Experimente aus der Angriffsfunktionsrekonstruktion oben, " +"gruppiert nach dem, was sie uns gelehrt haben." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Eine Trainingsaufzeichnung, die diese Reihenfolge beibehält, kann mehr " +"lehren als die endgültige Quelle allein. Es verbindet jede vorgeschlagene " +"Änderung mit einem beobachteten Ergebnis und der nächsten Entscheidung. Es " +"ist auch wichtig, ineffektive Variationen beizubehalten: Sie teilen einem " +"späteren Agenten mit, welche Hypothesen in diesem Zusammenhang bereits " +"getestet wurden." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Ich möchte, dass das Modell lernt, Feedback zu nutzen.{ph1} Ein " +"neutrales Ergebnis ist ein Grund, die Variation noch einmal zu überdenken. " +"Eine veränderte Nichtübereinstimmung kann auf eine andere Ursache hinweisen." +" Wenn lokale Änderungen nicht mehr informativ sind, sollte der Agent in der " +"Lage sein, die Quellendarstellung noch einmal aufzurufen oder die Beweise " +"erneut zu prüfen." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Zu lernen, diese Entscheidungen zu treffen, erfordert Autonomie. Manchmal " +"besteht der nützliche nächste Schritt darin, einen anderen Aufrufer zu " +"überprüfen, anstatt eine weitere Bearbeitung zu kompilieren. Eine starre " +"Abfolge erforderlicher Umschreibungen würde diese Wahlmöglichkeit zusammen " +"mit einem Teil des Verhaltens, das das Modell lernen soll, aufheben." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "Warum Reverse Engineering für Reinforcement Learning interessant ist" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Rekonstruktion mit klar abgegrenztem Umfang bietet eine praktische Umgebung," +" um diese Entscheidungen zu untersuchen. Bei festgelegtem Ziel und Compiler " +"liefern viele Quellcodeexperimente schnelles, wiederholbares Feedback. Der " +"Agent kann einen Kandidaten kompilieren, die Abweichungen prüfen und daraus " +"den nächsten Schritt wählen." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Reinforcement Learning könnte diesen Entscheidungsprozess durch das " +"erhaltene Feedback trainieren. Ein durch eine definierte Prüfung " +"angenommener Kandidat gibt uns ein konkretes Ergebnis, während wir anhand " +"der Abfolge der Versuche sehen können, wie viel Arbeit es gekostet hat, " +"dieses zu erreichen." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Es gibt bereits Forschungsergebnisse, die diese Richtung unterstützen. " +"{ph0}LLM4Decompile{ph1} untersucht Modelle, die auf die Dekompilierung " +"spezialisiert sind. {ph2}AutoDecompiler{ph3} trainiert die Multi-Turn-" +"Verfeinerung mithilfe von Compiler- und Ausführungsfeedback. Der Schwerpunkt" +" ihrer Studien liegt auf der Wiederherstellung des Programmverhaltens. Für " +"diese Arbeit würde ich sie als Ausgangspunkt für die damit verbundene " +"Aufgabe verwenden, eine Quelle zu finden, die mit der Ausgabe eines " +"historischen Compilers übereinstimmt." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Um eine so klar definierte Aufgabe zu erfüllen, müssen wir jedoch " +"möglicherweise zunächst feststellen, welche Ressourcen eine Funktion " +"besitzt, oder eine neue Methode zur Beobachtung des Programms während der " +"Ausführung entwickeln. In TH08 beispielsweise führte ein " +"{ph0}Kollisionsunterschied dazu, wie das ursprüngliche Programm " +"Gleitkommaberechnungen verarbeitete{ph1}. Bevor der Agent eine nützliche " +"Korrektur testen konnte, musste er herausfinden, was gemessen werden sollte." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Dies deutet auf eine weitere Rolle eines allgemein leistungsfähigen Modells " +"hin: Es hilft dabei, das Problem überhaupt überprüfbar zu machen. Sobald " +"diese Prüfung vorliegt, können wir untersuchen, wie weit eine erlernte " +"Suchrichtlinie damit kommen kann." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Wenn der Prüfer falsch ist" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Wenn wir eine Prüfung für das Training verwenden, wird auch ihr " +"Prüfungsumfang Teil der Lernumgebung. Ich nenne eine solche Referenz oder " +"einen solchen Prüfer ein Oracle. Selbst eine wiederholbare Antwort müssen " +"wir danach beurteilen, was sie tatsächlich überprüft." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 hat gezeigt, wie viel sich außerhalb dieser Abdeckung verbergen kann. " +"Einige rekonstruierte Funktionen haben ihre exakten Vergleiche mit falschen " +"Gleitkommakonstanten bestanden. Der Komparator passte die verschobenen " +"Adressen an, bevor er die Anweisungen überprüfte, überprüfte die Werte " +"hinter diesen Adressen jedoch nur, wenn sie explizit zur Überprüfung " +"aufgezeichnet wurden. Andere wörtliche Verweise könnten ohne Prüfung ihrer " +"Werte bestehen bleiben." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Um diese Lücke zu schließen, wurden bei einer {ph0}umfassenderen " +"Prüfung{ph1} falsche Konstanten in Funktionen gefunden, die bereits die " +"Überprüfung bestanden hatten. In einer Berechnung fügte der rekonstruierte " +"Quellcode {ph2} hinzu, während das Original {ph3} hinzufügte." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Ein Modell, das durch die alte Verifizierungsprüfung belohnt wurde, " +"könnte lernen, eine falsche Rekonstruktion zu erzeugen.{ph1} Wir haben mit " +"diesem Prüfer kein RL-Modell trainiert. Der von uns beobachtete Fehler lag " +"in der Prüfung selbst. Aber wenn wir es als Belohnung nutzen würden, würde " +"derselbe blinde Fleck Teil der Lernumgebung werden." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Ein Funktionstest kann einen ähnlichen blinden Fleck haben. " +"{ph0}Untersuchungen mit differenziellem Fuzzing auf LLM-Decompilern{ph1} " +"ergaben Verhaltensunterschiede außerhalb der bereitgestellten Tests. Wir " +"müssen daher einen bestandenen Test im Hinblick auf die Fälle verstehen, in " +"denen er durchgeführt wird. Ebenso muss eine Befehlsübereinstimmung im " +"Hinblick auf die Bytes und Daten verstanden werden, die sie überprüft." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Bevor ich eine Art Verifizierungsprüfung als Belohnung verwende, würde ich " +"sie mit absichtlich falschen Ergebnissen testen. Ich würde die Endabnahme " +"auch getrennt vom Quellcode durchführen, den der KI-Agent bearbeiten kann. " +"Das Modell muss die Verifizierung bestehen, indem es das Programm korrekt " +"rekonstruiert. Andernfalls könnte das einfache Kopieren eines Byte-Arrays " +"vom Ziel ein naives Bewertungssystem täuschen, ohne dass nützlicher " +"Quellcode wiederhergestellt wird." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Die Verbesserung des Lernenden und die Verbesserung seines Prüfers " +"gehören zum selben Forschungsproblem.{ph1} Je besser der Lernende darin " +"wird, das Feedback, das wir ihm geben, zu optimieren, desto wichtiger wird " +"auch das Verständnis dieses Feedbacks." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Ein Vergleich, der sich lohnt" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Wenn diese Prüfungen vorhanden sind, würde ich den Vergleich für eine feste " +"VC7.1-Aufgabenfamilie starten. Zunächst würde ich Grundlinien für ein " +"starkes allgemeines KI-Modell und ein kleineres Modell festlegen. Das " +"Hinzufügen von Repository-Wissen zum kleineren Modell würde zeigen, welche " +"Änderungen sich beim Abruf ergeben. Von dort aus würden wir durch eine " +"überwachte Spezialisierung und eine RL-trainierte Version untersuchen " +"können, was Training hinzufügt." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Um diese Vergleiche aussagekräftig zu machen, würde jedes Modell die " +"gleichen Zieldaten und Tools erhalten. Für die ausbildungsspezifischen " +"Vergleiche würde ich das Basismodell und das verfügbare Wissen ebenfalls " +"unverändert lassen. Wiederholte Versuche würden dabei helfen, eine " +"zuverlässige Suchstrategie von einer Kandidatenlösung zu unterscheiden, die " +"zufällig erfolgreich ist." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Ich würde dann zwei Startbedingungen trennen: die Rekonstruktion einer " +"Funktion aus ihren Anweisungen und die Beseitigung der letzten paar " +"Unterschiede in der gepflegten Quelle. Bei der zweiten Aufgabe könnte ein " +"spezialisiertes KI-Modell hervorragend geeignet sein, während ein " +"allgemeines KI-Modell einen Großteil der dafür erforderlichen Arbeit " +"übernimmt. Eine getrennte Messung würde diese Arbeitsteilung offenbaren." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Für beide Aufgaben sind Testbeispiele erforderlich, die vom Training und " +"Abruf ausgeschlossen sind. Verwandte Touhou-Spiele teilen den Engine-Code. " +"Der Ausschluss eines Spiels vom Training könnte dennoch dazu führen, dass " +"nahezu identische Funktionen im Trainingsset verbleiben. Stattdessen würde " +"ich ganze Gruppen verwandten Quellcodes ausschließen und ihre verifizierten " +"Antworten sowohl aus den Trainingsdaten als auch aus der Abrufbibliothek " +"heraushalten." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Das Ergebnis wären vollständige, unabhängig verifizierte Übereinstimmungen. " +"Gleiche Budgets für Kandidaten oder Kompilierungsversuche helfen, die " +"Suchqualität zu vergleichen. Gesamtzeit und Gesamtkosten einschließlich " +"Kompilierung zeigen, ob diese Qualität einen effizienten Arbeitsablauf " +"ermöglicht. Trainingskosten sollten separat erfasst werden." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Beide Messungen sind wichtig. Ein billiger Vorschlag kann zu einem teuren " +"Arbeitsablauf führen, wenn er mehr Kompilierungen verursacht, die keine " +"nützlichen Informationen liefern. Umgekehrt kann ein langsameres Modell " +"wirtschaftlicher sein, wenn es früher ein nützliches Experiment findet. Der " +"Vergleich sollte diese Kosten einbeziehen." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Akzeptierte Ergebnisse zu zählen hilft auch, Zwischenfortschritte " +"einzuordnen. Ein {ph0}Replay-Save-Kandidat{ph1} aus TH09 wirkte " +"vielversprechend, weil die kompilierte Funktion die erwartete Größe hatte. " +"Der vollständige Vergleich fand aber noch erhebliche Unterschiede. Eine " +"andere Anordnung der Befehle kann einen Kandidaten näher am Ziel erscheinen " +"lassen, ohne das eigentliche Problem zu lösen. Solche Diagnosen können das " +"nächste Experiment leiten; eine Belohnung für mehr Nähe würde ich jedoch " +"anhand der vollständigen Abnahmeprüfung validieren." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Mich würde das Muster dieser Ergebnisse interessieren. Wenn ein " +"spezialisiertes KI-Modell in einer bekannten Compilerfamilie gut " +"funktioniert, überlebt dieser Vorteil dann auch eine Änderung der Toolchain?" +" Und wenn beide KI-Modelle eine gute Retrievalfähigkeit haben, wie viel " +"bringt das Training dann noch? Die Antworten würden uns helfen zu " +"entscheiden, wo welche Art von Modell am nützlichsten ist." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Was für einen KI-Agenten lässt dies vermuten?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Wenn sich herausstellt, dass die Modelle in verschiedenen Phasen hilfreich " +"sind, könnte ein umfassender Agent mit Zugriff auf ein spezielles KI-Modell " +"eine nützliche Lösung sein. Sobald eine Aufgabe zu einer vertrauten " +"Compiler-Suche wird, könnte sie das spezialisierte KI-Modell nach Kandidaten" +" fragen. Wenn die Ergebnisse keinen Sinn mehr ergeben, könnte der breitere " +"Agent zum Zielbeweis zurückkehren oder die Messung selbst untersuchen." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"In dieser Vereinbarung wird die Spezialisierung zu einem Instrument, das der" +" Agent im Verlauf der Untersuchung wählen kann. Der Agent behält die " +"Freiheit, die Richtung zu ändern, die die früheren Durchbrüche ermöglicht " +"hat." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Dies ergibt sich natürlich aus dem industriellen Wandel, den ich im " +"vorherigen Aufsatz beschrieben habe. Die Möglichkeit, viel mehr Experimente " +"durchführen zu können, verändert die Art und Weise, wie wir die Arbeit " +"organisieren. Es gibt uns auch einen Grund zu fragen, welche Entscheidungen " +"ein breites Urteilsvermögen erfordern und welche sich durch wiederholte " +"Erfahrung mit einem bestimmten Handwerk verbessern." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Vorerst hat sich das stärkste allgemeine KI-Modell seinen Platz in meinem " +"Arbeitsablauf verdient, indem es Probleme löste, die ich ungelöst gelassen " +"hatte. Gerade diese Erfolge machen mich neugierig: Wie viel hing von seiner " +"breiten Fähigkeit ab? Wie viel könnte ein Modell übernehmen, das auf diese " +"Art der Rekonstruktion spezialisiert ist?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Die Repositorys bieten uns eine Möglichkeit, die Frage zu testen.{ph1} " +"Ich möchte diesen Datensatz verwenden, um den Vergleich zu erstellen und zu " +"sehen, was wir lernen." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Beweise und Modellzuschreibung" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Die Beispiele beschreiben historische Vergleiche auf Funktionsebene, die in " +"den verknüpften Commits aufgezeichnet wurden. Laufzeitprüfungen für das " +"gesamte Spiel sind separate Meilensteine. Quelle und übereinstimmende " +"Aufzeichnungen wurden am 13. Oktober 2026 überprüft." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"Die Bezeichnung TH09 {ph0} bedeutet GPT-6-Astra. Das mit {ph1} verknüpfte " +"Modell hat sich im Laufe der Zeit geändert, sodass die Bezeichnung allein " +"das in einem bestimmten Lauf verwendete Modell nicht identifizieren kann. " +"Explizite Modellnamen in den anderen zitierten Commits liefern die " +"aufgezeichnete Zuschreibung. Diese Historien enthalten keine konsistenten " +"Messungen der Kosten oder des Aufwands für jeden Lauf." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 temporäre Objektlebensdauern:{ph1} die {ph2}frühere " +"Kontextüberprüfung{ph3} und {ph4}vollständige Rekonstruktion, verifiziert " +"durch eine saubere Neukompilierung aus der Quelle{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front-Callback:{ph1} {ph2}Diagnosebereiche, die nicht " +"übereinstimmten{ph3}, {ph4}Astras neues Kontrollflussdiagramm{ph5} und seine" +" {ph6}akzeptierte Neukompilierungsprüfung{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Compiler-Kenntnisse:{ph1} {ph2}TH095 Wiederverwendung des Identifier-" +"Bucket-Verhaltens{ph3}, {ph4}TH04 Player-Quellcode und Linker-" +"Reihenfolge{ph5} und {ph6}Lunas vollständige Rekonstruktion der " +"Feinderschaffungsfunktion von TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Prüfungen und Diagnosen:{ph1} {ph2}TH08-Prüfung der " +"Gleitkommakonstanten{ph3}, {ph4}TH08-Untersuchung numerischer " +"Unterschiede{ph5} und {ph6}TH09-Rekonstruktion der Replay-Speicherung{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Die vorgeschlagenen Vergleiche spezialisierter Modelle und RL-Training sind " +"zukünftige Experimente. Die Projektgeschichten motivieren sie. Für diesen " +"Aufsatz wurde kein trainiertes Spezialmodell evaluiert." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Braucht Reverse Engineering ein größeres Modell? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Was ich durch die Rekonstruktion von Touhou über allgemeine Modelle, " +"Spezialmodelle und das Lernen, bessere Hypothesen anhand des Compiler-" +"Feedbacks aufzustellen, gelernt habe." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Auf dieser Seite" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Essay über Modelle und Reverse Engineering" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Ausgewählte Rekonstruktionsexperimente" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Nach oben" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"Die {ph0}ausführlichen Evidenznotizen{ph1} enthalten die aufgezeichneten " +"Vergleiche und den Kontext der Experimente." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Von N0zoM1z0 · 13. Oktober 2026 · Entwurf zur Durchsicht" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Einrichtungsanleitung" diff --git a/website/locales/es/messages.po b/website/locales/es/messages.po index 5ad61690c..bc68e0b74 100644 --- a/website/locales/es/messages.po +++ b/website/locales/es/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Saltar al contenido" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Inicio{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Reflexiones sobre ingeniería inversa." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Reconstrucción del juego{ph0}Ensayo" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "La revolución industrial en ingeniería inversa" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -53,34 +53,35 @@ msgstr "" "enseñó sobre los agentes, la verificación y el conocimiento que componen los" " proyectos." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Leer el artículo" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Por N0zoM1z0 * 10 octubre 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -101,6 +102,8 @@ msgstr "" "con REA y agentes de IA." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -136,112 +139,117 @@ msgstr "" "REA — Descubra cómo funciona el software. Ingeniería inversa con su agente " "de codificación." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Inicio de REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Navegación principal" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA en GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Únete a REA en Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Sigue a REA en X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -250,35 +258,35 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Inicio{ph1} / {ph2}Blog{ph3} / Reconstrucción Touhou" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Ensayo * Reconstrucción de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "La revolución industrial en ingeniería inversa." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Por N0zoM1z0 * 10 octubre 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Ideas clave" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -291,7 +299,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -305,7 +313,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -318,7 +326,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -331,7 +339,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -341,65 +349,65 @@ msgstr "" "{ph0}Estamos en los primeros días de la revolución industrial de ER.{ph1} " "Los métodos aún están tomando forma. Queda mucho por explorar." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Cómo se compone la experiencia" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Dirección humana{ph1} * Objetivo y criterios de aceptación" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Autonomía" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agente" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Elige un experimento.{ph0}Propón una hipótesis." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Verificación" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Referencia de validación" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Prueba contra a{ph0}referencia concreta." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Repositorio" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Memoria de trabajo" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -408,7 +416,7 @@ msgstr "Código, evidencia,{ph0}cheques y lecciones." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -417,26 +425,26 @@ msgstr "Desajuste{ph0}{ph1}Revisar la hipótesis{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Una mejor{ph0}{ph1}punto de partida{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Reutilización" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Pase{ph1} * Conservar el resultado y su evidencia" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -445,14 +453,14 @@ msgstr "" "Cada proyecto deja al siguiente con un mejor punto de partida. Eso incluye " "arreglar los cheques cuando descubrimos una brecha." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "En este artículo" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -460,7 +468,7 @@ msgstr "{ph0}Agosto de 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -468,7 +476,7 @@ msgstr "{ph0} TH08: la continuación{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -476,7 +484,7 @@ msgstr "{ph0}Dos enfoques{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -484,7 +492,7 @@ msgstr "{ph0} TH095: composición{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -492,7 +500,7 @@ msgstr "{ph0} TH04: entre arquitecturas{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -500,7 +508,7 @@ msgstr "{ph0}De exacto a legible{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -508,18 +516,18 @@ msgstr "{ph0}El cambio industrial{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Lo que se hace posible{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Qué cambió en agosto de 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -534,7 +542,7 @@ msgstr "" "tiempo a la siguiente función. También significaba mantener una imagen cada " "vez más grande en mi cabeza." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -548,7 +556,7 @@ msgstr "" "puede ser útil en otros lugares, pero cada campo necesita establecer qué " "puede verificar con una referencia confiable." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -562,7 +570,7 @@ msgstr "" "reconstrucción de Touhou me dio un proyecto sustancial en el que " "averiguarlo." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -579,7 +587,7 @@ msgstr "" "Darle esa libertad marcó la diferencia: pude dedicar más atención a la " "dirección del proyecto y a si sus controles eran confiables." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -590,7 +598,7 @@ msgstr "" "sobreviviría más allá del proyecto actual. ¿Se beneficiaría el próximo juego" " de todo lo que acabábamos de aprender?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: construyendo sobre el trabajo humano" @@ -599,7 +607,7 @@ msgstr "TH08: construyendo sobre el trabajo humano" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -613,7 +621,7 @@ msgstr "" "sustancial. Vino con el conocimiento de la construcción y una historia de " "contribuciones que conservé en la continuación." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -625,7 +633,7 @@ msgstr "" " agosto, el libro mayor registró la fuente de las 1.107 funciones de juego " "identificadas." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -636,7 +644,7 @@ msgstr "" "aproximadamente once días después de que comenzara la continuación. Siguió " "una edición web. La versión nativa Linux de 64 bits llegó el 30 de agosto." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -652,7 +660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -671,12 +679,12 @@ msgstr "" "propone una explicación y la prueba; un desajuste le da algo específico para" " investigar." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Una coincidencia exacta con la constante incorrecta" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -688,7 +696,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -701,7 +709,7 @@ msgstr "" "reconstruida verificó la potencia del jugador contra {ph0}. El original " "usado {ph1}, el umbral de potencia máxima." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -717,14 +725,14 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "" "{ph0}Sin embargo, la función ya había pasado la comparación exacta.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -740,7 +748,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -756,7 +764,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -771,7 +779,7 @@ msgstr "" " coma flotante. Encontró otras doce referencias incorrectas en cinco " "funciones aceptadas." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -785,7 +793,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -795,7 +803,7 @@ msgstr "" "{ph0}La referencia de verificación (oracle) también necesitaba " "reconstrucción.{ph1} Repararlo era parte de reparar el juego." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -813,7 +821,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -830,7 +838,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -840,7 +848,7 @@ msgstr "" "{ph0}Un lote exitoso nos dio tanto el código recuperado como un mejor " "entorno para el siguiente lote.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Dos ideas diferentes de reconstrucción" @@ -849,7 +857,7 @@ msgstr "Dos ideas diferentes de reconstrucción" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -861,7 +869,7 @@ msgstr "" "tipo de trabajo. El aviso anuncia que se realizarán desarrollos adicionales " "de forma privada hasta su finalización. Un pasaje dice:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -871,7 +879,7 @@ msgstr "" " que se aleja de nuestro trabajo pinta una mala imagen para futuros " "esfuerzos de descompilación…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -888,7 +896,7 @@ msgstr "" "que hay detrás. El desacuerdo que quiero discutir es sobre cómo debe " "proceder la reconstrucción y cómo debe juzgarse una contribución." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -902,7 +910,7 @@ msgstr "" "confianza en el colaborador importaba porque gran parte del razonamiento " "ocurría mientras trabajaban." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -913,7 +921,7 @@ msgstr "" "herramientas. Lo que cambió para mí fue que un agente podía usar ese " "conocimiento para llevar a cabo la próxima investigación por su cuenta." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -928,7 +936,7 @@ msgstr "" "Quiero que otra persona pueda examinar por qué elegimos una implementación, " "incluso si un agente hizo la mayor parte del trabajo." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -941,7 +949,7 @@ msgstr "" "Eso plantea preguntas reales sobre el crédito. También cambia lo que los " "mantenedores necesitan saber antes de aceptar una contribución." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -956,7 +964,7 @@ msgstr "" " diseñar el proceso y reconocer cuándo su resultado es incorrecto. " "Diferentes comunidades pueden elegir cuánto de ese cambio quieren asumir." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -981,7 +989,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -994,14 +1002,14 @@ msgstr "" "abreviado. TH08 ' s {ph4}créditos y procedencia{ph5} registre el límite de " "continuación." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: la experiencia comienza a agravarse" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1016,7 +1024,7 @@ msgstr "" "aprender el juego. Pero ya sabíamos mucho más sobre cómo comenzar una " "reconstrucción y cómo mantenerla en marcha." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1030,7 +1038,7 @@ msgstr "" "reconstrucción del Windows i386 se marcó como jugable el 10 de septiembre, " "aproximadamente doce días después de la inicialización." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1042,7 +1050,7 @@ msgstr "" "experiencia ya estaba presente en las herramientas y en la forma en que se " "organizó el proyecto." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1057,7 +1065,7 @@ msgstr "" "Necesitamos verlos trabajar juntos. Esa lección ayudó a dar forma a la forma" " en que abordamos la compilación de todo el programa de TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1070,7 +1078,7 @@ msgstr "" "puede seguir ayudándome después de que haya seguido adelante. El siguiente " "agente puede usar el resultado sin repetir la investigación que lo condujo." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1085,7 +1093,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1097,7 +1105,7 @@ msgstr "" " juego.{ph1} Podemos dedicar más esfuerzo del próximo proyecto a lo que " "realmente es nuevo sobre su objetivo." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1111,7 +1119,7 @@ msgstr "" " proyecto para descubrir por qué la fuente se ve de la manera en que lo " "hace." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: el flujo de trabajo sobrevive a una arquitectura diferente" @@ -1120,7 +1128,7 @@ msgstr "TH04: el flujo de trabajo sobrevive a una arquitectura diferente" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1136,7 +1144,7 @@ msgstr "" "diferente de los juegos Windows. Existentes {ph2}Trabajo ReC98{ph3} también " "nos dio valiosos conocimientos y material de origen aquí." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1149,7 +1157,7 @@ msgstr "" "salvaciones. El trabajo actual es un puerto nativo de 64 bits. Establecer " "una versión de DOS que funcione primero le da a ese puerto una referencia." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1162,7 +1170,7 @@ msgstr "" " Pero el agente aún podría seguir una pregunta hasta un resultado y dejar " "que ese resultado guíe el próximo experimento." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1177,7 +1185,7 @@ msgstr "" "controles estén disponibles, un agente puede resolver la pregunta de la " "misma manera que lo hizo con un título Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1189,7 +1197,7 @@ msgstr "" "trabajar. La arquitectura definió el problema; el flujo de trabajo aún nos " "dio una forma de resolverlo." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1206,7 +1214,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1217,12 +1225,12 @@ msgstr "" "pruebas manuales{ph1} · {ph2}puerto de 64 bits{ph3}. El puerto permanece en " "desarrollo." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Del código exacto al código legible" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1231,7 +1239,7 @@ msgstr "" "Una vez que una reconstrucción funciona, quiero que alguien más pueda " "entenderla." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1246,7 +1254,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1263,7 +1271,7 @@ msgstr "" "el razonamiento con la fuente para que la siguiente persona pueda ver de " "dónde vino esa interpretación." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1278,14 +1286,14 @@ msgstr "" "poseer ese estado. Para mover el comportamiento de manera segura, " "necesitamos recuperar la relación detrás del antiguo acceso a la memoria." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "El orden que uso ahora es:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1301,7 +1309,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1318,7 +1326,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1334,7 +1342,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1349,7 +1357,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1366,7 +1374,7 @@ msgstr "" "verifica que el programa reconstruido aún se construya y se comporte " "correctamente a lo largo de las rutas que ejercitamos." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1380,7 +1388,7 @@ msgstr "" "disponibles le da al agente una falla concreta para investigar antes de " "llevar a cabo una refactorización adicional." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1398,7 +1406,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1417,7 +1425,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1428,12 +1436,12 @@ msgstr "" "semántica hace utilizable el conocimiento recuperado.{ph1} Entonces, un " "puerto puede basarse en ambos." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Qué hace que esto sea un cambio industrial" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1447,7 +1455,7 @@ msgstr "" "hacer. Una herramienta mejor podría ayudar con cada función posterior que la" " necesitara." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1461,7 +1469,7 @@ msgstr "" "que prescriba cada paso, gran parte del trabajo permanece atado a mi " "atención." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1475,7 +1483,7 @@ msgstr "" " de nuevo. Todavía tengo que decidir si la evidencia acumulada respalda un " "hito del proyecto." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1491,7 +1499,7 @@ msgstr "" "usarlos para probar la fuente que propone y ver dónde se sostiene su " "explicación." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1509,7 +1517,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1530,7 +1538,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1548,7 +1556,7 @@ msgstr "" "resultados afectados. El próximo proyecto puede heredar una herramienta más " "sólida." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1564,7 +1572,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1577,7 +1585,7 @@ msgstr "" " y lecciones. Trabajar en un juego puede mejorar las condiciones iniciales " "de otro." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1589,12 +1597,12 @@ msgstr "" "Mejorar esas herramientas cambia cuánto puede hacer la próxima persona, o el" " próximo agente." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Los proyectos que ahora podemos considerar" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1606,7 +1614,7 @@ msgstr "" "atención de la que podría prestarle de manera realista. Muchos proyectos se " "quedarían en ideas." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1624,7 +1632,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1635,7 +1643,7 @@ msgstr "" "retroalimentación y conocimiento acumulado le permitirían a un agente " "trabajar en esto de manera confiable?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1646,12 +1654,12 @@ msgstr "" "Cada uno puede mejorar la forma en que nos acercamos al siguiente. Quiero " "seguir explorando hasta dónde nos puede llevar eso." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Hitos y fuentes del proyecto" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1686,7 +1694,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1721,7 +1729,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1740,7 +1748,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1764,7 +1772,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1787,7 +1795,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1804,7 +1812,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1826,7 +1834,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1841,7 +1849,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1863,27 +1871,27 @@ msgstr "" " Touhou con agentes de IA y cómo el conocimiento se compone en TH08 , TH095 " "y PC-98 TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Experiencia transmitida entre proyectos" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Ensayo de reconstrucción de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -1892,18 +1900,18 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Inicio{ph1}{ph2}/{ph3}Laboratorio de velocidad de dinosaurios" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Inspeccionar → reconstruir → cambiar" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Reconstruye la regla de velocidad del dinosaurio." @@ -1912,7 +1920,7 @@ msgstr "Reconstruye la regla de velocidad del dinosaurio." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1925,15 +1933,15 @@ msgstr "" "usamos su regla para construir este minijuego con {ph2}velocidad " "ajustable.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "En esta página" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1941,7 +1949,7 @@ msgstr "{ph0}Juega y cambia la velocidad{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1949,7 +1957,7 @@ msgstr "{ph0}Lea la regla recuperada{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1957,18 +1965,18 @@ msgstr "{ph0}Compruebe la reconstrucción{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Pruebe el análisis{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Juega y cambia la velocidad" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1980,49 +1988,49 @@ msgstr "" "velocidad fija. Seleccione la regla recuperada para comenzar en 6 y acelerar" " gradualmente nuevamente." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Juega a la reconstrucción" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Jugar" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Saltar ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Reiniciar" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Velocidad" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Utilice la regla de aceleración recuperada" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Regla original: comience en 6, luego aumente hacia 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Mueva el control deslizante para establecer su propia velocidad. Espaciar o " "saltar despeja un cactus." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2031,7 +2039,7 @@ msgstr "" "Habilite JavaScript para reproducir la reconstrucción. El código y la " "explicación anteriores siguen siendo legibles." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Lea el script REA devuelto" @@ -2039,7 +2047,7 @@ msgstr "Lea el script REA devuelto" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2054,7 +2062,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2064,18 +2072,18 @@ msgstr "" "Los ajustes son {ph0}, {ph1} y {ph2}. El juego ejecuta esta rama en una " "actualización sin colisión." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Usa la misma regla en el nuevo juego" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Copiar" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2093,7 +2101,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" @@ -2101,12 +2109,12 @@ msgstr "" "{ph0}Descargar la regla de velocidad{ph1} · {ph2}Leer el código del " "juego{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Compruebe la reconstrucción" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2117,27 +2125,27 @@ msgstr "" "obstáculos y programación automática. Compare esas velocidades registradas " "con una repetición de la regla recuperada." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Actualizaciones" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Juego original" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Regla reconstruida" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Ejecute la verificación de velocidad" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2147,14 +2155,14 @@ msgstr "" " lo que el incremento final puede tomar una velocidad justo por encima de " "13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Pruebe el análisis usted mismo" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2163,7 +2171,7 @@ msgstr "{ph0}Configurar REA {ph1} con su agente de codificación." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2172,7 +2180,7 @@ msgstr "" "Siga el {ph0}pasos de conexión del navegador{ph1}, usando {ph2} como la URL " "de la página." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2189,7 +2197,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2201,7 +2209,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2215,7 +2223,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2230,7 +2238,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2256,12 +2264,12 @@ msgstr "" "Lee la regla de velocidad del juego de dinosaurios con REA, reconstrúyela, " "luego cambia la velocidad y juega." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Reconstrucción de la velocidad de los dinosaurios" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2270,52 +2278,52 @@ msgstr "" "Minijuego de dinosaurios. Usa el botón de salto o presiona la barra " "espaciadora mientras el juego está enfocado." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Copiar regla de velocidad reconstruida" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copie el mensaje de análisis de dinosaurios" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Saltar al contenido" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Inicio{ph1} / Preguntas frecuentes" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA PREGUNTAS frecuentes." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Configuración, actualizaciones, análisis y solución de problemas." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Temas" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2323,7 +2331,7 @@ msgstr "{ph0}Configuración y actualizaciones{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2331,7 +2339,7 @@ msgstr "{ph0}Análisis{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2339,31 +2347,31 @@ msgstr "{ph0}Solución de Problemas{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Datos e intercambio{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Configuración y actualizaciones" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "¿Cómo instalo REA ?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * configuración del agente" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Copiar" @@ -2371,7 +2379,7 @@ msgstr "Copiar" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2385,12 +2393,12 @@ msgstr "" "ruta del archivo y una pregunta. La {ph0}guía de configuración{ph1} explica " "los requisitos y los pasos de tu primer análisis." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "¿Qué agentes de codificación pueden usar REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2405,18 +2413,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Conecte a su agente de codificación{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "¿Cómo actualizo REA ?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2425,13 +2433,13 @@ msgstr "" "REA se publica con frecuencia, incluidas correcciones de errores. Si instaló" " el CLI con npm :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * instalado CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2441,14 +2449,14 @@ msgstr "" "Siga el comando de actualización de configuración que imprime la " "actualización. Si configura su agente a través de {ph0}, corre:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * actualizar la configuración del agente" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2461,14 +2469,14 @@ msgstr "" " la nueva versión. Para un comando puntual de CLI, añade el comando después " "de {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Está instalando la habilidad desde skills.sh ¿suficiente?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2481,24 +2489,24 @@ msgstr "" "habilidad correspondiente, reinicie su agente para que pueda llamar a las " "herramientas." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Análisis" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "¿Qué puedo analizar con REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Comience con el tipo de software que tiene:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2510,7 +2518,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2522,7 +2530,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2532,7 +2540,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2544,12 +2552,12 @@ msgstr "" "Android, firmware y recursos empaquetados. {ph0}Ver los estudios de " "caso{ph1} para investigaciones trabajadas." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "¿Necesito Hopper, Ghidra o IDA ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2562,7 +2570,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2575,12 +2583,12 @@ msgstr "" "destino determinan qué proveedor se puede utilizar. {ph0}Configurar el " "análisis de programas de código máquina{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "¿Puedo usar REA sin un agente de codificación?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2589,14 +2597,14 @@ msgstr "" "Sí. El CLI utiliza los mismos flujos de trabajo de análisis. Para una " "aplicación JavaScript o Electron local:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * análisis estático de aplicaciones" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2607,13 +2615,13 @@ msgstr "" "{ph0}Utilice el CLI {ph1} para opciones de instalación." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "¿Qué código devuelve REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2628,7 +2636,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2640,12 +2648,12 @@ msgstr "" "probar una implementación. El {ph0} Cálculo de DX-Ball{ph1} y " "{ph2}Comprobador de banderas CTF{ph3} muestre cómo funciona ese proceso." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "¿Qué le pregunto a mi agente?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2662,7 +2670,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2670,7 +2678,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2680,18 +2688,18 @@ msgstr "" "Reemplaza el camino con tu objetivo. El {ph0}guías{ph1} proporcione " "indicaciones para ejemplos nativos, Electron y del navegador." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Solución de Problemas" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "¿Por qué mi agente no puede ver las herramientas REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2701,7 +2709,7 @@ msgstr "" "Reinicie o vuelva a conectar su agente después de la configuración. " "Verifique su registro REA con {ph0}; para Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * compruebe un cliente" @@ -2709,7 +2717,7 @@ msgstr "Terminal * compruebe un cliente" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2720,14 +2728,14 @@ msgstr "" "muestra un registro faltante o obsoleto, ejecute el programa de instalación " "para ese cliente:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * reparar la configuración de un cliente" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2739,14 +2747,14 @@ msgstr "" " herramientas, verifique el error de conexión MCP del cliente. {ph0}Más " "diagnósticos de configuración{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "¿Necesito iniciar Hopper primero?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2759,14 +2767,14 @@ msgstr "" " antes del análisis desatendido. {ph0}Consulte configuración de proveedor " "nativo{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "¿Qué hago si encuentro un error?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2778,7 +2786,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2791,17 +2799,17 @@ msgstr "" " el nombre del proveedor cuando el problema implique el análisis de " "programas de código máquina." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Datos e intercambio" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "¿REA carga mi aplicación?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2810,7 +2818,7 @@ msgstr "" "REA analiza los objetivos en su máquina. Su agente recibe los resultados y " "la política de datos de su proveedor de modelos se aplica a esos resultados." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "¿Cómo puedo compartir un ejemplo o contribuir?" @@ -2819,7 +2827,7 @@ msgstr "¿Cómo puedo compartir un ejemplo o contribuir?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2835,7 +2843,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2863,77 +2871,77 @@ msgstr "" "herramientas de análisis, agentes de codificación, solución de problemas y " "ejemplos para compartir." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Preguntas frecuentes sobre REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Copie el comando de configuración REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Copie el comando de actualización REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Comando de actualización de la configuración del agente de copia" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Copie el comando de análisis REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Copie el mensaje de análisis de ejemplo" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Copie el comando de diagnóstico del cliente" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Copiar comando de configuración de ámbito" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Saltar al contenido" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Inicio{ph1} / Tu primera investigación" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Averigüe dónde{ph0}las notas exportadas van." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2942,14 +2950,14 @@ msgstr "" "Use REA para inspeccionar una aplicación pequeña, siga su botón Exportar " "notas y verifique un detalle usted mismo." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "En este ejercicio" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2957,7 +2965,7 @@ msgstr "{ph0}1. Configurar{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2965,7 +2973,7 @@ msgstr "{ph0}2. Pregunte sobre exportación{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2973,7 +2981,7 @@ msgstr "{ph0}3. Sigue la respuesta{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2981,13 +2989,13 @@ msgstr "{ph0}4. Comprobar una predicción{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Haz otra pregunta{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Conecte a su agente a REA" @@ -3000,29 +3008,29 @@ msgstr "1. Conecte a su agente a REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Copiar" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "O ejecute este comando en su terminal:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3031,14 +3039,14 @@ msgstr "" "Revise el plan, apruebe la configuración y luego reinicie su agente. ¿Ya " "estás conectado? Continúe abajo." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Pregunte dónde está escrito el CSV" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3050,7 +3058,7 @@ msgstr "" "exportación{ph1} botón. Su agente puede inspeccionar su código sin instalar " "ni iniciar Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3062,14 +3070,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Descargar ZIP de ejemplo{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3079,12 +3087,12 @@ msgstr "" "Si su agente no puede descargar archivos, descomprímalo usted mismo. Dale el" " camino al {ph0} carpeta y la misma pregunta de exportación." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Siga la respuesta de regreso al código" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Busque una breve explicación con referencias de archivos y líneas:" @@ -3093,7 +3101,7 @@ msgstr "Busque una breve explicación con referencias de archivos y líneas:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3105,12 +3113,12 @@ msgstr "" "como CSV y escribe {ph1} en la carpeta de descargas del usuario. Las " "columnas son {ph2} y {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Del botón al escritor de archivos" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3119,7 +3127,7 @@ msgstr "" "El análisis estático de REA empareja el mensaje con su controlador. El " "destino se lee del código." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3131,7 +3139,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." @@ -3139,12 +3147,12 @@ msgstr "" "{ph0}Vea el rastreo completo del código y el resultado registrado de " "REA{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Comprobar una predicción" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3153,19 +3161,19 @@ msgstr "" "Una coma separa las columnas CSV. ¿Qué sucede cuando el título de una nota " "contiene una coma o comillas?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Ejecute el cheque usted mismo" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Abra una terminal en el desempaquetado {ph0} carpeta:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3174,17 +3182,17 @@ msgstr "" "Este comando usa un shell compatible con here-document, como Bash o Zsh. Su " "agente puede ejecutar el mismo JavaScript en el shell de su plataforma." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Haz otra pregunta" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Prueba un seguimiento en la misma conversación:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3193,7 +3201,7 @@ msgstr "" "¿Qué sucede si el archivo no se puede escribir? Siga el error de regreso a " "la página." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3206,7 +3214,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3220,7 +3228,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3235,7 +3243,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3260,65 +3268,65 @@ msgstr "" " a dónde van las notas exportadas y verifique el formateador CSV con un " "título de muestra." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Su primera investigación sobre REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Copie el mensaje de instalación de REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Comando Copiar configuración" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Aviso de investigación de Copy Notes" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Copie el mensaje de verificación CSV" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Comando Copiar comprobación del formateador" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Saltar al contenido" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Inicio{ph1} / Empezar" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Configure REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3326,49 +3334,49 @@ msgstr "" "Conecte REA a su agente de codificación o inspeccione una aplicación local " "desde su terminal." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Abra una terminal y verifique:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminal" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Copiar" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3381,7 +3389,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3392,17 +3400,17 @@ msgstr "" "deshabilitada en este sistema\"{ph1} cuando corres {ph2}, ejecute esto una " "vez e inténtelo de nuevo:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Si usa Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "De lo contrario:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Cierre la terminal, ábrala de nuevo y luego:" @@ -3410,7 +3418,7 @@ msgstr "Cierre la terminal, ábrala de nuevo y luego:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3422,7 +3430,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3434,7 +3442,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3444,14 +3452,14 @@ msgstr "" "¿Prefiere un instalador regular? Descargue la versión LTS desde " "{ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Opciones de configuración" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3459,7 +3467,7 @@ msgstr "{ph0}Conecte a su agente de codificación{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3467,7 +3475,7 @@ msgstr "{ph0}Utilice el CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3475,18 +3483,18 @@ msgstr "{ph0}Configurar el análisis de programas de código máquina{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Cómo obtener ayuda{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Conecte a su agente de codificación" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3498,12 +3506,12 @@ msgstr "" "Gemini CLI, Windsurf, Grok Build y otros clientes MCP compatibles. El " "conector de Grok Bot se agrega desde su chat." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "¿Eres nuevo en los agentes de codificación?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3515,7 +3523,7 @@ msgstr "" "ejecutar comandos, y pregunta antes de realizar cambios. REA le brinda " "herramientas de ingeniería inversa." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3527,7 +3535,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3540,7 +3548,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3553,7 +3561,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3563,7 +3571,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}, código abierto. Conecte al proveedor de " "modelos de su elección." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3580,18 +3588,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "O ejecute la configuración usted mismo" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "¿Cómo abro una terminal?" @@ -3600,7 +3608,7 @@ msgstr "¿Cómo abro una terminal?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3616,7 +3624,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3630,7 +3638,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3645,7 +3653,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3655,7 +3663,7 @@ msgstr "" "Pegue un comando con {ph0} {ph1} ( macOS : {ph2} {ph3}; Terminales Linux: " "{ph4} {ph5} {ph6}), luego presione Entrar." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3667,12 +3675,12 @@ msgstr "" "de seguridad de la configuración existente. Pregunta antes de aplicar los " "cambios." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Reinicie su cliente cuando finalice la configuración." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "¿Cómo reinicio mi cliente?" @@ -3681,7 +3689,7 @@ msgstr "¿Cómo reinicio mi cliente?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3697,7 +3705,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3707,7 +3715,7 @@ msgstr "" "{ph0}Agentes terminales{ph1} ( Claude Code, Codex, Gemini CLI ): salga de la" " sesión y vuelva a iniciarla." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3717,7 +3725,7 @@ msgstr "" "aplicación JavaScript o Electron, puede comenzar con:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3728,12 +3736,12 @@ msgstr "" " llamadas y las dependencias involucradas, con las ubicaciones de origen de " "sus hallazgos." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Reemplace la ruta con su objetivo local." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "¿Cómo obtengo la ruta completa de una carpeta?" @@ -3742,7 +3750,7 @@ msgstr "¿Cómo obtengo la ruta completa de una carpeta?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3757,7 +3765,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3770,7 +3778,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3780,19 +3788,19 @@ msgstr "" "{ph0}Cualquier sistema:{ph1} arrastre la carpeta a una ventana de terminal y" " aparecerá su ruta." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "En una terminal, coloque comillas alrededor de una ruta que contenga " "espacios." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Utilice el CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3801,14 +3809,14 @@ msgstr "" "Analice una carpeta de aplicación JavaScript o Electron o un archivo ASAR " "sin ejecutar la aplicación:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Análisis estático de aplicaciones" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3818,13 +3826,13 @@ msgstr "" "Reemplace la ruta con el directorio de la aplicación extraída o {ph0} " "archivo. En Windows, una ruta como {ph1} trabaja aquí." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "¿Dónde encuentro una aplicación?¿archivo asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3836,7 +3844,7 @@ msgstr "" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3848,7 +3856,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3861,14 +3869,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} a menudo {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3876,7 +3884,7 @@ msgstr "" "Algunas aplicaciones se instalan en otro lugar. Busque en la carpeta de la " "aplicación {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3888,31 +3896,31 @@ msgstr "" "se pueden resolver están marcadas en el resultado." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Si desea un permanente {ph0} comando en tu shell:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Instale el CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Continúe con la guía de aplicación del JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Configurar el análisis de programas de código máquina" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3922,12 +3930,12 @@ msgstr "" " Elija y configure uno a continuación, luego proporcione a REA su ejecutable" " o biblioteca." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Elija una herramienta: Ghidra, Hopper o IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3939,17 +3947,17 @@ msgstr "" "necesita un descompilador nativo para su arquitectura de host. Establezca " "las rutas antes de ejecutar la configuración:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Conecte su instalación de Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Conexión Ghidra * macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3961,12 +3969,12 @@ msgstr "" "seleccionado. En Linux arm64, es posible que deba compilar el descompilador " "nativo de Ghidra por separado." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Conecte Ghidra en Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3977,12 +3985,12 @@ msgstr "" " y x64 PE nativas y DLL en unidades NTFS locales fijas. Utilice un Ghidra " "12.1 existente.instalación de x y un JDK 21 de 64 bits o más reciente:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Conexión Ghidra · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3990,7 +3998,7 @@ msgstr "" "Reemplace las dos rutas con sus instalaciones, luego revise el plan de " "configuración." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -4000,7 +4008,7 @@ msgstr "" "anterior; detecta una instalación existente u ofrece un plan de instalación " "para su aprobación." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -4009,7 +4017,7 @@ msgstr "" "En macOS , complete la opción de primera ejecución de Hopper de modo de " "demostración o activación de licencia antes de un análisis desatendido." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -4020,7 +4028,7 @@ msgstr "" "existente para una GUI adjunta o una base de datos sin cabecera. El " "análisis sin cabeza Linux y macOS permanece sin verificar." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Conecte un registro IDA MCP existente" @@ -4030,7 +4038,7 @@ msgstr "Conecte un registro IDA MCP existente" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4042,13 +4050,13 @@ msgstr "" " un archivo JSON. Un existente {ph3} objeto con un {ph4} también se acepta " "la entrada. Apunte REA a ese archivo antes de la configuración:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Conexión IDA · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4066,7 +4074,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4078,18 +4086,18 @@ msgstr "" "Para un agente, incluya {ph1} en el entorno del registro REA y seleccione " "IDA al abrir el binario." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Para una configuración Ghidra existente, inspeccione una función con:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Análisis de funciones" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." @@ -4097,13 +4105,13 @@ msgstr "" "Reemplazar {ph0} con el nombre de la función o la dirección que desea " "inspeccionar." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "" "Cómo funcionan las sesiones de análisis de programas de código máquina" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4116,7 +4124,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4126,18 +4134,18 @@ msgstr "" "{ph0}Siga un ejemplo de análisis de programas de código máquina{ph1} para " "ver cómo el resultado de la función conduce a un cálculo recuperado." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Cómo obtener ayuda" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Si su agente no ve REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4147,27 +4155,27 @@ msgstr "" "Reinicie o vuelva a conectar el cliente después de la configuración. " "Compruebe su conexión REA con {ph0}; para Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Compruebe un cliente" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Si un proveedor necesita atención" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Verifique el proveedor que está usando. Para Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Consulte a un proveedor" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4177,7 +4185,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4190,7 +4198,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4204,7 +4212,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4218,7 +4226,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4243,112 +4251,112 @@ msgstr "" "JavaScript o Electron local desde la terminal. Configuración, primeras " "preguntas y guías nativas para proveedores." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Copiar comprobación de la versión Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Copie el comando de instalación de Node.js para Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Copie el comando de política de ejecución de PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Copie el comando de instalación Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Copie el comando de instalación fnm para macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Copie los 24 comandos Node.js para macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Copie el comando de instalación fnm para Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Copie los 24 comandos Node.js para Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "Guía de introducción al REA" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Copie el mensaje de instalación de REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Comando Copiar configuración del agente" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Copie el comando de análisis JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Copie el comando de instalación de CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Copiar el comando de conexión de Ghidra para macOS y Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Copie la conexión Ghidra para Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Copie la conexión IDA para Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Copiar comando de análisis de funciones nativas" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Copie el comando de diagnóstico del cliente" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Copie el comando de diagnóstico del proveedor" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -4357,20 +4365,20 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Inicio{ph1} / {ph2}Guías{ph3} / Observación del navegador" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Vea lo que sucede{ph0}cuando haces clic." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4379,14 +4387,14 @@ msgstr "" "Use una pequeña aplicación de navegador para conectar una acción, su " "solicitud de red y el JavaScript que genera una descarga." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "En esta guía" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4394,7 +4402,7 @@ msgstr "{ph0}El ejemplo{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4402,7 +4410,7 @@ msgstr "{ph0}Abra el navegador{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4410,7 +4418,7 @@ msgstr "{ph0}Pregúntele a su agente{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4418,13 +4426,13 @@ msgstr "{ph0}Captura desde CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Lea la solicitud y el script{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "¿Qué sucede cuando haces clic en Exportar?" @@ -4434,7 +4442,7 @@ msgstr "¿Qué sucede cuando haces clic en Exportar?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4446,7 +4454,7 @@ msgstr "" "exportación{ph3} botón. Al hacer clic en él, se carga {ph4}, formatea las " "dos notas como CSV e inicia una descarga ." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Del clic a la descarga de CSV" @@ -4457,7 +4465,7 @@ msgstr "Del clic a la descarga de CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4473,7 +4481,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4492,7 +4500,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4502,17 +4510,17 @@ msgstr "" "{ph0}03 * Su agente{ph1}{ph2}Lea el código de exportación{ph3}{ph4}Conecte " "la solicitud observada a {ph5} en {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Inicie la captura antes de hacer clic en Exportar notas." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Abra Chrome con depuración remota" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4521,21 +4529,21 @@ msgstr "" "Abra el ejemplo de Hosted Notes con un perfil de navegador independiente y " "un puerto de depuración local. En Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Inicie el navegador de ejemplo" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Copiar" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4544,7 +4552,7 @@ msgstr "" "Utilice la ruta ejecutable de su navegador instalado en macOS o Windows . " "Puede reemplazar la URL de la página con otra página que desee inspeccionar." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4553,7 +4561,7 @@ msgstr "" "REA se conecta a este navegador existente. Usted mantiene el control de la " "página, realiza la acción y cierra el navegador cuando termina." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Pídale a su agente que vea una acción" @@ -4566,7 +4574,7 @@ msgstr "Pídale a su agente que vea una acción" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4578,7 +4586,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4590,7 +4598,7 @@ msgstr "" "CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4601,7 +4609,7 @@ msgstr "" "{ph0}, y la URL de la página. Deje que inicie la captura antes de hacer " "clic." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4612,23 +4620,23 @@ msgstr "" "y lee la evidencia resultante. Luego puede inspeccionar el script detrás de " "la exportación." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "O captura desde la terminal" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Encontrar el ID de destino de la página:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Encuentra la página" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4638,14 +4646,14 @@ msgstr "" "Elija el destino con la URL de ejemplo de Notes. Reemplazar {ph0} abajo con " "su ID, luego ejecute:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Captura los siguientes diez segundos" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4656,7 +4664,7 @@ msgstr "" "{ph0}Notas de exportación{ph1} en ese navegador. El resultado llega después " "de que finaliza la ventana de observación." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4667,49 +4675,49 @@ msgstr "" "red durante esa ventana y la forma de la respuesta JSON. Las solicitudes " "anteriores están fuera de esta captura." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Leer el script de solicitud y exportación" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Grabado con REA 4.1.0 en el ejemplo de notas locales" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Hecho capturado" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Valor" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Solicitud" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Respuesta" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Iniciador de la solicitud" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * guión" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Estructura de respuesta" @@ -4717,19 +4725,19 @@ msgstr "Estructura de respuesta" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} con {ph1} y {ph2} campos" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Leer los scripts cargados" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4741,7 +4749,7 @@ msgstr "" "datos:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4754,7 +4762,7 @@ msgstr "" "solicitó este clic {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4766,7 +4774,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4792,65 +4800,65 @@ msgstr "" "navegador, capture un clic, inspeccione la solicitud y siga el script de " "exportación." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Observación del navegador" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Copie inicie el navegador de ejemplo" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Copie el mensaje de ejemplo" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Copiar buscar la página" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Copia captura los siguientes diez segundos" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Copiar leer los scripts cargados" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Saltar al contenido" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Inicio{ph1} / Guías" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Guías REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4859,37 +4867,37 @@ msgstr "" "Analice una función nativa, una exportación Electron o una solicitud del " "navegador. Cada guía incluye un mensaje, código y resultados." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Primera investigación" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Configurar REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Conecte su agente de codificación o use REA desde la terminal." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Comience con REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Programas de código máquina" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Recuperar un cálculo de la posición del sonido izquierda/derecha" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4899,22 +4907,22 @@ msgstr "" "siga a la persona que llama, lea las constantes numéricas y verifique la C " "recuperada." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Guía de análisis de programas de código máquina" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript y Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Siga una exportación de CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4924,14 +4932,14 @@ msgstr "" "la precarga y el proceso principal. Utilice REA para conectar la API, el " "canal IPC y el escritor de archivos." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Guía JavaScript y Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4939,17 +4947,17 @@ msgstr "" "Para obtener una aplicación empaquetada más grande, siga {ph0} Puente del " "portapapeles de Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Comportamiento del navegador" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Observar un clic" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4958,7 +4966,7 @@ msgstr "" "Abra un ejemplo de notas de trabajo, capture una solicitud de exportación y " "busque el código que convierte su respuesta en una descarga." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Guía de observación del navegador" @@ -4977,12 +4985,12 @@ msgstr "" "Aprenda REA a través de breves ejemplos trabajados: un cálculo nativo, una " "exportación Electron CSV y una solicitud del navegador." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -4991,20 +4999,20 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Inicio{ph1} / {ph2}Guías{ph3} / JavaScript y Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Rastrear un Electron {ph0} Exportación CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -5013,14 +5021,14 @@ msgstr "" "Haga clic en un botón desde la API de la página, a través de Electron IPC, " "hasta el escritor de archivos CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "En esta guía" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -5028,7 +5036,7 @@ msgstr "{ph0}El ejemplo{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5036,7 +5044,7 @@ msgstr "{ph0}Pregúntele a su agente{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5044,7 +5052,7 @@ msgstr "{ph0}Rastrear el código de exportación{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5052,20 +5060,20 @@ msgstr "{ph0}Prueba el ejemplo{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Inspeccione la grabadora CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "¿A dónde van las \"Notas de exportación\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5077,7 +5085,7 @@ msgstr "" "de exportación{ph1} llama a una API en la página, cruza al proceso principal" " y escribe un CSV . El comportamiento se distribuye en varios archivos." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "La exportación CSV a través de procesos Electron" @@ -5091,7 +5099,7 @@ msgstr "La exportación CSV a través de procesos Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5108,7 +5116,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5125,7 +5133,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5138,13 +5146,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} formatea las notas → {ph1} escribe {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5155,14 +5163,14 @@ msgstr "" " API expuesta. La ruta se infiere del código; una captura en tiempo de " "ejecución puede verificar qué se ejecuta." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Pregunte por la exportación CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5180,14 +5188,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Copiar" @@ -5198,7 +5206,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5209,7 +5217,7 @@ msgstr "" "esta aplicación. ¿Dónde se crea el CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5219,7 +5227,7 @@ msgstr "" "Mensaje de ejemplo. Incluya la ruta absoluta a la carpeta de la aplicación o" " {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5230,17 +5238,17 @@ msgstr "" "módulos y límites de procesos. Su agente usa ese mapa para limitar la " "investigación a la función de exportación." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Rastrear el código de exportación" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "La página llama a una pequeña API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5251,7 +5259,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5263,7 +5271,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5274,7 +5282,7 @@ msgstr "" "notas y el proceso principal escribe {ph1} en la carpeta de descargas del " "usuario." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5284,7 +5292,7 @@ msgstr "" "ubicaciones de origen acompañan a los hallazgos de la API, el canal y el " "controlador." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Analice el ejemplo usted mismo" @@ -5292,25 +5300,25 @@ msgstr "Analice el ejemplo usted mismo" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Descargar ZIP de ejemplo{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Explore los seis archivos fuente" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Análisis estático de aplicaciones" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5321,7 +5329,7 @@ msgstr "" "canal IPC y un controlador coincidente en {ph0}. Las ubicaciones de origen " "están en {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5332,13 +5340,13 @@ msgstr "" "ASAR. Un agente puede seguir una cadena literal, un nombre de API o un canal" " IPC con las herramientas de rastreo de funciones de REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Inspeccione la grabadora CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5348,7 +5356,7 @@ msgstr "" "Sigue {ph0} a su manejador. ¿Qué entradas llegan al escritor CSV y qué " "sucede si falla la escritura del archivo?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5364,7 +5372,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5378,7 +5386,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5392,7 +5400,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5418,32 +5426,32 @@ msgstr "" "precarga y controlador IPC con REA . Incluye archivos de ejemplo " "descargables y un resultado de análisis verificado." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript y Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Copie el mensaje de ejemplo" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Copiar análisis de aplicaciones estáticas" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -5452,7 +5460,7 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5460,7 +5468,7 @@ msgstr "" "{ph0}Inicio{ph1} / {ph2}Guías{ph3} / Análisis de programas de código máquina" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." @@ -5468,7 +5476,7 @@ msgstr "" "Recuperar DX-Ball 's{ph0}cálculo de la posición del sonido izquierda / " "derecha." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5477,14 +5485,14 @@ msgstr "" "Inspeccione las instrucciones originales, identifique la entrada y las " "constantes, luego verifique la C recuperada." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "En esta guía" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5492,7 +5500,7 @@ msgstr "{ph0}El ejemplo{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5500,7 +5508,7 @@ msgstr "{ph0}Pregúntele a su agente{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5508,7 +5516,7 @@ msgstr "{ph0}Lea los resultados del REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5516,18 +5524,18 @@ msgstr "{ph0}Recuperar y comprobar{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Usa tu propio binario{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Calcular el posicionamiento del sonido estéreo izquierdo/derecho" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5539,7 +5547,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5551,7 +5559,7 @@ msgstr "" " llamada a {ph1}. REA también devuelve sus instrucciones y llamadas, que le" " dan al agente una forma de investigar la aritmética faltante." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "¿Eres nuevo en estos términos?" @@ -5560,7 +5568,7 @@ msgstr "¿Eres nuevo en estos términos?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5572,7 +5580,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5585,7 +5593,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5598,7 +5606,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5610,7 +5618,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5620,7 +5628,7 @@ msgstr "" "{ph0}Constantes:{ph1} números fijos almacenados en el programa, leídos como " "bytes sin procesar y decodificados." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Tres pruebas, un cálculo" @@ -5631,7 +5639,7 @@ msgstr "Tres pruebas, un cálculo" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5649,7 +5657,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5667,7 +5675,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5678,7 +5686,7 @@ msgstr "" "numéricas{ph3}{ph4}Decodificación de bytes referenciados a {ph5}, {ph6} y un" " valor de escala.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5687,7 +5695,7 @@ msgstr "" "REA proporciona las instrucciones, la relación función-llamada y los bytes. " "El agente los interpreta juntos." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Pregunte sobre el comportamiento" @@ -5696,7 +5704,7 @@ msgstr "Pregunte sobre el comportamiento" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5707,19 +5715,19 @@ msgstr "" "herramienta de análisis de programas de código máquina{ph3}, proporcione el " "ejecutable local y una pregunta:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "¿Qué herramienta de análisis debo usar?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA necesita uno de estos para leer programas nativos:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5733,7 +5741,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5746,7 +5754,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5757,7 +5765,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5773,14 +5781,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Copiar" @@ -5791,7 +5799,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5802,7 +5810,7 @@ msgstr "" "posicionamiento del sonido estéreo. Explique el cálculo y muestre el " "código.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5813,7 +5821,7 @@ msgstr "" "DX-Ball 1.07. REA no incluye DX-Ball, así que use su propia copia o haga el" " mismo tipo de pregunta sobre otro pequeño programa Windows que tenga." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "¿Cómo obtengo la ruta completa de un archivo?" @@ -5822,7 +5830,7 @@ msgstr "¿Cómo obtengo la ruta completa de un archivo?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5837,7 +5845,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5850,7 +5858,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5860,17 +5868,17 @@ msgstr "" "{ph0}Cualquier sistema:{ph1} arrastre el archivo a una ventana de terminal y" " aparecerá su ruta." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Lea los resultados del REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Lea la entrada" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5880,13 +5888,13 @@ msgstr "" " de coma flotante. Esta es la entrada ausente en la primera vista de " "pseudocódigo." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Siga a la persona que llama" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5897,12 +5905,12 @@ msgstr "" "instrucciones anteriores multiplican la coordenada del mosaico por 30; " "sumando {ph0} (20) da la posición de la pantalla del ladrillo." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Lee las constantes a las que se hace referencia" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5912,12 +5920,12 @@ msgstr "" "proporciona los valores reales; el orden de instrucción le dice al agente " "cómo se usan." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Escriba y verifique la función recuperada" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5928,7 +5936,7 @@ msgstr "" "-500, 0 y 500 antes de la conversión de enteros. El cálculo coloca el centro" " de la pantalla en el centro del campo estéreo." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5941,21 +5949,21 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "" "{ph0}Vea la investigación completa y la comparación de assembly-to-C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Pruébalo con tu propio binario" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5969,7 +5977,7 @@ msgstr "" " para investigar . Las preguntas iniciales útiles incluyen \"¿ Cómo se " "analiza este archivo?\"o\" ¿Qué función maneja esta acción de menú?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5978,13 +5986,13 @@ msgstr "" "Si ya conoce el nombre o la dirección de una función, puede consultarla " "desde el terminal. Para una instalación Ghidra configurada:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Análisis de funciones" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5998,7 +6006,7 @@ msgstr "" " sesión. Las consultas MCP de su agente reutilizan el binario importado " "mientras esa sesión está abierta." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -6022,50 +6030,50 @@ msgstr "" "Recupere un cálculo nativo con REA: inspeccione instrucciones, siga a una " "persona que llama, lea constantes y verifique C reconstruido." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Análisis de programas de código máquina" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Copie el mensaje de ejemplo" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Análisis de la función de copia" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Saltar al contenido" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "En esta página" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Configurar REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6073,7 +6081,7 @@ msgstr "{ph0}Configurar REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6081,7 +6089,7 @@ msgstr "{ph0}¿Qué es RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6089,7 +6097,7 @@ msgstr "{ph0}Cómo ayuda REA{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6097,7 +6105,7 @@ msgstr "{ph0}Juego de dinosaurios{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6105,7 +6113,7 @@ msgstr "{ph0}Calculadora{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6113,7 +6121,7 @@ msgstr "{ph0}Prueba REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6121,7 +6129,7 @@ msgstr "{ph0}Profundiza{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6129,25 +6137,25 @@ msgstr "{ph0}Ayuda y comentarios{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Comunidad{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Ingeniería inversa, con su agente de codificación" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Descubre cómo{ph0}funciona el software." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6158,7 +6166,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6166,13 +6174,13 @@ msgstr "¿Ya conoces RE? {ph0}Saltar a guías de análisis →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "¿Quieres profundizar? {ph0}Leer el Blog →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Copia este prompt en tu agente de programación:" @@ -6185,38 +6193,38 @@ msgstr "Copia este prompt en tu agente de programación:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Copiar" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "O ejecuta esto en la terminal:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Revisa y aprueba los cambios propuestos. Después, reinicia tu agente." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "¿Qué es la ingeniería inversa?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6230,7 +6238,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6242,7 +6250,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6250,7 +6258,7 @@ msgstr "Antes de REA · Lo investigas {ph0}por tu cuenta{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6258,7 +6266,7 @@ msgstr "{ph0}01{ph1} Decodificar ramas" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6266,7 +6274,7 @@ msgstr "{ph0}02{ph1} Rastrear llamadas" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6276,20 +6284,20 @@ msgstr "{ph0}03{ph1} Recuperar la regla" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Original x64 * instrucciones seleccionadas{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * ¿Qué sucursal?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6299,29 +6307,29 @@ msgstr "" "“{ph0}¿0x5b? ¿0x5c?{ph1} Dos saltos al mismo lugar. ¿Qué operadores son " "estos?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Busque los ID de comando y luego etiquete la rama." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Divide ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Multiplicar ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · ¿Qué hacen las funciones llamadas?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6331,25 +6339,25 @@ msgstr "" "\"100 está claro. Las llamadas son solo direcciones. {ph0}¿Cuál divide? ¿Qué" " valor entra?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "" "Inspeccione las funciones auxiliares y rastree los valores almacenados." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Divide" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * ¿Cuál es la regla?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6359,20 +6367,20 @@ msgstr "" "\"Esta ruta se multiplica por la otra entrada. Entonces {ph0}10% significa " "10% de 200{ph1} después de +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "" "Asigne un nombre a los operandos y verifique ambas rutas de operadores." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Razonamiento experto ilustrativo" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6384,20 +6392,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Con REA · Le preguntas a {ph0}tu agente{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Un solo prompt." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6411,21 +6419,21 @@ msgstr "Pregúntale a tu agente {ph0}con palabras normales.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ejemplo de indicador * Calculadora" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Respuesta de ejemplo * basada en los hallazgos" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6433,29 +6441,29 @@ msgid "" msgstr "" "Después de +, el botón % toma {ph0}un porcentaje del primer número.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA proporciona" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Instrucciones del manejador, código descompilado y llamadas." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Tu agente explica" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Qué rama se aplica, qué calcula y cómo reconstruirla." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6468,7 +6476,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6478,37 +6486,37 @@ msgstr "" "{ph0}Probemos con dos ejemplos.{ph1} Cambia la velocidad de un juego, luego " "regresa a la Calculadora y reconstruye su botón%." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Ejemplo 01 * Juego de dinosaurios de Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "¿Por qué el dinosaurio va cada vez más rápido?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Objetivo" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Reconstruye el juego con {ph0}velocidad ajustable.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "¿Por qué realizar ingeniería inversa?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6518,49 +6526,49 @@ msgstr "" "Para reproducir su aceleración, necesitamos {ph0}la regla en el juego " "terrestre{ph1}: qué tan rápido comienza, cuánto aumenta y cuándo se detiene." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Juega a la reconstrucción" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Jugar" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Saltar ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Reiniciar" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Velocidad" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Utilice la regla de aceleración recuperada" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Regla original: comience en 6, luego aumente hacia 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Mueva el control deslizante para establecer su propia velocidad. Espaciar o " "saltar despeja un cactus." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6569,14 +6577,14 @@ msgstr "" "Habilite JavaScript para reproducir la reconstrucción. El código y la " "explicación anteriores siguen siendo legibles." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA devolvió" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6595,7 +6603,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6609,7 +6617,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6623,7 +6631,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6637,7 +6645,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6647,12 +6655,12 @@ msgstr "" "{ph0}Comience a las 6.{ph1} Añadir {ph2}0.001{ph3} cada actualización sin " "colisión, mientras que la velocidad es inferior {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Abra el laboratorio de velocidad →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Qué hace cada parte" @@ -6663,7 +6671,7 @@ msgstr "Qué hace cada parte" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6679,7 +6687,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6696,7 +6704,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6706,13 +6714,13 @@ msgstr "" "{ph0}03 * Tú{ph1}{ph2}Cambia la velocidad y juega{ph3}{ph4}Prueba la " "aceleración original y luego elige tu propio ritmo.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Vea el script, las comprobaciones y cómo probar el análisis" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6723,7 +6731,7 @@ msgstr "" "depuración local y devolvió el archivo cargado {ph0}, incluyendo su fuente y" " resumen." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6737,7 +6745,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6754,7 +6762,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6772,7 +6780,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6781,19 +6789,19 @@ msgstr "" "{ph0}Código de velocidad inspeccionado{ph1} · {ph2} Chromium Autores * " "Licencia BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Ejemplo 02 * Calculadora Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Recrea el botón % de la calculadora." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6804,7 +6812,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6815,29 +6823,29 @@ msgstr "" "Inspeccionamos la aplicación instalada para encontrar a qué número se aplica" " el porcentaje." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Prueba el cálculo" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Restablecer" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% de 200 = 20. Entonces 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Ilustración interactiva de la regla de porcentaje inspeccionado." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6849,7 +6857,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6863,7 +6871,7 @@ msgstr "Para este ejemplo, {ph0} y {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6879,7 +6887,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6891,7 +6899,7 @@ msgstr "" "Windows. Recupere las reglas después de + y×, luego construya una pequeña " "calculadora que use ambas.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Con +" @@ -6899,13 +6907,13 @@ msgstr "Con +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Toma el 10% del primer número.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Con ×" @@ -6913,13 +6921,13 @@ msgstr "Con ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Convierta el 10% en 0.1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Desde la aplicación instalada hasta un botón % que funciona" @@ -6931,7 +6939,7 @@ msgstr "Desde la aplicación instalada hasta un botón % que funciona" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6948,7 +6956,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6960,12 +6968,12 @@ msgstr "" "reglas{ph3}{ph4}Verifique la sucursal con la fuente de Microsoft, luego " "intente + y × arriba.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Vea el código real y cómo se verificó la respuesta" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6986,7 +6994,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6996,17 +7004,17 @@ msgstr "" "{ph0}Porcentaje de implementación{ph1} · {ph2}Casos de prueba de " "Microsoft{ph3} · {ph4}Guía de configuración nativa{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Su primera investigación" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Pruebe REA en una aplicación pequeña." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -7015,12 +7023,12 @@ msgstr "" "Descargue nuestro ejemplo de Notes, rastree su exportación CSV y verifique " "una entrada modificada." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Pruebe el ejemplo guiado" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "¿Quieres profundizar?" @@ -7029,7 +7037,7 @@ msgstr "¿Quieres profundizar?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7049,14 +7057,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ejemplo de solicitud * Sitio web" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Sí, esta." @@ -7069,7 +7077,7 @@ msgstr "Sí, esta." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7084,7 +7092,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7098,23 +7106,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Vea el estudio de caso de DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Para los pasos de configuración y análisis, elija su objetivo:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Programas de código máquina" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7123,17 +7131,17 @@ msgstr "" "Inspeccione funciones, cadenas, referencias y relaciones función-llamada en " "ejecutables y bibliotecas." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Guía de análisis de programas de código máquina" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript y Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7142,17 +7150,17 @@ msgstr "" "Asigne módulos, rutas, IPC y dependencias nativas desde una carpeta de " "aplicaciones o un archivo ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Flujos de trabajo de aplicaciones" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Actividad del navegador y del tiempo de ejecución" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7161,12 +7169,12 @@ msgstr "" "Capture la actividad seleccionada del navegador o del proceso y, a " "continuación, compare los resultados entre ejecuciones." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Guía de observación del navegador" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "¿Tienes preguntas?" @@ -7177,7 +7185,7 @@ msgstr "¿Tienes preguntas?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7188,12 +7196,12 @@ msgstr "" "{ph3}, o {ph4}abrir un problema de GitHub{ph5} para errores y solicitudes de" " funciones." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Únete a la comunidad" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7217,27 +7225,27 @@ msgstr "" "comportamiento del navegador con su agente de codificación. Siga guías " "claras y pruebe ejemplos interactivos con REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Copie el mensaje de instalación de REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Comando Copiar configuración" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Siga el análisis manual de la calculadora" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Copiar pregunta de porcentaje de la calculadora" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7246,37 +7254,37 @@ msgstr "" "Minijuego de dinosaurios. Usa el botón de salto o presiona la barra " "espaciadora mientras el juego está enfocado." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copie el mensaje de análisis de dinosaurios" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Elija el cálculo" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Copie el mensaje de análisis de la calculadora" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Copie el mensaje del proyecto del sitio web" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Copiar mensaje de reconstrucción del juego" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -7285,26 +7293,26 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Inicio{ph1} / {ph2}Vitrinas{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Caso práctico * Autenticador Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "" "Cómo funciona un autenticador{ph0}¿generar un código de inicio de sesión?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7314,17 +7322,17 @@ msgstr "" " cálculo en un APK de Android y luego reconstrúyelo con un reloj que puedas " "controlar." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * Versión oficial APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Ver Aegis en GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Desde un APK hasta un código que puedes reproducir" @@ -7335,7 +7343,7 @@ msgstr "Desde un APK hasta un código que puedes reproducir" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7353,7 +7361,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7371,7 +7379,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7383,14 +7391,14 @@ msgstr "" "código.{ph3}{ph4}Una nueva demostración del navegador reproduce la regla y " "la compara con casos de referencia pública.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "En este estudio de caso" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7398,7 +7406,7 @@ msgstr "{ph0}Pregúntele a su agente{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7406,7 +7414,7 @@ msgstr "{ph0}Pruebe el generador de código{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7414,7 +7422,7 @@ msgstr "{ph0}Encuentra el código con REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7422,7 +7430,7 @@ msgstr "{ph0}Lea el cálculo{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7430,20 +7438,20 @@ msgstr "{ph0}Compruebe la reconstrucción{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Inspeccione el APK usted mismo{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Pregúntele a su agente" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7461,21 +7469,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Copiar" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7485,14 +7493,14 @@ msgstr "" "Un mensaje de ejemplo para el APK descargado, con el análisis de Android de " "REA configurado. {ph0}Obtenga el APK y la configuración de análisis ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Pruebe el generador de código" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7504,33 +7512,33 @@ msgstr "" "el número de bloque con la clave de cuenta para generar un código. La misma " "clave y bloque producen el mismo código." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Mueve el reloj 60 segundos" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Tiempo" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "segundos" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Nuestro reloj de ejemplo ajustable" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "bloque de 30 segundos" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Bloque" @@ -7539,35 +7547,35 @@ msgstr "Bloque" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 segundos{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Código generado" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Clave de cuenta + bloque → seis dígitos" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Tiempo de ejemplo, en segundos" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 segundos" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 segundos" @@ -7576,7 +7584,7 @@ msgstr "60 segundos" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7588,7 +7596,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7598,7 +7606,7 @@ msgstr "" "La clave es fija, pública {ph0}Datos de prueba RFC 6238{ph1}. La " "demostración implementa el cálculo recuperado del APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7607,18 +7615,18 @@ msgstr "" "El diagrama muestra el resultado a los 59 segundos. Habilite JavaScript para" " cambiar el reloj." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Encuentra el código con REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Reduzca el APK a tres clases" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7629,14 +7637,14 @@ msgstr "" "progreso y las cuentas importadas. TOTP significa una contraseña de un solo" " uso basada en el tiempo." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Conecte el generador a la pantalla de la aplicación" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7648,7 +7656,7 @@ msgstr "" "llamando {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7658,14 +7666,14 @@ msgstr "" "Las solicitudes muestran una ruta de entrada acortada. Los nombres de clase " "de resultado omiten lo común {ph0} prefijo." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Lea el cálculo" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7680,7 +7688,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7688,7 +7696,7 @@ msgstr "{ph0}01{ph1} Bloque de tiempo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7696,7 +7704,7 @@ msgstr "{ph0}02{ph1} Tecla + bloque" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7704,7 +7712,7 @@ msgstr "{ph0}03{ph1} Seis dígitos" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7716,7 +7724,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7730,7 +7738,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7745,7 +7753,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7756,7 +7764,7 @@ msgstr "" "mostrar. El panel de la derecha es un resumen explicativo. {ph0} El código " "Aegis es GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Dentro del generador" @@ -7765,7 +7773,7 @@ msgstr "Dentro del generador" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7775,7 +7783,7 @@ msgstr "" "El APK lanzado pone {ph0} en {ph1}. REA sigue la llamada de {ph2} y " "devuelve este cuerpo; la fuente original llama al ayudante {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7792,20 +7800,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Compare con la fuente de publicación correspondiente{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Compruebe la reconstrucción" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7818,29 +7826,29 @@ msgstr "" "independiente en {ph0}133 casos de prueba{ph1}, incluidos los límites de los" " bloques de tiempo y los códigos que comienzan con cero." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Tiempo de ejemplo" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Código de seis dígitos" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 segundos" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 segundos" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7851,17 +7859,17 @@ msgstr "" "publicados en {ph0}RFC 6238 (en inglés){ph1}. Compare la implementación del " "navegador con ellos:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Ejecutar comprobaciones de referencia" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Lea el cálculo de la demostración" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7870,7 +7878,7 @@ msgstr "" "Los casos de referencia usan ocho dígitos. La verificación también verifica " "sus resultados de seis dígitos." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7879,14 +7887,14 @@ msgstr "" "La verificación ejecuta métodos Java extraídos y la nueva demostración. El " "Android APK fue inspeccionado estáticamente." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Inspeccione el APK usted mismo" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7898,7 +7906,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7908,18 +7916,18 @@ msgstr "" "El análisis de Android necesita un JDK 17 completo o posterior. Selecciónelo" " con {ph0} o {ph1}. Este caso usó JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Apunte REA al archivo del proveedor e inspeccione el APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7932,7 +7940,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7942,7 +7950,7 @@ msgstr "" "Una pregunta siguiente: {ph0}¿qué sucede cuando una cuenta usa ocho dígitos " "o un intervalo de tiempo diferente?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Fuentes" @@ -7958,7 +7966,7 @@ msgstr "Fuentes" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7972,7 +7980,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" @@ -7980,7 +7988,7 @@ msgstr "" "{ph0}Casos de referencia RFC 6238{ph1} · {ph2}Datos de prueba de " "demostración{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -8006,37 +8014,37 @@ msgstr "" "inicio de sesión de seis dígitos e intente una reconstrucción con un reloj " "ajustable." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Estudio de caso Aegis APK" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Copie el indicador de ejemplo Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Siga el cálculo del código de inicio de sesión" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Copie el comando de inspección APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -8045,26 +8053,26 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Inicio{ph1} / {ph2}Vitrinas{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Estudio de caso · DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Encuentra la bandera en{ph0}un binario CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8075,18 +8083,18 @@ msgstr "" "sus reglas en ecuaciones y encontrar una entrada que haga que se imprima el " "programa original {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "" "comprobador de banderas de cuadrados enmascarados * Fácil * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Ver el desafío original" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "De una respuesta binaria a una respuesta marcada" @@ -8097,7 +8105,7 @@ msgstr "De una respuesta binaria a una respuesta marcada" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8115,7 +8123,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8133,7 +8141,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8145,7 +8153,7 @@ msgstr "" "¡Correcto!{ph3}{ph4}Un script de Python resuelve las ecuaciones. REA " "captura el programa original aceptando el resultado.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." @@ -8153,14 +8161,14 @@ msgstr "" "El desafío es de joseph, publicado en el repositorio oficial de " "DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "En este estudio de caso" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8168,7 +8176,7 @@ msgstr "{ph0}Encuentra el código de verificación{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8176,7 +8184,7 @@ msgstr "{ph0}Leer una máscara{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8184,7 +8192,7 @@ msgstr "{ph0}Ensamblado a código legible{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8192,7 +8200,7 @@ msgstr "{ph0}Resuelve las ecuaciones{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8200,20 +8208,20 @@ msgstr "{ph0}Revisa la respuesta{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Pruébalo tú mismo{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Encuentra el código de verificación" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8231,17 +8239,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Copiar" @@ -8252,7 +8260,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8264,7 +8272,7 @@ msgstr "" "indicador. Explique cómo funcionan las comprobaciones y luego verifique la " "respuesta con el programa original.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8273,12 +8281,12 @@ msgstr "" "Un mensaje de ejemplo, con el desafío descargado disponible localmente y un " "análisis del proveedor de programas de código máquina conectado." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Siga el indicador de entrada a su función" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8287,14 +8295,14 @@ msgstr "" "La referencia le da al agente un lugar para investigar, aunque se hayan " "eliminado los nombres de funciones originales del ejecutable." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Lea el corrector y sus dos ayudantes" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8307,7 +8315,7 @@ msgstr "" "resultado con un número almacenado. Su {ph0}- pasos de bytes a través {ph1} " "los bytes dan 26 máscaras." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8317,12 +8325,12 @@ msgstr "" "destino local se acorta para su visualización; las direcciones se refieren a" " la imagen importada de REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Un cheque revela un carácter" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8336,7 +8344,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." @@ -8344,7 +8352,7 @@ msgstr "" "La séptima comprobación selecciona solo una posición. {ph0}Figura " "abierta{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Lea la máscara y su objetivo desde el binario" @@ -8353,7 +8361,7 @@ msgstr "Lea la máscara y su objetivo desde el binario" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8365,12 +8373,12 @@ msgstr "" "razón {ph1} significa -21. El objetivo es un entero little-endian. Juntos, " "estos bytes le dicen al agente que {ph2}, entonces ese personaje es {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "De las instrucciones a un cheque legible" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8381,7 +8389,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8389,7 +8397,7 @@ msgstr "{ph0}01{ph1} Inicio" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8397,7 +8405,7 @@ msgstr "{ph0}02{ph1} Seleccione" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8405,7 +8413,7 @@ msgstr "{ph0}03{ph1} Añadir" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8413,18 +8421,18 @@ msgstr "{ph0}04{ph1} Avance" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Comparar" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * instrucciones originales seleccionadas" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Resumen legible de C * one-check" @@ -8432,7 +8440,7 @@ msgstr "Resumen legible de C * one-check" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8440,7 +8448,7 @@ msgstr "{ph0}01 * Comience en cero.{ph1} {ph2} contiene la suma corriente." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8452,7 +8460,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8464,7 +8472,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8478,7 +8486,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8488,7 +8496,7 @@ msgstr "" "{ph0}05 * Comparar con el objetivo almacenado.{ph1} La persona que llama " "recibe la suma en {ph2}. Un desajuste salta a {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8498,12 +8506,12 @@ msgstr "" "La C es un resumen explicativo con nombres descriptivos y un bucle aplanado " "de 36 celdas." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Resuelve las 26 ecuaciones" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8515,13 +8523,13 @@ msgstr "" "1441. Las selecciones superpuestas dan ecuaciones que un pequeño script de " "Python puede resolver juntas." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Extracto de Python * solver" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8535,19 +8543,19 @@ msgstr "" "letras, dígitos, guiones bajos y llaves. La descarga completa incluye las 26" " máscaras y objetivos." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Descargue el solucionador completo" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Verifique la respuesta con el programa original" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8559,47 +8567,47 @@ msgstr "" "indicador resuelto. Cambiar un carácter seleccionado de {ph0} para {ph1} " "hace la primera suma 1440 en lugar de 1441, y el programa la rechaza." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Entrada" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Salida observada" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Código de salida" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Bandera del solucionador" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Un personaje cambió" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Mostrar el indicador recuperado y la salida capturada" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * salida del programa original" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Bandera de copia" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8609,12 +8617,12 @@ msgstr "" "desafío publicados por los organizadores, marcada después de resolver el " "binario." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Detalles de origen, identidad de destino y análisis" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8625,7 +8633,7 @@ msgstr "" "utilizando REA 4.1.0 con Ghidra 12.1.4 en Linux x64. El binario es un ELF " "x86-64 despojado, 15.248 bytes." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8648,7 +8656,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8658,12 +8666,12 @@ msgstr "" "{ph0}Compare con la fuente de los organizadores{ph1} · {ph2}Metadatos de " "desafío y bandera{ph3} · {ph4} Notas de evidencia REA{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Pruébalo tú mismo" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8672,13 +8680,13 @@ msgstr "" "Descargue el desafío original y el solucionador en una carpeta. Utilice el " "mensaje anterior para investigar con su agente o ejecute el script incluido." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * resuelve y ejecuta" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8690,7 +8698,7 @@ msgstr "" "programa. Resolviendo necesidades Python y {ph0}. Ejecutar el ejecutable " "original necesita Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Configure REA con su agente de codificación" @@ -8711,29 +8719,29 @@ msgstr "" "de DownUnderCTF. Encuentre las funciones de verificación, extraiga las " "máscaras y compare un indicador recuperado con el programa original." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Estudio de caso de CTF flag-checker" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Copie el mensaje de ejemplo de CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "" "Ecuación de máscara CTF; desplácese horizontalmente en pantallas más " "pequeñas" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8744,42 +8752,42 @@ msgstr "" "14. Solo esa celda contribuye a la suma. Su código de carácter requerido es " "55, lo que significa que el carácter es 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Siga la verificación CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Copie la asamblea CTF" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Verificación CTF legible por copia" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Copiar extracto del solucionador CTF" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Copiar bandera recuperada" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Copiar comandos del solucionador CTF" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -8788,25 +8796,25 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Inicio{ph1} / {ph2}Vitrinas{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Estudio de caso * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Reconstruyendo DX-Ball {ph0}desde su ejecutable." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8815,14 +8823,14 @@ msgstr "" "El objetivo es una versión C mantenible del juego Windows de 1996. REA " "ayuda al agente a inspeccionar el original, una función a la vez." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8834,14 +8842,14 @@ msgstr "" "instrucciones, las personas que llaman y las lecturas de datos; el proyecto " "de reconstrucción implementa y prueba el resultado. {ph0}Figura abierta{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "En este estudio de caso" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8849,7 +8857,7 @@ msgstr "{ph0}El proyecto{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8857,7 +8865,7 @@ msgstr "{ph0}Bandeja de sonido{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8865,23 +8873,23 @@ msgstr "{ph0}Comprobando el resultado{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Continuar el trabajo{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "funciones C mantenidas" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "comparaciones con el código original" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "funciones con bytes compilados coincidentes" @@ -8892,7 +8900,7 @@ msgstr "funciones con bytes compilados coincidentes" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8902,12 +8910,12 @@ msgstr "" "Punto de control del proyecto: 7 de octubre de 2026. {ph0}Libro de " "progreso{ph1} · {ph2}Cobertura de la prueba{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "El proyecto hasta ahora" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8923,12 +8931,12 @@ msgstr "" "física de la pelota y la paleta, el manejo del encendido y la integración " "Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Encontrar el cálculo de la posición del sonido izquierda/derecha" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8947,17 +8955,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Copiar" @@ -8968,7 +8976,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8979,7 +8987,7 @@ msgstr "" "posicionamiento del sonido estéreo. Explique el cálculo y muestre el " "código.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8990,7 +8998,7 @@ msgstr "" "local disponible. La investigación a continuación muestra las consultas REA " "y la evidencia detrás de la respuesta." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -9005,7 +9013,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9019,12 +9027,12 @@ msgstr "" "entrada de pila y operaciones de coma flotante. Esa discrepancia le dio al " "agente una razón concreta para seguir investigando." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "La primera vista del descompilador" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -9033,18 +9041,18 @@ msgstr "" "La salida muestra una llamada de conversión. Al leer las instrucciones a " "continuación, se revela la entrada y el cálculo que alimenta esa llamada." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Tres preguntas respondidas a través de REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Recuperar la entrada faltante" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9055,14 +9063,14 @@ msgstr "" " las personas que llaman. Aquí, {ph0} expone la entrada entera que falta en " "la vista del descompilador." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Siga a la persona que llama para comprender la entrada" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9073,12 +9081,12 @@ msgstr "" " instrucciones anteriores {ph0} por 30; sumando 20 da la coordenada de la " "pantalla del ladrillo, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Leer los valores detrás de las direcciones de memoria" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9088,12 +9096,12 @@ msgstr "" "panorámica inicial. El agente ahora tiene los valores necesarios para la " "expresión C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "De los hallazgos de REA a C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9104,7 +9112,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9112,7 +9120,7 @@ msgstr "{ph0}01{ph1} Entrada" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9120,7 +9128,7 @@ msgstr "{ph0}02{ph1} Multiplicar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9128,7 +9136,7 @@ msgstr "{ph0}03{ph1} Restar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9136,18 +9144,18 @@ msgstr "{ph0}04{ph1} Escala" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Regreso" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Original x86 · extracto" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Reconstruido C" @@ -9157,7 +9165,7 @@ msgstr "Reconstruido C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9177,7 +9185,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9193,7 +9201,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9211,7 +9219,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9228,7 +9236,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9241,7 +9249,7 @@ msgstr "" "resultado a {ph4}; original-las comparaciones x86 verifican el valor " "devuelto." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9252,23 +9260,23 @@ msgstr "" "aritmética y retorno. La lista completa a continuación también incluye las " "tiendas intermedias y la configuración y limpieza de funciones." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Montaje completo y pruebas de apoyo" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA resultado * 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Lo que suministra la persona que llama" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9278,54 +9286,54 @@ msgstr "" "La función de golpe de ladrillo en {ph0} escala su coordenada de mosaico en " "30, agrega 20 y luego la empuja antes de la llamada:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Lo que establecen las lecturas de los datos" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "Lecturas de bytes REA, decodificadas como dobles little-endian" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Dirección" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Valor" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Utilizado para" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Primera multiplicación" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Resta" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} inicialmente" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Escala de pan almacenada" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9342,7 +9350,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9352,12 +9360,12 @@ msgstr "" "{ph0}Fuente mantenida{ph1} · {ph2}Notas de investigación y referencias de " "evidencia{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Comprobando la función recuperada" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9367,12 +9375,12 @@ msgstr "" "coinciden con el original y sus bytes compilados coinciden con el " "ejecutable." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 casos de conducta" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9383,12 +9391,12 @@ msgstr "" "con la C mantenida. Cubren cada posición entera de 0 a 640 en cinco escalas " "panorámicas: 0, 0.5, 1, 20 y -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 bytes coincidentes" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9400,7 +9408,7 @@ msgstr "" "aplicar las reubicaciones revisadas y verificar las constantes a las que se " "hace referencia." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9415,18 +9423,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Lea los detalles de la repetición del compilador{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Continuar la investigación" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9438,7 +9446,7 @@ msgstr "" "funciones relevantes, recupere su estado y dependencias, luego compare la " "implementación con la original." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9448,7 +9456,7 @@ msgstr "" "instrucciones de configuración del proyecto DX-Ball y proporcione su " "objetivo original correspondiente. Entonces corre:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "En la caja de DX-Ball" @@ -9457,7 +9465,7 @@ msgstr "En la caja de DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9471,7 +9479,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9487,7 +9495,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9512,7 +9520,7 @@ msgstr "" "mantenido, pruebas originales-x86 y bytes de funciones compiladas " "coincidentes." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9520,7 +9528,7 @@ msgstr "" "DX-Ball investigación panorámica de sonido; desplácese horizontalmente en " "pantallas más pequeñas" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9536,70 +9544,70 @@ msgstr "" "independiente con el x86 original en 3205 casos y mediante la reproducción " "del compilador VC4.0 que coincide con 63 bytes." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Estudio de caso de reconstrucción DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Copie el mensaje de ejemplo" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Siga el cálculo de la posición del sonido izquierda/derecha" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Copiar extracto original de la asamblea" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Copiar función de panorámica de sonido" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Copie el ensamblaje completo de la bandeja de sonido" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Copie el comando de análisis DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Saltar al contenido" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Inicio{ph1} / Vitrinas" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "Estudios de caso de REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9608,17 +9616,17 @@ msgstr "" "Android, juegos, Electron y un desafío CTF, con código, cifras y resultados " "comprobados." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Análisis de Android * APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Cómo genera un autenticador un código de inicio de sesión" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9629,22 +9637,22 @@ msgstr "" "publicado. Rastree los métodos de generación con REA, luego mueva un reloj " "de demostración para ver por qué el código cambia cada 30 segundos." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Lea el caso práctico de Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Análisis de programas de código máquina" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Resolver un comprobador de banderas CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9655,22 +9663,22 @@ msgstr "" "funciones de verificación, convierta máscaras y sumas en ecuaciones, luego " "verifique el indicador resuelto con el programa original." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Lea el estudio de caso de CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Reconstrucción nativa ·" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "Cálculo de la posición del sonido izquierdo/derecho de DX-Ball" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9682,22 +9690,22 @@ msgstr "" "que llaman y las constantes numéricas conducen a una pequeña función C, " "comprobada con el comportamiento original y los 63 bytes compilados." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Lea el caso práctico de DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Rastreo de funciones" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Cómo Notion copia texto y HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9709,22 +9717,22 @@ msgstr "" "luego vea cómo un pequeño marcador HTML mantiene los datos enriquecidos del " "bloque conectados a una copia." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Lea el caso práctico de Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "Reconstrucción PC-98 DOS *" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Cómo TH04 apunta a un anillo de balas" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9735,17 +9743,17 @@ msgstr "" "coincidir sus operaciones de multiplicación, división y coordinación con C++" " legible, luego vea cómo producen un anillo dirigido al jugador." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Lea el caso práctico de TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Guías paso a paso" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9755,7 +9763,7 @@ msgstr "" "solicitud del navegador. Cada uno comienza con un mensaje y un objetivo " "concreto." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Lea las guías" @@ -9775,12 +9783,12 @@ msgstr "" "demostraciones: un autenticador de Android, DX-Ball, Notion, TH04 y un " "comprobador de indicadores de DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -9789,25 +9797,25 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Inicio{ph1} / {ph2}Vitrinas{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Estudio de caso * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Cómo copia Notion{ph0}texto y HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9817,12 +9825,12 @@ msgstr "" "través de la precarga y el proceso principal, hasta el escritor del " "portapapeles de Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Escritorio Notion 7.6.1 * JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "El puente dentro del paquete de escritorio de Notion" @@ -9834,7 +9842,7 @@ msgstr "El puente dentro del paquete de escritorio de Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9851,7 +9859,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9868,7 +9876,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9885,7 +9893,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9896,13 +9904,13 @@ msgstr "" "escribe el texto y HTML suministrados.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Un canal une los dos lados: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9912,14 +9920,14 @@ msgstr "" "principal. Al resolver los contenedores, se revelan las llamadas Electron " "detrás de esos nombres." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "En este estudio de caso" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9927,7 +9935,7 @@ msgstr "{ph0}Sigue el puente del portapapeles{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9935,19 +9943,19 @@ msgstr "{ph0}Mantener la estructura de un bloque{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Más ejemplos y fuentes{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "¿A dónde va la operación de copia?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9967,17 +9975,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Copiar" @@ -9988,7 +9996,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9998,7 +10006,7 @@ msgstr "" "{ph0}›{ph1}{ph2}Use REA para rastrear cómo Notion copia texto y HTML en el " "portapapeles del sistema. Muestre el código en cada paso.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -10007,12 +10015,12 @@ msgstr "" "Un mensaje de ejemplo con el paquete de aplicaciones locales de Notion " "disponible para su agente de codificación." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA encuentra dónde comenzar a leer" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -10023,13 +10031,13 @@ msgstr "" "la página y la llamada que envía una solicitud IPC. Ambos hallazgos vienen " "con rangos de origen en el paquete minimizado:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "Hallazgos REA → dos lugares para abrir" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10043,7 +10051,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10057,12 +10065,12 @@ msgstr "" "nombre le da al agente algo preciso que buscar en el paquete principal. Los " "cuatro extractos a continuación muestran la ruta que conecta." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Cuatro piezas cortas de código" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -10071,13 +10079,13 @@ msgstr "" "Simplificado a partir del JavaScript empaquetado , con nombres de variables " "legibles. Se omiten los miembros no relacionados." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Comience en la API expuesta en la página" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10087,13 +10095,13 @@ msgstr "" "Este miembro proporciona el nombre del canal. La implementación de {ph0} nos" " dice cómo la solicitud sale del proceso de la página." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Resolver el contenedor de la precarga" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10104,14 +10112,14 @@ msgstr "" "respuesta de Electron. Ahora podemos buscar {ph0} en el lado del proceso " "principal." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Compruebe cómo está registrado el destinatario" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10121,12 +10129,12 @@ msgstr "" "El proceso principal usa otro envoltorio. Su {ph0} el método registra un " "{ph1} receptor para ese canal." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Encuentre la escritura y su verificación de remitente" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10137,13 +10145,13 @@ msgstr "" "los datos proporcionados a la API del portapapeles de Electron. El canal y " "los dos envoltorios resueltos conectan el método expuesto a esta llamada." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "¿Cómo mantiene su estructura un bloque copiado?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10154,27 +10162,27 @@ msgstr "" "datos del bloque localmente y coloca una IDENTIFICACIÓN en el HTML copiado " "para conectarlos." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Enlaces HTML a los datos de bloque guardados" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Leer el ID HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Encuentre la misma identificación local" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Restaurar datos de bloque Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10184,7 +10192,7 @@ msgstr "" "bloque cuando los ID coinciden; una entrada obsoleta devuelve solo texto y " "HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10193,24 +10201,24 @@ msgstr "" "Al pegar, Notion busca el ID HTML y lo compara con la copia guardada. Los ID" " coincidentes restauran los datos del bloque." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Formato de portapapeles grabado a partir de activos web almacenados en caché" " el 13 de julio de 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Más ejemplos y fuentes" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Otro ejemplo: Tablas de rebajas" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10219,12 +10227,12 @@ msgstr "" "Notion analiza Markdown en datos de bloque. Este ejemplo muestra cómo una " "tabla se convierte en encabezado y filas de datos." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Una tabla a través del analizador de rebajas de Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10233,13 +10241,13 @@ msgstr "" "Salida grabada de un analizador Markdown extraído. La tabla se convierte en " "filas y celdas." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Otra ruta: la conexión SQLite sin conexión" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10253,7 +10261,7 @@ msgstr "" "otro a un proceso de utilidad SQLite. Los lotes de declaraciones posteriores" " y los resultados viajan por ese puerto." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10263,7 +10271,7 @@ msgstr "" " por qué rastrear solo la solicitud inicial de IPC pierde la conversación " "posterior." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Fuentes y cómo leer los extractos" @@ -10271,7 +10279,7 @@ msgstr "Fuentes y cómo leer los extractos" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10289,7 +10297,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10305,7 +10313,7 @@ msgstr "" "guardadas ejecutaron módulos extraídos y arneses pequeños; sus resultados " "describen esas sondas en lugar de una sesión de IU de escritorio capturada." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10320,7 +10328,7 @@ msgstr "" "implementaciones de envoltura en el paquete." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10338,7 +10346,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10352,7 +10360,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10378,52 +10386,52 @@ msgstr "" "los contenedores IPC y el proceso principal, con breves extractos de código " "y un vistazo a su rico formato de portapapeles." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Estudio de caso Notion Electron" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Copie el indicador de análisis Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Copie el extracto de precarga de Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Copiar extracto del contenedor de invocación Notion" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Copie el extracto del contenedor del controlador Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Copiar extracto del receptor del portapapeles Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Restauración de datos enriquecidos del portapapeles al pegar" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Volver arriba" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Saltar al contenido" @@ -10432,25 +10440,25 @@ msgstr "Saltar al contenido" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Inicio{ph1} / {ph2}Vitrinas{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Estudio de caso * Touhou 4: Historia de Lotus Land" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Reconstruyendo los TH04{ph0}patrones de bala." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10460,17 +10468,17 @@ msgstr "" "inspeccionar la función DOS original, luego siga sus instrucciones en C ++ " "legible." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 · DOS de 16 bits * C++ y ensamblado" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Ver la reconstrucción del TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "De las instrucciones originales a la fuente verificada" @@ -10481,7 +10489,7 @@ msgstr "De las instrucciones originales a la fuente verificada" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10497,7 +10505,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10515,7 +10523,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10531,7 +10539,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10543,7 +10551,7 @@ msgstr "" " comprobaciones grabadas del compilador cubren el código de generación de " "viñetas que contiene este ayudante.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10552,14 +10560,14 @@ msgstr "" "REA devuelve el código original y su evidencia de análisis. El proyecto TH04" " proporciona las comprobaciones de código fuente y compilador mantenidas." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "En este estudio de caso" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10567,7 +10575,7 @@ msgstr "{ph0}El anillo de bala{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10575,7 +10583,7 @@ msgstr "{ph0}Qué devuelve REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10583,7 +10591,7 @@ msgstr "{ph0}Ensamblado a C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10591,18 +10599,18 @@ msgstr "{ph0}Comprobando la fuente{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}El proyecto completo{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Cómo apunta un anillo al jugador" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10621,16 +10629,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Su agente de codificación" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Copiar" @@ -10641,7 +10649,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10652,7 +10660,7 @@ msgstr "" "lo apunta al jugador. Explique el cálculo y muestre el " "código.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10662,7 +10670,7 @@ msgstr "" "reconstrucción disponibles localmente." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10676,7 +10684,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10687,12 +10695,12 @@ msgstr "" " dirección del jugador 40 y la rotación de la plantilla 0. {ph0}Figura " "abierta{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "La plantilla de cocción en la fuente recuperada" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Ataque anular de Elly * extracto de la fuente" @@ -10701,7 +10709,7 @@ msgstr "Ataque anular de Elly * extracto de la fuente" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10711,13 +10719,13 @@ msgstr "" "Estas líneas seleccionan el patrón antes de la dificultad y el ajuste del " "rendimiento. {ph0}Lea la fuente del ataque{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Qué devuelve REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10729,12 +10737,12 @@ msgstr "" "cada bala. REA devuelve sus instrucciones, pseudocódigo y referencias. Tres" " partes de ese resultado explican el patrón." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Verifique la imagen de DOS antes de leer su código" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10743,7 +10751,7 @@ msgstr "" "La comprobación vincula el código cargado y los registros de reubicación al " "ejecutable suministrado. La ruta anterior se acorta para su visualización." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Lee el anillo multiplica y divide" @@ -10751,7 +10759,7 @@ msgstr "Lee el anillo multiplica y divide" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10763,12 +10771,12 @@ msgstr "" "luego la división usa el recuento leído de {ph1}. La fuente mantenida nombra" " ese campo {ph2}. La secuencia completa aparece a continuación." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Encuentra dónde se dirige el patrón hacia el jugador" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10781,12 +10789,12 @@ msgstr "" "anillo. Los nombres de origen hacen que esas direcciones sean legibles; REA " "permite al agente verificar las operaciones originales detrás de ellas." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Del ensamblado al C ++ legible" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10799,7 +10807,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10807,7 +10815,7 @@ msgstr "{ph0}01{ph1} Índice" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10815,7 +10823,7 @@ msgstr "{ph0}02{ph1} Espacio" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10823,7 +10831,7 @@ msgstr "{ph0}03{ph1} Objetivo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10831,18 +10839,18 @@ msgstr "{ph0}04{ph1} Rotar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Tienda" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * instrucciones originales de 16 bits" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Resumen de anillo dirigido legible por C++ ·" @@ -10850,7 +10858,7 @@ msgstr "Resumen de anillo dirigido legible por C++ ·" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10864,7 +10872,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10880,7 +10888,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10895,7 +10903,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10910,7 +10918,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10924,7 +10932,7 @@ msgstr "" " como lo hace la conversión de bytes sin signo. La fuente circundante " "también convierte este ángulo y velocidad en velocidad." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10936,7 +10944,7 @@ msgstr "" "comprobaciones del compilador a continuación se aplican a la fuente " "mantenida en el proyecto vinculado." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Lea el anillo mantenido y apunte la fuente" @@ -10953,7 +10961,7 @@ msgstr "Lea el anillo mantenido y apunte la fuente" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10963,12 +10971,12 @@ msgstr "" "{ph0}Macro de anillo{ph1} · {ph2}Objetivo y fuente de velocidad{ph3} · " "{ph4}Representación de ángulos{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Comprobación de la fuente mantenida" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10978,12 +10986,12 @@ msgstr "" "generación de viñetas, incluido este ayudante, con su cadena de herramientas" " Turbo C++ 4.0 J anclada." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2.139 bytes coincidentes" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10992,12 +11000,12 @@ msgstr "" "El código compilado de generación de viñetas coincide con una sección de " "2139 bytes del ejecutable original." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Dos construcciones limpias" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -11011,7 +11019,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." @@ -11019,59 +11027,59 @@ msgstr "" "Grabado el 3 de octubre de 2026. {ph0}Leer las comprobaciones del " "compilador{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Identidad del objetivo y alcance del análisis" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Objetivo original" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156,258 bytes, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Entrada auxiliar" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} en la imagen cargada de REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Desplazamiento del archivo original" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, devuelto por {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Inspección de código grabado" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 de octubre de 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11082,7 +11090,7 @@ msgstr "" " al MAPA y la reubicación superpuesta." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11098,7 +11106,7 @@ msgstr "" "rangos informados." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11115,7 +11123,7 @@ msgstr "" " suministrado está anclada por su manifiesto de repositorio, con la " "procedencia independiente de volcado prístino aún abierta." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11126,12 +11134,12 @@ msgstr "" " tiempo y el comportamiento del hardware PC-98 tienen comprobaciones de " "tiempo de ejecución separadas en el proyecto de reconstrucción." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "La reconstrucción completa del TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11144,7 +11152,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11156,7 +11164,7 @@ msgstr "{ph0}Explore el repositorio TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11172,7 +11180,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11189,7 +11197,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11215,22 +11223,22 @@ msgstr "" "ensamblado y el C ++ recuperado para ver cómo se separa un anillo de balas y" " se apunta al jugador." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "En esta página" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "Estudio de caso del patrón de bala TH04" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Copie el indicador de ejemplo TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11238,7 +11246,7 @@ msgstr "" "TH04 anillos de bala fijos y apuntados; desplácese horizontalmente en " "pantallas más pequeñas" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11251,27 +11259,27 @@ msgstr "" "misma cantidad; la primera viñeta resaltada apunta hacia el jugador. Ambos " "mantienen un espaciado de 16 unidades de ángulo, o 22.5 grados." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Copie la plantilla de cocción TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Siga el cálculo del anillo apuntado TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Copie el extracto de la asamblea TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Cálculo de anillo apuntado legible por copia" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Volver arriba" @@ -11381,7 +11389,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Velocidad fija: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11391,7 +11399,7 @@ msgstr "" "verificación controlada del juego original cuando se redondean a tres " "decimales." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11763,591 +11771,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Mismo espaciado: 256 ÷ 16 = 16 unidades de ángulo = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Casos prácticos" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Primeros pasos" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Guías" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Código fuente" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Licencia MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Únete a la comunidad" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Síguenos en X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * fuente de script seleccionada" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Código fuente" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Salida esperada del formateador" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Instrucciones" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Llamador" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Constantes" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Función C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Botón" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API de precarga" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Archivo CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Su clic" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Solicitud capturada" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Script de exportación" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA resultado · resumen.extracto de ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "Extracto de instrucciones REA * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "Extracto de la persona que llama REA * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "Resultados de bytes REA * interpretados como dobles little-endian" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Extracto recuperado de C *" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Mira cómo funciona REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Vitrinas →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Configuración seleccionada del script inspeccionado" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Resumen legible del controlador %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * instrucciones originales seleccionadas" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "ID de operador * Fuente de Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Sigue a @ reatools en X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agente → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → agente * resultados seleccionados" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → agente * métodos y llamadores" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * Java descompilado seleccionado" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Resumen legible * interpretación del agente" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, cuerpo completo" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Descargar Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Descargar proveedor de análisis de Android" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agente → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → agente * resultados seleccionados" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → agente * instrucciones seleccionadas" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agente → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → agente * séptima entradas" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Ejecutable original * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Descarga el desafío original" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Descargar solver" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA resultado * extracto de pseudocódigo" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agente → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → extracto de instrucciones del agente ·" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → extracto del agente * llamante" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agente → REA * dos {ph0} solicitudes" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Resultados de bytes REA * decodificados como dobles" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Comience con su propio objetivo" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Generando código" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Regla recuperada" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Reloj ajustable" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Binario" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Comprobación del código" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Ecuaciones" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "¡Correcto!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Ejecutable" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Hallazgos REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Recuperado C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Validación" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Aplicación empaquetada" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "API expuesta" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Envoltorios IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Portapapeles" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Código DOS original" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Instrucciones REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Cálculo de ángulos" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Anillo de bala" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "API de página expuesta" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Llamada IPC del renderizador" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Enviado al portapapeles del sistema" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Guardado localmente por Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Entrada de rebajas" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Salida estructurada del analizador · extracto" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analiza tu propia app" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agente → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → agente * campos seleccionados" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agente → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → extracto de instrucciones del agente ·" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Resultado de la misma función · extracto del objetivo" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Correspondiente C ++ mantenido" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Macro de anillo * Rama TH04, extracto" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Ángulo y velocidad · extracto de la fuente" @@ -12381,7 +12397,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12399,7 +12415,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12420,7 +12436,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12441,7 +12457,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12460,7 +12476,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12479,7 +12495,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12490,14 +12506,14 @@ msgstr "" "por mí.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Reconstrucción * {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12508,7 +12524,7 @@ msgstr "" "agente de codificación y revise los cambios propuestos." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12517,7 +12533,7 @@ msgstr "Un ejemplo proporcionado · {ph0} y npm * Su agente de codificación" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12536,7 +12552,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12552,7 +12568,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12571,7 +12587,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12582,7 +12598,7 @@ msgstr "" " en {ph7} y escribe el archivo.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12597,7 +12613,7 @@ msgstr "{ph0} * líneas 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12610,7 +12626,7 @@ msgstr "" " predicción y la salida real.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12621,7 +12637,7 @@ msgstr "" "Esto verifica el formateador directamente con {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12629,7 +12645,7 @@ msgstr "{ph0} · CSV formateador" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12638,7 +12654,7 @@ msgstr "" "Necesitarás {ph0} 22 (22.19+), 24 (24.11+) o 26+. npm viene con {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12646,7 +12662,7 @@ msgstr "No tengo {ph0}, ¿ o no estás seguro?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12659,7 +12675,7 @@ msgstr "" "{ph1} 24 LITROS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12673,7 +12689,7 @@ msgstr "{ph0} * extracto de fuente de ejemplo" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12684,9 +12700,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12694,7 +12710,7 @@ msgstr "{ph0} * fuente de ejemplo" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12709,7 +12725,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12722,7 +12738,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12736,7 +12752,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12747,7 +12763,7 @@ msgstr "" "{ph3} da 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12756,7 +12772,7 @@ msgstr "REA * cargado {ph0} * líneas seleccionadas" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12774,7 +12790,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12793,7 +12809,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12806,28 +12822,28 @@ msgstr "" "demo donde pueda cambiar la hora.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * Miembro API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * Ayudante de IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "principal/{ph0} * ayudante del manejador" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12837,12 +12853,1434 @@ msgstr "principal/{ph0} * receptor del portapapeles" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Primeros pasos {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Cambiar al modo claro" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Cambiar al modo oscuro" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Para examinar los cuerpos de las solicitudes y respuestas HTTP, use " +"{ph0}Fiddler Everywhere: capturas SAZ, MCP y habilidades públicas{ph1}. " +"Exporte SAZ o HAR 1.2 para obtener Evidence de capturas en REA sin conexión," +" o conecte el servidor MCP de Everywhere para inspeccionar el tráfico " +"capturado con su agente." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Modelos especializados{ph0}Ensayo" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "¿Necesita la ingeniería inversa un modelo más grande?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Lo que la reconstrucción de Touhou sugiere sobre los modelos generales, los " +"especializados y el aprendizaje a partir de los resultados del compilador." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Por N0zoM1z0 · 13 de octubre de 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Saltar al contenido" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Inicio{ph1} / {ph2}Blog{ph3} / Modelos e ingeniería inversa" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "ensayo" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "¿La ingeniería inversa necesita un modelo más grande?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Por N0zoM1z0 · 13 de octubre de 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Ideas clave" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}La capacidad del modelo afecta qué hipótesis puede proponer un agente " +"de IA.{ph1} Las sesiones posteriores resolvieron problemas que el trabajo " +"anterior había dejado sin resolver." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Un compilador familiar ofrece patrones concretos para que los aprenda " +"un modelo especializado.{ph1} Algunas coincidencias exactas de código de " +"máquina dependen de patrones de código fuente específicos y reutilizables." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Incluya el conocimiento del repositorio en una comparación justa.{ph1} " +"Es posible que un modelo más pequeño con una buena recuperación de " +"conocimiento ya tenga suficiente información para avanzar." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Entrene el modelo para elegir el siguiente experimento útil y pruebe su" +" verificador.{ph1} La retroalimentación es útil solo en la medida en que el " +"verificador verifica lo correcto." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Evaluar los resultados de reconstrucción verificados junto con el " +"tiempo y el costo.{ph1} Eso es lo que quiero medir para todo el flujo de " +"trabajo del agente de IA." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "En este artículo" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Qué cambiaron los modelos más capaces{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}¿Por qué especializarse?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}¿Dónde debería almacenarse esta experiencia?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Aprendiendo el próximo experimento útil{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Ingeniería inversa y aprendizaje por refuerzo{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Cuando el verificador está equivocado{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Una comparación que vale la pena realizar{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}¿Qué tipo de agente de IA sugiere esto?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Qué cambiaron los modelos más capaces" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Desde agosto de 2026, he estado explorando cuánta ingeniería inversa puede " +"realizar un agente con acceso a un programa y una forma de comprobar su " +"funcionamiento. La mayor parte de mi experiencia proviene de la " +"reconstrucción de juegos, especialmente Touhou. A medida que he ido " +"cambiando de modelo, los repositorios han ido manteniendo un registro de lo " +"que cada sesión logró recuperar." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Gran parte de ese trabajo apunta a una reconstrucción exacta: compilamos la " +"fuente mantenida bajo una cadena de herramientas histórica con versiones " +"fijas y comprobamos si reproduce la función de destino. Cuando un modelo " +"posterior tiene éxito donde el trabajo anterior se estancó, los cambios en " +"las fuentes muestran qué hizo posible ese progreso." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Los valores temporales debían seguir siendo válidos al mismo tiempo" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Gran parte de la lógica de la función de ataque TH09 ya había sido " +"reconstruida, pero el compilador aún almacenaba resultados temporales de " +"manera diferente al original. El problema restante era cuánto tiempo " +"necesitaban esos resultados para permanecer vivos y cuándo se podía " +"reutilizar su almacenamiento." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Un registro de sesión {ph0}GPT-6-Sol{ph1} informó esta discrepancia después " +"de probar varias disposiciones de código fuente ordinarias. Cuando " +"{ph2}GPT-6.1-Sol examinó el problema nuevamente{ph3}, propuso una hipótesis " +"útil sobre la vida útil de estas variables temporales." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"La función produjo resultados temporales y los copió en posiciones de " +"animación. En C++, un resultado temporal permanece vivo hasta que finaliza " +"la expresión que lo utiliza. Agrupar las operaciones reales en una expresión" +" mantuvo esos resultados vivos juntos, por lo que el compilador ya no pudo " +"reutilizar el mismo almacenamiento para todos ellos." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Un resultado aún compartía almacenamiento con un valor utilizado más " +"adelante para comprobaciones de colisiones. Darle a ese valor su propia vida" +" útil resolvió la superposición restante. Después de varios experimentos " +"específicos, {ph0}una recompilación limpia del código fuente confirmó que la" +" función completa coincidía{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Me interesa saber cómo el descubrimiento y las pruebas se apoyaron " +"mutuamente. La hipótesis sobre la vida temporal de los objetos dio al agente" +" de IA una nueva dirección. Los comentarios del compilador le ayudaron a " +"refinar esa hipótesis hasta convertirla en una disposición de código fuente " +"que coincidiera." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Un gráfico de flujo de control diferente" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Una segunda función TH09 muestra por qué esa nueva dirección puede ser " +"importante. Aquí el obstáculo fue cómo varias ramas compartieron su trabajo " +"final. El trabajo anterior de {ph0}GPT-6.1-Sol{ph1} consiguió que partes de " +"la función coincidieran, pero las ramas aún se unían de manera diferente al " +"original." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra cambió el gráfico de flujo de control circundante{ph1}. Los" +" caminos principales conducían ahora a una actualización final compartida y " +"al regreso. En esa estructura fuente, el compilador combinó las ramas de la " +"misma manera que el original. La función completa coincidió y una " +"{ph2}verificación de reconstrucción separada lo confirmó{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Cambiar la representación abrió un espacio de búsqueda más " +"productivo.{ph1} Ambos casos me dan una razón para tomar en serio la " +"capacidad del modelo general: un agente puede seguir probando variaciones " +"locales durante mucho tiempo antes de encontrar una mejor manera de expresar" +" el trabajo circundante." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Las sesiones posteriores también heredaron el código anterior y los intentos" +" fallidos documentados. Esa experiencia acumulada formaba parte de su " +"ventaja. El historial permite examinar los hallazgos y sus comprobaciones; " +"una comparación controlada ayudaría a separar el efecto del modelo del de la" +" experiencia que recibió." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Esto es lo que hace que la pregunta me resulte interesante. Algunos avances " +"se produjeron al encontrar una nueva representación. Gran parte del trabajo " +"restante implicó probar diferentes disposiciones de código fuente con un " +"compilador familiar. ¿Cuánto de esto requiere una amplia capacidad de " +"razonamiento? ¿Cuánto podría aprender un modelo trabajando repetidamente con" +" ese compilador y código?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "¿Por qué podría funcionar bien un modelo de IA especializado?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou nos da una razón concreta para esperar que esa experiencia ayude. " +"Gran parte del código del juego proviene del mismo autor, ZUN, por lo que " +"los hábitos recurrentes son una suposición inicial razonable. Los " +"repositorios respaldan esto con ejemplos útiles: bucles relacionados y " +"arreglos de ayuda han proporcionado hipótesis en todos los juegos." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Esos patrones fuente se vuelven más específicos cuando incluimos el " +"compilador. Bajo una versión particular y un conjunto de opciones, pequeños " +"cambios en la fuente pueden producir diferencias repetibles en el código de " +"máquina. Algunas de esas diferencias son sorprendentemente oscuras." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"En TH095, por ejemplo, {ph0}incluso el nombre de una variable local podría " +"afectar dónde la almacenó VC7.1{ph1}. Mover su declaración no resolvió el " +"diseño del almacenamiento. Sin embargo, una función en segundo plano " +"anterior había revelado un patrón de nombres que afectaba la elección del " +"compilador. Eso sugirió una hipótesis más prometedora para {ph2}reconstruir " +"{ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"La reutilización de ese patrón para la variable de tamaño de archivo produjo" +" el diseño requerido sin agregar almacenamiento. Entonces coincidió la " +"función completa." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Este es un detalle muy específico que un modelo de IA de propósito general " +"puede no conocer cuando encuentra el problema por primera vez. Un modelo " +"especializado para este compilador podría ver muchos de estos casos y " +"aprender qué variaciones del código fuente vale la pena probar primero." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"La oportunidad es especialmente clara en los problemas finales de " +"emparejamiento en los que ya entendemos el comportamiento. Entonces nos " +"preguntamos qué disposición ordinaria del código fuente convierte este " +"compilador en las instrucciones observadas. La especialización podría ayudar" +" al modelo a proponer esas formas de manera más eficiente, mientras que el " +"objetivo aún determina qué hipótesis sobreviven." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Los patrones útiles deben conservar su contexto. TH08 utiliza una versión " +"Visual C++ anterior a TH095 y TH09. TH04 utiliza un compilador diferente de " +"la era DOS. Su {ph0}reconstrucción del código del jugador{ph1} necesitaba " +"diferentes hipótesis sobre los patrones del código fuente y cómo el código " +"compilado se vinculaba a un ejecutable. Tener el mismo autor nos da una " +"expectativa inicial, pero cada objetivo nos dice si aplica. Un modelo " +"especializado necesitaría distinguir estos contextos." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "¿Dónde debería almacenarse esta experiencia?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Antes de decidir enseñar esos patrones mediante el entrenamiento de modelos," +" miraría el conocimiento que ya guardamos en el repositorio. En el " +"{ph0}ensayo anterior{ph1}, escribí sobre cómo se convertiría en la memoria " +"de trabajo del proyecto. Esa memoria incluye lecciones del compilador, junto" +" con la fuente y los experimentos fallidos que los hicieron útiles." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Al recuperar ese registro, un agente puede comenzar con un resultado " +"conocido e inspeccionar cómo llegamos a él. También puede evitar " +"alternativas que ya han fracasado en el mismo contexto. El punto de partida " +"mejora sin cambiar los parámetros entrenados del modelo." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Mientras reconstruía la función de TH09 para crear enemigos, una sesión " +"{ph0}GPT-6-Luna-max{ph1} tomó una hipótesis del código fuente relacionado de" +" TH08. Ese código anterior sugirió cómo organizar el bucle y manejar las " +"fallas dentro de él. La propia evidencia de TH09 proporcionó los detalles " +"específicos del juego. Las reconstrucciones de la fuente confirmaron que la " +"función completa coincidía." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"El modelo no sabía esa peculiaridad del compilador\" y \"el modelo no" +" podía usarlo\" son problemas diferentes.{ph1} La recuperación puede " +"resolver el primero, pero convertir ese hecho en un candidato útil aún " +"requiere trabajo. Y si el código fuente candidato falla, el modelo debe " +"decidir qué significa el resultado para su próximo intento. Conocer el " +"patrón relevante es sólo el comienzo de ese proceso." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Por esa razón, incluiría en cualquier comparación un modelo de IA de " +"propósito general más pequeño con buena recuperación. Darle la misma " +"biblioteca de experiencia nos ayudaría a identificar qué aporta la " +"capacitación: mejor generación de candidatos, mejores decisiones después de " +"la retroalimentación, o ambas." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Aprendiendo el próximo experimento útil" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Esas decisiones después del feedback son las que más me gustaría estudiar. " +"En la reconstrucción agente, el modelo propone una explicación y la compara " +"con el programa. Incluso cuando el código fuente candidato falla, el " +"resultado puede reducir las posibilidades restantes y sugerir un próximo " +"experimento más útil." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Considere nuevamente el ejemplo de los resultados temporales. Su fuente " +"final muestra el arreglo que funcionó, pero la ruta a esa fuente contiene " +"más información. Cada uno de los siguientes experimentos ayudó a identificar" +" lo que aún era necesario cambiar." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "experimento" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Lo que nos enseñó su resultado" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Pruebe una forma diferente de copiar los resultados." + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "El código de copia cambia, pero la función aún difiere." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Utilice los valores devueltos directamente" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"La copia sigue el patrón original, pero el almacenamiento temporal aún " +"difiere." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Mantener todas las variables temporales válidas al mismo tiempo." + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Se almacenan por separado, pero uno aún se superpone a un valor utilizado " +"más adelante para las comprobaciones de colisiones." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Mantenga el valor de verificación de colisiones separado" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Una recompilación limpia del código fuente confirma la coincidencia " +"completa." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Experimentos seleccionados de la reconstrucción de la función de ataque " +"anterior, agrupados según lo que nos enseñaron." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Un registro de capacitación que mantenga esta secuencia puede enseñar más " +"que la fuente final por sí sola. Conecta cada cambio propuesto con un " +"resultado observado y la siguiente decisión. Mantener variaciones ineficaces" +" también es importante: le dicen a un agente posterior qué hipótesis ya han " +"sido probadas en ese contexto." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Me gustaría que el modelo aprendiera a utilizar la " +"retroalimentación.{ph1} Un resultado neutral es una razón para reconsiderar " +"la variación; una discrepancia modificada puede indicar otra causa. Cuando " +"las ediciones locales dejan de ser informativas, el agente debería poder " +"revisar la representación de la fuente o inspeccionar la evidencia " +"nuevamente." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Aprender a tomar esas decisiones requiere autonomía. A veces, el siguiente " +"paso útil es inspeccionar a otra persona que llama en lugar de compilar otra" +" edición. Una secuencia rígida de reescrituras requeridas eliminaría esa " +"elección, junto con parte del comportamiento que queremos que aprenda el " +"modelo." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "" +"Por qué la ingeniería inversa es interesante para el aprendizaje por " +"refuerzo" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"La reconstrucción acotada nos brinda un entorno práctico para estudiar estas" +" opciones. Una vez que se corrigen las versiones de destino y del " +"compilador, muchos experimentos de origen producen comentarios rápidos y " +"repetibles. El agente puede compilar un candidato, inspeccionar la " +"discrepancia y utilizar esa observación para elegir el siguiente paso." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"El aprendizaje por refuerzo podría entrenar ese proceso de toma de " +"decisiones a través de la retroalimentación que recibe. Un candidato " +"aceptado mediante un control definido nos da un resultado concreto, mientras" +" que la secuencia de intentos nos permite observar cuánto trabajo ha sido " +"necesario para alcanzarlo." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Ya existen investigaciones que respaldan esta dirección. " +"{ph0}LLM4Decompile{ph1} estudia modelos especializados para la " +"descompilación. {ph2}AutoDecompiler{ph3} entrena el refinamiento de varios " +"turnos utilizando el compilador y los comentarios de ejecución. Sus estudios" +" se centran en la recuperación funcional. Para este trabajo, los usaría como" +" punto de partida para la tarea relacionada de encontrar una fuente que " +"coincida con la salida de un compilador histórico." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Sin embargo, para alcanzar una tarea tan bien definida, es posible que " +"primero necesitemos establecer qué recursos posee una función o diseñar una " +"nueva forma de observar el comportamiento del programa durante su ejecución." +" En TH08, por ejemplo, una {ph0}diferencia de colisión llevó a cómo el " +"programa original manejaba los cálculos de punto flotante{ph1}. Antes de que" +" el agente pudiera probar una corrección útil, tenía que decidir qué medir." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Esto sugiere otra función para un modelo con amplias capacidades: ayudar a " +"que el problema sea verificable en primer lugar. Una vez que exista esa " +"verificación, podemos investigar hasta dónde puede llegar una política de " +"búsqueda aprendida." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Cuando el verificador está equivocado" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Al entrenar con una comprobación, su cobertura pasa a formar parte del " +"entorno de aprendizaje. Llamo oracle a esa referencia o verificador. Aunque " +"la respuesta sea repetible, debemos entender qué verifica realmente." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 mostró cuánto se puede ocultar fuera de esa cobertura. Algunas " +"funciones reconstruidas pasaron sus comparaciones exactas con constantes " +"flotantes incorrectas. El comparador ajustó las direcciones reubicadas antes" +" de verificar las instrucciones, pero verificó los valores detrás de esas " +"direcciones solo cuando se habían registrado explícitamente para su " +"verificación. Otras referencias literales podrían pasar sin que se examinen " +"sus valores." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Para abordar esta brecha, una {ph0}auditoría más amplia{ph1} encontró " +"constantes incorrectas en funciones que ya habían pasado la verificación. En" +" un cálculo, el código fuente reconstruido agregó {ph2}, mientras que el " +"original agregó {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Un modelo recompensado por la comprobación anterior podría aprender a " +"producir una reconstrucción incorrecta.{ph1} No entrenamos un modelo RL " +"usando ese verificador. El fallo que observamos estaba en la propia " +"comprobación. Pero si lo usáramos como recompensa, el mismo punto ciego " +"pasaría a formar parte del entorno de aprendizaje." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Una prueba funcional puede tener un punto ciego similar. {ph0}La " +"investigación que utilizó fuzzing diferencial en descompiladores LLM{ph1} " +"encontró diferencias de comportamiento fuera de las pruebas proporcionadas. " +"Por lo tanto, debemos entender una prueba aprobatoria en términos de los " +"casos en los que se aplica. De manera similar, una coincidencia de " +"instrucciones debe entenderse en términos de los bytes y datos que verifica." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Antes de utilizar cualquier tipo de control de verificación como recompensa," +" lo probaría con resultados deliberadamente incorrectos. También mantendría " +"la aceptación final separada del código fuente que el agente de IA puede " +"editar. El modelo debe pasar la verificación reconstruyendo el programa " +"correctamente. De lo contrario, simplemente copiar una matriz de bytes del " +"destino podría engañar a un sistema de puntuación ingenuo sin recuperar el " +"código fuente útil." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Mejorar al alumno y mejorar su verificador pertenecen al mismo problema" +" de investigación.{ph1} A medida que el alumno mejora en la optimización de " +"los comentarios que le damos, comprender esos comentarios también se vuelve " +"más importante." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Una comparación que vale la pena realizar" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Con esas comprobaciones implementadas, comenzaría la comparación en una " +"familia de tareas fija VC7.1. Primero, establecería líneas de base para un " +"modelo de IA de propósito general sólido y uno más pequeño. Agregar " +"conocimiento del repositorio al modelo más pequeño mostraría qué cambios en " +"la recuperación. A partir de ahí, la especialización supervisada y una " +"versión capacitada con RL nos permitirían examinar qué agrega la " +"capacitación." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Para que esas comparaciones sean informativas, cada modelo recibiría la " +"misma evidencia y herramientas objetivo. Para las comparaciones específicas " +"de la capacitación, también mantendría fijo el modelo base y el conocimiento" +" disponible. Las pruebas repetidas ayudarían a distinguir una estrategia de " +"búsqueda confiable de una solución candidata que tiene éxito por casualidad." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Luego separaría dos condiciones iniciales: reconstruir una función a partir " +"de sus instrucciones y cerrar las últimas diferencias en la fuente " +"mantenida. Un modelo de IA especializado podría ser excelente en la segunda " +"tarea, mientras que un modelo de IA de propósito general hace gran parte del" +" trabajo necesario para alcanzarla. Medirlos por separado revelaría esa " +"división del trabajo." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Ambas tareas necesitan ejemplos de prueba excluidos del entrenamiento y la " +"recuperación. Los juegos Touhou relacionados comparten el código del motor. " +"Excluir un juego del entrenamiento aún podría dejar funciones casi idénticas" +" en el conjunto de entrenamiento. En cambio, excluiría grupos enteros de " +"código fuente relacionado y mantendría sus respuestas verificadas fuera de " +"los datos de entrenamiento y de la biblioteca de recuperación." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Para estos ejemplos, el resultado serían coincidencias completas y " +"verificadas de forma independiente. La igualdad de presupuestos para las " +"propuestas de los candidatos o los intentos de compilación ayudaría a " +"comparar la calidad de la búsqueda. Medir el tiempo y el costo total, " +"incluida la compilación, mostraría si esa calidad produce un flujo de " +"trabajo eficiente. Los costos de capacitación deben medirse por separado." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Ambas medidas importan. Una propuesta barata puede generar un flujo de " +"trabajo costoso si genera más compilaciones que no proporcionan información " +"útil. Por el contrario, un modelo más lento puede resultar más económico si " +"encuentra antes un experimento útil. La comparación debe incluir estos " +"costos." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Contar los resultados aceptados también ayuda a interpretar los avances " +"intermedios. Un {ph0}candidato para guardar repeticiones{ph1} de TH09 " +"parecía prometedor porque la función compilada tenía el tamaño esperado, " +"pero la comparación completa aún encontró diferencias importantes. La forma " +"en que el compilador ordena las instrucciones puede hacer que un candidato " +"parezca más cercano sin resolver el problema de fondo. Estos diagnósticos " +"orientan el siguiente experimento; antes de premiar una mayor cercanía, la " +"contrastaría con la comprobación completa de aceptación." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Me interesaría conocer el patrón de estos resultados. Si un modelo de IA " +"especializado funciona bien dentro de una familia de compiladores familiar, " +"¿esa ventaja sobrevive a un cambio en la cadena de herramientas? Y una vez " +"que ambos modelos de IA tengan una buena recuperación, ¿cuánto aporta aún el" +" entrenamiento? Las respuestas nos ayudarían a decidir dónde es más útil " +"cada tipo de modelo." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "¿Qué tipo de agente de IA sugiere esto?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Si los modelos resultan útiles en diferentes etapas, un acuerdo útil podría " +"ser un agente amplio con acceso a un modelo de IA especializado. Una vez que" +" una tarea se convierte en una búsqueda familiar del compilador, podría " +"solicitar candidatos al modelo de IA especializado. Si los resultados dejan " +"de tener sentido, el agente más amplio podría volver a la evidencia objetivo" +" o investigar la medición en sí." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"En ese arreglo, la especialización se convierte en una herramienta que el " +"agente puede elegir a medida que se desarrolla la investigación. El agente " +"conserva la libertad de cambiar la dirección que hizo posibles los avances " +"anteriores." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Esto se deriva naturalmente del cambio industrial que describí en el ensayo " +"anterior. Poder realizar muchos más experimentos cambia la forma en que " +"organizamos el trabajo. También nos da una razón para preguntar qué " +"decisiones requieren un juicio amplio y cuáles mejoran a través de " +"experiencias repetidas con un oficio en particular." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Por ahora, el modelo general más potente se ha ganado su lugar en mi flujo " +"de trabajo al resolver problemas que había dejado pendientes. Esos éxitos me" +" llevan a examinar el proceso: ¿cuánto dependía de la amplitud del modelo y " +"cuánto podría asumir uno entrenado específicamente para esta clase de " +"reconstrucción?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Los repositorios nos brindan una forma de probar la pregunta.{ph1} Me " +"gustaría usar ese registro para realizar la comparación y ver qué " +"aprendemos." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Atribución de evidencia y modelo" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Los ejemplos describen comparaciones históricas a nivel de función " +"registradas en las confirmaciones vinculadas. Las comprobaciones del tiempo " +"de ejecución del juego completo son hitos separados. Los registros fuente y " +"coincidentes se revisaron el 13 de octubre de 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"La etiqueta TH09 {ph0} significa GPT-6-Astra. El modelo asociado con {ph1} " +"cambió con el tiempo, por lo que esa etiqueta por sí sola no puede " +"identificar el modelo utilizado en una ejecución específica. Los nombres de " +"modelos explícitos en las otras confirmaciones citadas proporcionan la " +"atribución registrada. Estos historiales no incluyen mediciones consistentes" +" de costo o esfuerzo para cada ejecución." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 duración de los objetos temporales:{ph1} la {ph2}revisión de " +"contexto anterior{ph3} y la {ph4}reconstrucción completa verificada mediante" +" una recompilación limpia del código fuente{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front devolución de llamada:{ph1} {ph2}regiones de diagnóstico que" +" no coincidieron{ph3}, {ph4}Astra nuevo gráfico de flujo de control{ph5} y " +"su {ph6}verificación de recompilación aceptada{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Conocimiento del compilador:{ph1} {ph2}TH095 reutilización del " +"comportamiento del identificador-depósito{ph3}, {ph4}TH04 código fuente del " +"jugador y orden del enlazador{ph5} y {ph6}Luna reconstrucción completa de la" +" función de creación de enemigos de TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Comprobaciones y diagnósticos:{ph1} {ph2}TH08 auditoría constante de " +"punto flotante{ph3}, {ph4}TH08 investigación numérica{ph5} y {ph6}TH09 " +"reconstrucción para guardar reproducciones{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Las comparaciones propuestas de modelos especializados y entrenamiento RL " +"son experimentos futuros. Las historias de los proyectos los motivan. Para " +"este ensayo no se evaluó ningún modelo especializado entrenado." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "¿La ingeniería inversa necesita un modelo más grande? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Lo que me enseñó la reconstrucción Touhou sobre modelos generales, modelos " +"especializados y cómo aprender a proponer mejores hipótesis a partir de los " +"comentarios del compilador." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "En esta página" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Modelos y ensayo de ingeniería inversa." + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Experimentos de reconstrucción seleccionados." + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Volver arriba" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"Las {ph0}notas detalladas de evidencia{ph1} incluyen las comparaciones " +"registradas y el contexto de los experimentos." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Por N0zoM1z0 · 13 de octubre de 2026 · Borrador para revisión" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Guía de instalación" diff --git a/website/locales/fa/messages.po b/website/locales/fa/messages.po index d678fee59..02b489a3c 100644 --- a/website/locales/fa/messages.po +++ b/website/locales/fa/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "پرش به محتوا" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}خانه{ph1} / وبلاگ" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "وبلاگ." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "افکار در مهندسی معکوس." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "بازسازی بازی{ph0}مقاله" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "انقلاب صنعتی در مهندسی معکوس" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "چه دستی دوباره و بازسازی TH08, TH095 و TH04 به من آموخت در مورد عوامل, تأیید" " و دانش است که ترکیبات در سراسر پروژه." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "مقاله را بخوانید" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "توسط N0zoM1z0 * 10 اکتبر 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -99,6 +100,8 @@ msgstr "" "افکار در مهندسی معکوس ، با استفاده از تجربه عملی با REA و عوامل هوش مصنوعی." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -134,112 +137,117 @@ msgstr "" "REA-پیدا کردن چگونه نرم افزار کار می کند. مهندسی معکوس با عامل برنامه نویسی " "شما." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "صفحهٔ اصلی REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "ناوبری اصلی" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA در GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "به REA در Discord بپیوندید" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "REA را در X دنبال کنید" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -248,35 +256,35 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}خانه{ph1} / {ph2}وبلاگ{ph3} / بازسازی توهو" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "مقاله * بازسازی توهو" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "انقلاب صنعتی در مهندسی معکوس" -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "توسط N0zoM1z0 * 10 اکتبر 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "نکات اصلی" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -289,7 +297,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -303,7 +311,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -315,7 +323,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -328,7 +336,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -338,65 +346,65 @@ msgstr "" "{ph0}ما در روزهای اولیه انقلاب صنعتی RE هستیم.{ph1} روش ها هنوز در حال شکل " "گرفتن هستند. هنوز چيزاي زيادي براي کشف کردن باقي مونده" -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "چگونه ترکیبات تجربه" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}جهت گیری انسان{ph1} * هدف و معیارهای پذیرش" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "استقلال عمل" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "دستیار" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "یک آزمایش را انتخاب کنید.{ph0}یک فرضیه را پیشنهاد کنید." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "اعتبارسنجی" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "مرجع اعتبارسنجی" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "تست در برابر یک{ph0}مرجع بتن." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "مخزن کد" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "حافظهٔ کاری" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -405,7 +413,7 @@ msgstr "کد ، شواهد,{ph0}چک ها و درس ها" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -414,26 +422,26 @@ msgstr "عدم تطابق{ph0}{ph1}فرضیه را بازنگری کنید{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "بهتر{ph0}{ph1}نقطه شروع{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "استفادهٔ دوباره" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}گذرنامه{ph1} * نتیجه و شواهد آن را حفظ کنید" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -442,14 +450,14 @@ msgstr "" "هر پروژه با نقطه شروع بهتر از پروژه بعدی باقی می ماند. که شامل اصلاح چک ها " "هم ميشه وقتي که ما يه شکاف پيدا مي کنيم" -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "در این مقاله" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -457,7 +465,7 @@ msgstr "{ph0}آگوست 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -465,7 +473,7 @@ msgstr "{ph0} TH08: ادامه{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -473,7 +481,7 @@ msgstr "{ph0}دو رویکرد{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -481,7 +489,7 @@ msgstr "{ph0} TH095: ترکیب{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -489,7 +497,7 @@ msgstr "{ph0} TH04: در سراسر معماری{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -497,7 +505,7 @@ msgstr "{ph0}از دقیق تا قابل خواندن{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -505,18 +513,18 @@ msgstr "{ph0}شیفت صنعتی{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}آنچه ممکن می شود{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "آنچه در آگوست 2026 تغییر کرد" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -530,7 +538,7 @@ msgstr "" "تست می کردم. ادامه دادن به این معنی بود که بیشتر وقت خودم را صرف کار بعدی می" " کردم. همچنین به این معنی بود که یک تصویر بزرگ در ذهنم نگه دارم." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -543,7 +551,7 @@ msgstr "" "این مقاله است. این روش می تواند در جای دیگر مفید باشد ، اما هر فیلد باید " "مشخص کند که چه چیزی را می تواند با یک مرجع قابل اعتماد بررسی کند." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -555,7 +563,7 @@ msgstr "" "مامور چقدر ميتونه با دسترسي به برنامه و ابزار توسعه معمولي به اينجا برسه " "بازسازی توهو به من یک پروژه قابل توجهی داد که در آن می توانستم بفهمم." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -572,7 +580,7 @@ msgstr "" "توانم توجه بیشتری به جهت پروژه و اینکه آیا چک های آن قابل اعتماد است ، صرف " "کنم." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -583,7 +591,7 @@ msgstr "" "پروژه فعلی زنده می ماند. آیا بازی بعدی از هر چیزی که تازه یاد گرفته بودیم " "سود می برد ؟" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: ساخت بر روی کار انسانی" @@ -592,7 +600,7 @@ msgstr "TH08: ساخت بر روی کار انسانی" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -605,7 +613,7 @@ msgstr "" "GensokyoClub{ph3}. منبع عمومی آنها به من یک پایه قابل توجهی داد. با دانش " "ساخت و ساز و سابقه کمک هایی که در ادامه حفظ کردم ، همراه بود." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -616,7 +624,7 @@ msgstr "" " آگوست آغاز شد. تا 19 آگوست ، دفتر کل منبع ثبت شده برای تمام 1107 عملکرد " "بازی شناسایی شده بود." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -627,7 +635,7 @@ msgstr "" "ادامه ، انجام شد. یک نسخه وب به دنبال آن بود. نسخه بومی Linux 64 بیتی در 30 " "اوت وارد شد." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -643,7 +651,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -661,12 +669,12 @@ msgstr "" " توضیح می دهد و آن را آزمایش می کند ؛ عدم تطابق چیزی خاص برای تحقیق به آن می" " دهد." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "مطابقت دقیق با ثابت اشتباه" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -677,7 +685,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -689,7 +697,7 @@ msgstr "" "جمع آوری خودکار آیتم شد. منبع بازسازی شده قدرت بازیکن را در برابر {ph0}. اصل" " مورد استفاده {ph1}، حد حداکثر قدرت" -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -704,13 +712,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}با این حال تابع قبلا مقایسه دقیق را پشت سر گذاشته بود.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -724,7 +732,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -740,7 +748,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -754,7 +762,7 @@ msgstr "" "مرجع ثابت نقطه شناور را بررسی کرد. این دوازده مرجع نادرست دیگر را در پنج " "تابع پذیرفته شده پیدا کرد." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -767,7 +775,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -777,7 +785,7 @@ msgstr "" "{ph0}مرجع تأیید (اوراکل) نیز نیاز به بازسازی داشت.{ph1} تعمیر آن بخشی از " "تعمیر بازی بود." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -795,7 +803,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -810,7 +818,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -820,7 +828,7 @@ msgstr "" "{ph0}یک دسته موفق به ما کد بازیابی شده و یک محیط بهتر برای دسته بعدی را " "داد.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "دو ایده متفاوت از بازسازی" @@ -829,7 +837,7 @@ msgstr "دو ایده متفاوت از بازسازی" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -841,7 +849,7 @@ msgstr "" "این اطلاعیه اعلام می کند که توسعه بیشتر به صورت خصوصی تا زمان تکمیل اتفاق " "خواهد افتاد. در یکی از این بخش ها آمده است:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -850,7 +858,7 @@ msgstr "" "ظهور grifters (تجزیه هوش مصنوعی و پورت ها) در این فضا گرفتن از کار ما یک " "تصویر بد برای تلاش های تجزیه آینده را نقاشی می کند…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -867,7 +875,7 @@ msgstr "" " بحث کنم این است که بازسازی چگونه باید ادامه یابد و چگونه باید یک سهم را " "قضاوت کرد." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -879,7 +887,7 @@ msgstr "" "همان شخص می رسید. یک پروژه به شدت به تخصص آن شخص متکی بود. اعتماد به کمک " "کننده مهم بود چون خیلی از استدلال ها در حالی که کار می کردند اتفاق می افتاد." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -890,7 +898,7 @@ msgstr "" "سازند. چیزی که برای من تغییر کرد این بود که یک مامور می توانست از این دانش " "برای پیگیری تحقیقات بعدی به تنهایی استفاده کند." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -904,7 +912,7 @@ msgstr "" " به در ببرد. من می خواهم شخص دیگری بتواند بررسی کند که چرا ما یک پیاده سازی " "را انتخاب کردیم ، حتی اگر یک نماینده بیشتر کار را انجام دهد." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -917,7 +925,7 @@ msgstr "" " را مطرح می کند. همچنین آنچه را که نگهدارندگان باید قبل از پذیرش سهم بدانند " "تغییر می دهد." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -932,7 +940,7 @@ msgstr "" "دهد که خروجی آن اشتباه است. جوامع مختلف می توانند انتخاب کنند که چه مقدار از" " این تغییر را می خواهند انجام دهند." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -957,7 +965,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -969,14 +977,14 @@ msgstr "" "{ph2}سیاست مشارکت{ph3}. نقل قول یک گزیده کوتاه است. TH08 {ph4}اعتبارات و " "منشأ{ph5} مرز ادامه را ثبت کنید." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: تجربه شروع به ترکیب می کند" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -990,7 +998,7 @@ msgstr "" "باید بازی را یاد می گرفتیم. اما ما قبلا خیلی بیشتر در مورد چگونگی شروع " "بازسازی و چگونگی حرکت آن می دانستیم." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1003,7 +1011,7 @@ msgstr "" "متصل شد. بازسازی Windows i386 در 10 سپتامبر ، حدود دوازده روز پس از شروع ، " "قابل بازی بود." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1014,7 +1022,7 @@ msgstr "" " انجام شده در یک بازی دیگر بهره مند شود. این تجربه قبلا در ابزارها و نحوه " "سازماندهی پروژه وجود داشت." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1029,7 +1037,7 @@ msgstr "" "می کنن این درس به شکل گیری نحوه ی نزدیک شدن ما به ساخت کل برنامه ی TH095 کمک" " کرد." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1042,7 +1050,7 @@ msgstr "" "اینکه من حرکت کردم. عامل بعدی می تواند نتیجه را بدون تکرار تحقیقات منجر به " "آن استفاده کند." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1056,7 +1064,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1067,7 +1075,7 @@ msgstr "" "{ph0}این روش بخشی از مواد اولیه برای بازی بعدی می شود.{ph1} ما می توانیم " "بیشتر از تلاش پروژه بعدی را صرف آنچه در واقع جدید در مورد هدف آن است." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1080,7 +1088,7 @@ msgstr "" "کنند. آنها مجبور نیستند کل تاریخچه پروژه را بازسازی کنند تا بفهمند چرا منبع " "به این شکل به نظر می رسد." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: جریان کار از یک معماری متفاوت جان سالم به در می برد" @@ -1089,7 +1097,7 @@ msgstr "TH04: جریان کار از یک معماری متفاوت جان سا #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1104,7 +1112,7 @@ msgstr "" "افزاری آن نیاز به شواهد متفاوتی از بازی های Windows داشت. موجود {ph2}کار " "ReC98{ph3} ما دانش ارزشمندی و منبع مواد را در اینجا نیز به ما داد." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1117,7 +1125,7 @@ msgstr "" "بیتی بومی است. ایجاد یک نسخه dos کار برای اولین بار به آن پورت یک مرجع می " "دهد." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1130,7 +1138,7 @@ msgstr "" "تواند یک سوال را تا نتیجه دنبال کند و اجازه دهد که نتیجه آزمایش بعدی را " "هدایت کند." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1145,7 +1153,7 @@ msgstr "" "نماینده می تواند از طریق سوال کار کند ، همانطور که در عنوان Windows انجام " "شده است." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1156,7 +1164,7 @@ msgstr "" "مجبور نکرد که با یک روش جدید کار شروع کنیم. معماری مشکل را تعریف کرد ؛ جریان" " کار هنوز راهی برای حل آن به ما داد." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1173,7 +1181,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1183,19 +1191,19 @@ msgstr "" "وضعیت پروژه از 10 اکتبر 2026: {ph0}بازسازی DOS و تست دستی{ph1} · {ph2}پورت " "64 بیتی{ph3}. بندر همچنان در حال توسعه است." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "از کد دقیق تا کد قابل خواندن" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "وقتی بازسازی جواب داد ، میخوام یه نفر دیگه بتونه درکش کنه." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1209,7 +1217,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1225,7 +1233,7 @@ msgstr "" " نام معنی دار و نوعی متناسب با شواهد به آن بدهیم. ما استدلال را با منبع نگه " "می داریم تا فرد بعدی بتواند ببیند که این تفسیر از کجا آمده است." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1240,14 +1248,14 @@ msgstr "" " می کند. برای حرکت ایمن رفتار ، باید رابطه پشت دسترسی به حافظه قدیمی را " "بازیابی کنیم." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "سفارشي که الان ازش استفاده ميکنم:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1263,7 +1271,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1279,7 +1287,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1294,7 +1302,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1308,7 +1316,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1324,7 +1332,7 @@ msgstr "" "برنامه بازسازی شده هنوز در مسیرهایی که ما تمرین می کنیم درست می سازد و رفتار" " می کند." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1337,7 +1345,7 @@ msgstr "" "نسخه های مختلف حالت ترک کند. نگه داشتن هر دو چک در دسترس به عامل یک شکست " "مشخص برای تحقیق قبل از حمل یک refactor بیشتر می دهد." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1354,7 +1362,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1372,7 +1380,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1382,12 +1390,12 @@ msgstr "" "{ph0}بازسازی دقیق به ما مرجع می دهد. بازسازی معنایی دانش بازیابی شده را قابل" " استفاده می کند.{ph1} سپس یک پورت می تواند بر روی هر دو ساخته شود." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "چه چیزی این را به یک تغییر صنعتی تبدیل می کند ؟" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1400,7 +1408,7 @@ msgstr "" "کارهایی بود که می توانستم انجام دهم. یک ابزار بهتر می تواند در هر عملکرد " "بعدی که به آن نیاز دارد کمک کند." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1413,7 +1421,7 @@ msgstr "" "نیاز دارد. اگر باید منتظر بمانم تا هر مرحله را تجویز کنم ، بیشتر کار به توجه" " من وابسته است." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1426,7 +1434,7 @@ msgstr "" "تا اشتباه را به اندازه کافی خوب درک کند تا دوباره امتحان کند. هنوز بايد " "تصميم بگيرم که آيا شواهد جمع شده از يک نقطه عطف پروژه حمايت ميکنه يا نه" -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1440,7 +1448,7 @@ msgstr "" "بازسازی کامپایلر و چک های مرجع خود را تامین می کند. مامور می تواند از آن ها " "برای تست منبع پیشنهادی خود استفاده کند و ببیند که توضیح آن در کجا قرار دارد." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1457,7 +1465,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1477,7 +1485,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1494,7 +1502,7 @@ msgstr "" "تحت تاثیر آن را دوباره بررسی کنیم. پروژه بعدی می تواند یک ابزار قوی تر را به" " ارث ببرد." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1509,7 +1517,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1521,7 +1529,7 @@ msgstr "" "راه مشترک برای حمل چک ها و درس های خود را به جلو می دهد. کار بر روی یک بازی " "می تواند شرایط شروع را برای دیگری بهبود بخشد." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1533,12 +1541,12 @@ msgstr "" "بهبود این ابزارها ، میزان کاری که فرد بعدی یا نماینده بعدی می تواند انجام " "دهد را تغییر می دهد." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "پروژه هایی که اکنون می توانیم در نظر بگیریم" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1549,7 +1557,7 @@ msgstr "" "مهندسی معکوس جذاب باشد و هنوز هم نیاز به توجه بیشتر از آنچه که من می توانم " "به طور واقع گرایانه به آن بدهم. بسیاری از پروژه ها ایده ها را حفظ می کنند." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1565,7 +1573,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1576,7 +1584,7 @@ msgstr "" "دانش انباشته شده ای به یک نماینده اجازه می دهد تا به طور قابل اعتماد روی این" " کار کند ؟ {ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1587,12 +1595,12 @@ msgstr "" "هرکدام می توانند روش برخورد ما با روش بعدی را بهبود ببخشند. ميخوام به کاوش " "ادامه بدم که چقدر ميتونه ما رو ببره" -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "نقاط عطف و منابع پروژه" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1626,7 +1634,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1660,7 +1668,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1678,7 +1686,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1701,7 +1709,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1723,7 +1731,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1739,7 +1747,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1760,7 +1768,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1774,7 +1782,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1794,27 +1802,27 @@ msgstr "" "N0zoM1z0 در مهندسی معکوس دستی ، بازسازی Touhou با عوامل هوش مصنوعی و چگونگی " "ترکیبات دانش در TH08 ، TH095 و PC-98 TH04 منعکس می شود ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "تجربه انجام شده بین پروژه ها" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "مقاله بازسازی توهو" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -1823,18 +1831,18 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}خانه{ph1}{ph2}/{ph3}آزمایشگاه سرعت دایناسور" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "بازرسی → بازسازی → تغییر" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "قانون سرعت دایناسور رو دوباره بساز" @@ -1843,7 +1851,7 @@ msgstr "قانون سرعت دایناسور رو دوباره بساز" #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1855,15 +1863,15 @@ msgstr "" "کند. {ph0} REA اسکریپت در حال اجرا بازگشت;{ph1} ما از قاعده اش برای ساخت این" " مینی بازی با {ph2}سرعت قابل تنظیم{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "در این صفحه" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1871,7 +1879,7 @@ msgstr "{ph0}بازی و تغییر سرعت{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1879,7 +1887,7 @@ msgstr "{ph0}قانون بازیابی شده را بخوانید{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1887,18 +1895,18 @@ msgstr "{ph0}بازسازی را بررسی کنید{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}تجزیه و تحلیل را امتحان کنید{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "بازی و تغییر سرعت" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1909,49 +1917,49 @@ msgstr "" " بازی کندتر و یا سریع تر; آن را به یک سرعت ثابت سوئیچ. قانون بازیابی شده را " "انتخاب کنید تا از 6 شروع شود و به تدریج دوباره تسریع شود." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "نسخهٔ بازسازی‌شده را بازی کنید" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "بازی" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "پرش ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "شروع دوباره" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "سرعت" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "از قانون شتاب بازیابی شده استفاده کنید" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "قانون اصلی: از 6 شروع کنید ، سپس به سمت 13 افزایش دهید." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "نوار لغزنده را حرکت دهید تا سرعت خود را تنظیم کنید. فضا یا پرش یک کاکتوس را " "پاک می کند." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -1959,7 +1967,7 @@ msgid "" msgstr "" "JavaScript را قادر به بازی بازسازی کنید. کد و توضیح بالا قابل خواندن است." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "خواندن اسکریپت REA بازگشت" @@ -1967,7 +1975,7 @@ msgstr "خواندن اسکریپت REA بازگشت" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1981,7 +1989,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1991,18 +1999,18 @@ msgstr "" "تنظیمات: {ph0}, {ph1} و {ph2}. این بازی این شاخه را در یک به روزرسانی بدون " "برخورد اجرا می کند." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "از همان قانون در بازی جدید استفاده کنید" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "کپی" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2019,18 +2027,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}دانلود قانون سرعت{ph1} · {ph2}کد بازی را بخوانید{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "بازسازی را بررسی کنید" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2040,27 +2048,27 @@ msgstr "" "ما عملکرد به روز رسانی بازی اصلی را با موانع و برنامه ریزی خودکار غیرفعال " "نامیدیم. این سرعت های ثبت شده را با تکرار قانون بازیابی شده مقایسه کنید." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "به روز رسانی" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "بازی اصلی" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "قانون بازسازی شده" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "بررسی سرعت را اجرا کنید" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2069,14 +2077,14 @@ msgstr "" "مقادیر به سه اعشاری گردآوری شده است. شاخه قبل از اضافه کردن چک می کند ، " "بنابراین افزایش نهایی می تواند سرعت را کمی بالاتر از 13 بگیرد." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "تجزیه و تحلیل را خودتان امتحان کنید" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2085,7 +2093,7 @@ msgstr "{ph0}راه اندازی REA {ph1} با عامل برنامه نویسی #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2094,7 +2102,7 @@ msgstr "" "دنبال کنید {ph0}مراحل اتصال مرورگر{ph1}، با استفاده از {ph2} به عنوان URL " "صفحه." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2111,7 +2119,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2123,7 +2131,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2137,7 +2145,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2152,7 +2160,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2177,12 +2185,12 @@ msgstr "" "قانون سرعت بازی دایناسور را با REA بخوانید ، آن را بازسازی کنید ، سپس سرعت " "را تغییر دهید و بازی کنید." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "بازسازی سرعت دایناسور" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2191,52 +2199,52 @@ msgstr "" "دایناسور مینی بازی. در حالی که بازی متمرکز است از دکمه پرش یا فضای فشار " "استفاده کنید." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "کپی قانون سرعت بازسازی شده" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "کپی دایناسور تجزیه و تحلیل فوری" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "پرش به محتوا" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}خانه{ph1} / سوالات متداول" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA سوالات متداول." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "راه اندازی ، به روز رسانی ، تجزیه و تحلیل و عیب یابی." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "موضوعات" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2244,7 +2252,7 @@ msgstr "{ph0}راه اندازی و به روز رسانی{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2252,7 +2260,7 @@ msgstr "{ph0}تحلیل{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2260,31 +2268,31 @@ msgstr "{ph0}عیب یابی{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}داده ها و اشتراک گذاری{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "راه اندازی و به روز رسانی" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "چطور REA را نصب کنم؟" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "ترمینال * راه اندازی عامل" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "کپی" @@ -2292,7 +2300,7 @@ msgstr "کپی" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2305,12 +2313,12 @@ msgstr "" " از پایان، دستیار را دوباره اجرا کنید و مسیر فایل و پرسش خود را به آن بدهید." " پیش‌نیازها و مراحل اولین تحلیل در {ph0}راهنمای راه‌اندازی{ph1} آمده است." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "کدام عوامل کدگذاری می توانند از REA استفاده کنند ؟" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2325,18 +2333,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}عامل برنامه نویسی خود را وصل کنید{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "چطور REA را به‌روز کنم؟" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2344,13 +2352,13 @@ msgid "" msgstr "" "REA اغلب منتشر می شود ، از جمله رفع اشکال. اگر CLI را با npm نصب کرده اید :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "ترمینال * نصب CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2360,14 +2368,14 @@ msgstr "" "دستور setup refresh چاپ شده توسط update را دنبال کنید. اگه ماموريت رو از " "طريق {ph0}، فرار کن:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "ترمینال * راه اندازی عامل تازه" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2379,14 +2387,14 @@ msgstr "" "بسته استفاده می‌کند؛ برای استفاده از نسخه جدید، راه‌اندازی را دوباره انجام " "دهید. برای اجرای یک دستور CLI، دستور مورد نظر را پس از {ph0} بنویسید." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "نصب مهارت از skills.sh کافيه ؟" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2398,24 +2406,24 @@ msgstr "" "برای اتصال سرور MCP و نصب مهارت تطبیق ، سپس عامل خود را دوباره راه اندازی " "کنید تا بتواند ابزارها را فراخوانی کند." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "تحلیل" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "با REA چه چیزی را می توانم تجزیه و تحلیل کنم ؟" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "با نوع نرم افزاری که دارید شروع کنید:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2427,7 +2435,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2439,7 +2447,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2447,7 +2455,7 @@ msgstr "{ph0}صفحات مرورگر{ph1}: اسکریپت ها ، درخواست #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2459,12 +2467,12 @@ msgstr "" "سیستم عامل و منابع بسته بندی شده است. {ph0}مشاهده مطالعات موردی{ph1} برای " "تحقیقات کار." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "آیا به Hopper ، Ghidra یا IDA نیاز دارم ؟" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2476,7 +2484,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2489,12 +2497,12 @@ msgstr "" "ارائه دهنده می تواند مورد استفاده قرار گیرد. {ph0}راه اندازی تجزیه و تحلیل " "برنامه های کد ماشین{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "آیا می توانم از REA بدون یک عامل کدگذاری استفاده کنم ؟" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2503,14 +2511,14 @@ msgstr "" "بله. CLI از همان جریان های کاری تجزیه و تحلیل استفاده می کند. برای یک برنامه" " محلی JavaScript یا Electron:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "ترمینال * تجزیه و تحلیل کاربرد استاتیک" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2521,13 +2529,13 @@ msgstr "" " استفاده کنید {ph1} برای گزینه های نصب." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA چه کدی برمی‌گرداند؟" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2542,7 +2550,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2554,12 +2562,12 @@ msgstr "" "استفاده می کند. این {ph0} محاسبه DX-Ball{ph1} و {ph2}چک کننده پرچم CTF{ph3} " "نشان دهید که این فرآیند چگونه کار می کند." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "از دستیار چه بپرسم؟" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2576,7 +2584,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2584,7 +2592,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2594,18 +2602,18 @@ msgstr "" "مسیر را با هدف خود جایگزین کنید. این {ph0}راهنماها{ph1} ارائه راهنمایی برای " "نمونه های بومی ، Electron و مرورگر." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "عیب یابی" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "چرا نماینده من نمیتونه ابزار REA رو ببینه؟" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2615,7 +2623,7 @@ msgstr "" "بعد از راه اندازی دوباره کارگزار خود را راه اندازی کنید یا دوباره وصل کنید. " "ثبت نام REA خود را با {ph0}; برای Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "ترمینال * یک مشتری را بررسی کنید" @@ -2623,7 +2631,7 @@ msgstr "ترمینال * یک مشتری را بررسی کنید" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2633,14 +2641,14 @@ msgstr "" "جایگزین کنید {ph0} با شناسه مشتری شما ، مانند {ph1} یا {ph2}. اگر گزارش ثبت " "نام گمشده یا قدیمی را نشان می دهد ، برای آن مشتری تنظیم کنید:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "ترمینال * تعمیر راه اندازی یک مشتری" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2652,14 +2660,14 @@ msgstr "" "ابزارها وجود ندارند ، خطای اتصال MCP مشتری را بررسی کنید. {ph0}تشخیص راه " "اندازی بیشتر{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "آیا باید ابتدا Hopper را شروع کنم؟" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2671,14 +2679,14 @@ msgstr "" "حالت دمو یا فعال سازی مجوز را قبل از تجزیه و تحلیل بدون نظارت تکمیل کنید. " "{ph0}مشاهده راه اندازی ارائه دهنده بومی{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "اگر با خطا روبه‌رو شدم چه کنم؟" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2690,7 +2698,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2702,17 +2710,17 @@ msgstr "" " نوع هدف ، مراحل بازتولید و خروجی خطا. شامل نام ارائه دهنده زمانی که مشکل " "شامل تجزیه و تحلیل برنامه های کد ماشین است." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "داده ها و اشتراک گذاری" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "آیا REA برنامه من را آپلود می کند ؟" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2721,7 +2729,7 @@ msgstr "" "REA اهداف را در دستگاه شما تجزیه و تحلیل می کند. نماینده شما نتایج را دریافت" " می کند و سیاست داده ارائه دهنده مدل آن برای این نتایج اعمال می شود." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "چگونه می توانم یک مثال را به اشتراک بگذارم یا کمک کنم ؟" @@ -2730,7 +2738,7 @@ msgstr "چگونه می توانم یک مثال را به اشتراک بگذا #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2745,7 +2753,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2769,77 +2777,77 @@ msgstr "" "پاسخ به سوالات رایج REA: نصب ، به روز رسانی ، ابزارهای تجزیه و تحلیل ، عوامل" " کدگذاری ، عیب یابی و به اشتراک گذاری نمونه ها." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "سوالات متداول در مورد REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "کپی REA دستور راه اندازی" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "کپی REA دستور به روز رسانی" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "دستور Copy agent setup refresh" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "کپی REA CLI دستور تجزیه و تحلیل" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "کپی مثال تجزیه و تحلیل prompt" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "دستور تشخیص مشتری را کپی کنید" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "دستور Copy scoped setup" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "پرش به محتوا" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}خانه{ph1} / اولین تحقیق شما" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "پیدا کردن که در آن{ph0}اسکناس های صادر شده می روند." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2848,14 +2856,14 @@ msgstr "" "از REA برای بازرسی یک برنامه کوچک استفاده کنید ، دکمه یادداشت های صادراتی آن" " را دنبال کنید و خودتان یک جزئیات را بررسی کنید." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "در این تمرین" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2863,7 +2871,7 @@ msgstr "{ph0}1. راه اندازی{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2871,7 +2879,7 @@ msgstr "{ph0}2. درباره صادرات بپرسید{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2879,7 +2887,7 @@ msgstr "{ph0}3. پاسخ را دنبال کنید{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2887,13 +2895,13 @@ msgstr "{ph0}4. پیش بینی را بررسی کنید{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. سوال دیگری بپرسید{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. نماینده خود را به REA متصل کنید" @@ -2906,29 +2914,29 @@ msgstr "1. نماینده خود را به REA متصل کنید" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "کپی" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "یا این دستور را در ترمینال خود اجرا کنید:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2937,14 +2945,14 @@ msgstr "" "نقشه رو بررسي کن ، راه اندازي رو تاييد کن ، بعد ماموريت رو دوباره راه بنداز." " در حال حاضر متصل? ادامه در زیر." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. بپرسید CSV کجا نوشته شده است" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2955,7 +2963,7 @@ msgstr "" "مثال یک برنامه شش فایل Electron با یک {ph0}یادداشت های صادراتی{ph1} دکمه. " "نماینده شما می تواند کد خود را بدون نصب یا راه اندازی Electron بازرسی کند ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2967,14 +2975,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}دانلود نمونه زیپ{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2984,12 +2992,12 @@ msgstr "" "اگر نماینده شما نمی تواند فایل ها را دانلود کند ، خودتان این آرشیو را باز " "کنید. راه رو به سمت {ph0} پوشه و همان سوال صادرات." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. پاسخ را به کد دنبال کنید" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "به دنبال یک توضیح کوتاه با مرجع فایل و خط باشید:" @@ -2998,7 +3006,7 @@ msgstr "به دنبال یک توضیح کوتاه با مرجع فایل و خ #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3009,12 +3017,12 @@ msgstr "" "دکمه یک {ph0} پیام. فرآیند اصلی یادداشت ها را به عنوان CSV فرمت می کند و می " "نویسد {ph1} در پوشه Downloads کاربر. ستون ها عبارتند از {ph2} و {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "از دکمه به نویسنده فایل" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3023,7 +3031,7 @@ msgstr "" "تجزیه و تحلیل استاتیک REA پیام را با کنترل کننده آن جفت می کند. مقصد از کد " "خوانده می شود." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3034,18 +3042,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}مشاهده کد کامل ردیابی و ثبت REA نتیجه{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. پیش بینی را بررسی کنید" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3054,19 +3062,19 @@ msgstr "" "یک کاما ستون های CSV را جدا می کند. چه اتفاقی می افتد وقتی یک عنوان یادداشت " "خود شامل یک علامت یا علامت نقل قول است ؟" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "خودتان چک را اجرا کنید" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "باز کردن یک ترمینال در بسته بندی نشده {ph0} پوشه:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3076,17 +3084,17 @@ msgstr "" " می کند. نماینده شما می تواند همان JavaScript را در پوسته پلتفرم شما اجرا " "کند." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. سوال دیگری بپرسید" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "در همان مکالمه پیگیری کنید:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3094,7 +3102,7 @@ msgid "" msgstr "" "اگه فایل نتونه نوشته بشه چی میشه ؟ خطای بازگشت به صفحه را دنبال کنید." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3107,7 +3115,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3121,7 +3129,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3135,7 +3143,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3160,65 +3168,65 @@ msgstr "" "بپرسید که یادداشت های صادر شده کجا می روند و قالب CSV را با عنوان نمونه " "بررسی کنید." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "اولین تحقیق REA شما" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "کپی REA نصب و راه اندازی prompt" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "دستور Copy setup" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "یادداشت های کپی تحقیقات فوری" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "کپی CSV چک prompt" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "دستور copy formatter check" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "پرش به محتوا" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}خانه{ph1} / شروع کن" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "REA را تنظیم کنید ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3226,49 +3234,49 @@ msgstr "" "REA را به عامل کدگذاری خود متصل کنید یا یک برنامه محلی را از ترمینال خود " "بازرسی کنید." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "ترمینال رو باز کن و چک کن:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "ترمینال" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "کپی" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3281,7 +3289,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3291,17 +3299,17 @@ msgstr "" "اگر PowerShell بعدا می گوید {ph0}\"اجرای اسکریپت ها در این سیستم غیرفعال " "است\"{ph1} وقتی می دوید {ph2}، اين رو يه بار اجرا کن و دوباره امتحان کن:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "اگر از Homebrew استفاده می کنید :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "در غیر این صورت:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "ترمینال رو ببند ، دوباره بازش کن ، بعد:" @@ -3309,7 +3317,7 @@ msgstr "ترمینال رو ببند ، دوباره بازش کن ، بعد:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3321,7 +3329,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3333,7 +3341,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3343,14 +3351,14 @@ msgstr "" "یک نصب کننده معمولی را ترجیح می دهید ؟ دانلود نسخه LTS از " "{ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "گزینه های راه اندازی" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3358,7 +3366,7 @@ msgstr "{ph0}عامل برنامه نویسی خود را وصل کنید{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3366,7 +3374,7 @@ msgstr "{ph0}از CLI استفاده کنید {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3374,18 +3382,18 @@ msgstr "{ph0}راه اندازی تجزیه و تحلیل برنامه های ک #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}کمک گرفتن{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "عامل برنامه نویسی خود را وصل کنید" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3397,12 +3405,12 @@ msgstr "" "Build و سایر مشتریان MCP پشتیبانی شده است. اتصال Grok Bot از چت آن اضافه شده" " است." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "تازه وارد برنامه نویسی ؟" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3413,7 +3421,7 @@ msgstr "" "شما کار می کند. می تواند فایل ها را بخواند و دستورات را اجرا کند و قبل از " "ایجاد تغییرات می پرسد. REA به آن ابزار مهندسی معکوس می دهد." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3425,7 +3433,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3438,7 +3446,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3450,7 +3458,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3460,7 +3468,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}، منبع باز ارائه دهنده مدل مورد نظر خود را " "متصل کنید." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3477,18 +3485,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "یا خودتان راه اندازی کنید" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "چگونه ترمینال را باز کنم ؟" @@ -3497,7 +3505,7 @@ msgstr "چگونه ترمینال را باز کنم ؟" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3513,7 +3521,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3527,7 +3535,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3540,7 +3548,7 @@ msgstr "{ph0} Linux :{ph1} مطبوعات {ph2} {ph3} {ph4} در اکثر دسک #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3550,7 +3558,7 @@ msgstr "" "یک دستور را با {ph0} {ph1} (macOS : {ph2} {ph3}; ترمینال های Linux: {ph4} " "{ph5} {ph6}), سپس Enter را فشار دهید." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3561,12 +3569,12 @@ msgstr "" " مهارت تحقیق تطبیق را اضافه می کند و پشتیبان گیری از پیکربندی موجود را حفظ " "می کند. قبل از اعمال تغییرات می پرسد." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "مشتری خود را پس از اتمام راه اندازی دوباره راه اندازی کنید." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "چطور موکلم رو دوباره راه بندازم ؟" @@ -3575,7 +3583,7 @@ msgstr "چطور موکلم رو دوباره راه بندازم ؟" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3591,7 +3599,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3601,7 +3609,7 @@ msgstr "" "{ph0}عوامل ترمینال{ph1} (Claude Code ، Codex ، Gemini CLI ): از جلسه خارج " "شوید و دوباره شروع کنید." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3611,7 +3619,7 @@ msgstr "" " Electron ، ممکن است با:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3621,12 +3629,12 @@ msgstr "" "نگاه کن {ph0} و نحوه صادرات داده ها را پیدا کنید. نقاط ورود ، تماس ها و " "وابستگی های مربوطه را با مکان های منبع برای یافته های خود نشان دهید." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "مسیر را با هدف محلی خود جایگزین کنید." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "چطور می توانم مسیر کامل یک پوشه را بدست آورم ؟" @@ -3635,7 +3643,7 @@ msgstr "چطور می توانم مسیر کامل یک پوشه را بدست #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3650,7 +3658,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3662,7 +3670,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3671,18 +3679,18 @@ msgid "" msgstr "" "{ph0}هر سیستم:{ph1} پوشه را به یک پنجره ترمینال بکشید و مسیر آن ظاهر می شود." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "در یک ترمینال ، نقل قول ها را در اطراف مسیری قرار دهید که شامل فضاها است." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "از CLI استفاده کنید" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3691,14 +3699,14 @@ msgstr "" "یک پوشه برنامه JavaScript یا Electron یا آرشیو ASAR را بدون اجرای برنامه " "تجزیه و تحلیل کنید:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "تجزیه و تحلیل کاربرد استاتیک" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3708,13 +3716,13 @@ msgstr "" "مسیر را با دایرکتوری برنامه استخراج شده خود جایگزین کنید یا {ph0} فایل. در " "Windows ، مسیری مانند {ph1} اینجا کار میکنه" -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "کجا یه اپلیکیشن پیدا کنم ؟ فایل آسار?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3725,7 +3733,7 @@ msgstr "برنامه های Electron معمولا آن را در یک {ph0} پو #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3737,7 +3745,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3750,21 +3758,21 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} اغلب {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "" "برخی از برنامه ها در جای دیگری نصب می شوند. پوشه برنامه را جستجو کنید {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3775,31 +3783,31 @@ msgstr "" "منبع آنها را می دهد. اتصالات REA نمی تواند حل شود در نتیجه مشخص شده است." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "اگه ميخواي يه {ph0} فرمان در پوسته شما:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "CLI را نصب کنید" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}ادامه با راهنمای برنامه JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "راه اندازی تجزیه و تحلیل برنامه های کد ماشین" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3808,12 +3816,12 @@ msgstr "" "برنامه های کد ماشین نیاز به یک ابزار تجزیه و تحلیل محلی دارند. یکی را در زیر" " انتخاب و پیکربندی کنید ، سپس به REA فایل اجرایی یا کتابخانه خود را بدهید." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "یک ابزار را انتخاب کنید: Ghidra ، Hopper یا IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3824,17 +3832,17 @@ msgstr "" "Linux یا macOS ، در x64 یا arm64. نصب Ghidra شما به یک تجزیه کننده بومی برای" " معماری میزبان شما نیاز دارد. قبل از اجرای تنظیمات مسیرها را تنظیم کنید:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "نصب Ghidra خود را وصل کنید" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "اتصال Ghidra * macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3845,12 +3853,12 @@ msgstr "" "کند و تنظیمات معتبر را برای مشتری انتخاب شده شما ثبت می کند. در Linux arm64 " "، ممکن است لازم باشد تجزیه کننده بومی Ghidra را جداگانه بسازید." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "اتصال Ghidra در Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3861,12 +3869,12 @@ msgstr "" "و x64 PE و Dll ها در درایوهای ntfs محلی ثابت است. از Ghidra 12.1 موجود " "استفاده کنید.x نصب و 64 بیتی JDK 21 یا جدیدتر:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "اتصال Ghidra * Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3874,7 +3882,7 @@ msgstr "" "دو مسیر را با نصب های خود جایگزین کنید ، سپس برنامه راه اندازی را بررسی " "کنید." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3884,7 +3892,7 @@ msgstr "" "این دستور یک نصب موجود را تشخیص می دهد یا یک برنامه نصب برای تأیید شما ارائه" " می دهد." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3893,7 +3901,7 @@ msgstr "" "در macOS ، انتخاب اولین اجرا Hopper از حالت نمایشی یا فعال سازی مجوز را قبل " "از تجزیه و تحلیل بدون نظارت تکمیل کنید." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3904,7 +3912,7 @@ msgstr "" " یک رابط کاربری گرافیکی متصل یا یک پایگاه داده بدون سر. تجزیه و تحلیل بدون " "سر Linux و macOS هنوز تایید نشده است." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "ثبت نام IDA MCP موجود را وصل کنید" @@ -3914,7 +3922,7 @@ msgstr "ثبت نام IDA MCP موجود را وصل کنید" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3926,13 +3934,13 @@ msgstr "" "موجود {ph3} شی با یک {ph4} ورود نیز پذیرفته می شود. نقطه REA در آن فایل قبل " "از راه اندازی:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "اتصال IDA * Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3949,7 +3957,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3960,29 +3968,29 @@ msgstr "" "به REA مسیر اجرایی اصلی را با {ph0} در یک پرس و جو CLI. برای یک نماینده ، " "شامل {ph1} در محیط ثبت REA و انتخاب کنید IDA هنگام باز کردن باینری." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "برای یک راه اندازی Ghidra موجود ، یک تابع را با:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "تجزیه و تحلیل عملکرد" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "جایگزین کنید {ph0} با نام تابع یا آدرس که می خواهید بازرسی کنید." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "چگونه تجزیه و تحلیل برنامه های کد ماشین جلسات کار می کنند" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3995,7 +4003,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4005,18 +4013,18 @@ msgstr "" "{ph0}یک مثال از تجزیه و تحلیل برنامه های کد ماشین را دنبال کنید{ph1} برای " "دیدن اینکه چگونه نتیجه تابع منجر به محاسبه بازیابی می شود." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "کمک گرفتن" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "اگر نماینده شما REA را نمی بیند" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4026,27 +4034,27 @@ msgstr "" "مشتری را پس از راه اندازی مجددا راه اندازی کنید یا دوباره وصل کنید. اتصال " "REA خود را با {ph0}; برای Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "بررسی یک مشتری" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "اگر یک ارائه دهنده نیاز به توجه داشته باشد" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "ارائه دهنده ای که استفاده می کنید را بررسی کنید. برای Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "یک ارائه دهنده را بررسی کنید" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "گزارش چک شکست خورده و گام بعدی پیشنهاد شده را ارائه می دهد." @@ -4055,7 +4063,7 @@ msgstr "گزارش چک شکست خورده و گام بعدی پیشنهاد ش #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4068,7 +4076,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4082,7 +4090,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4094,7 +4102,7 @@ msgstr "{ph0} مسائل GitHub{ph1}{ph2}گزارش یک مشکل با دستو #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4118,112 +4126,112 @@ msgstr "" "Electron را از ترمینال بازرسی کنید. راه اندازی ، سوالات اول و راهنمای ارائه " "دهنده بومی." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "نسخه Node.js را کپی کنید" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "کپی Node.js دستور نصب برای Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "کپی PowerShell اجرای دستور سیاست" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "کپی Homebrew Node.js دستور نصب" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "کپی دستور نصب fnm برای macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "کپی Node.js 24 دستورات برای macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "کپی دستور نصب fnm برای Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "کپی Node.js 24 دستورات برای Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "راهنمای شروع REA" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "کپی REA نصب و راه اندازی prompt" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "دستور Copy agent setup" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "دستور تجزیه و تحلیل JavaScript را کپی کنید" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "دستور نصب CLI را کپی کنید" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "کپی فرمان اتصال Ghidra برای macOS و Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "کپی اتصال Ghidra برای Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "کپی اتصال IDA برای Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "کپی دستور تجزیه و تحلیل تابع بومی" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "دستور تشخیص مشتری را کپی کنید" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "دستور تشخیص ارائه دهنده کپی" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -4232,20 +4240,20 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}خانه{ph1} / {ph2}راهنماها{ph3} / مشاهده مرورگر" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "ببینید چه اتفاقی می افتد{ph0}وقتی کلیک می کنید." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4254,14 +4262,14 @@ msgstr "" "از یک برنامه مرورگر کوچک برای اتصال یک عمل ، درخواست شبکه آن و JavaScript که" " یک بارگیری ایجاد می کند استفاده کنید." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "در این راهنما" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4269,7 +4277,7 @@ msgstr "{ph0}مثال{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4277,7 +4285,7 @@ msgstr "{ph0}مرورگر را باز کنید{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4285,7 +4293,7 @@ msgstr "{ph0}از نماینده خود بپرسید{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4293,13 +4301,13 @@ msgstr "{ph0}ضبط از CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}درخواست و اسکریپت را بخوانید{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "وقتی روی Export کلیک می کنید چه اتفاقی می افتد ؟" @@ -4309,7 +4317,7 @@ msgstr "وقتی روی Export کلیک می کنید چه اتفاقی می ا #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4321,7 +4329,7 @@ msgstr "" "دکمه. با کلیک بر روی آن بارگذاری می شود {ph4}، دو یادداشت را به عنوان CSV " "فرمت می کند و شروع به دانلود می کند." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "از کلیک تا دانلود CSV" @@ -4332,7 +4340,7 @@ msgstr "از کلیک تا دانلود CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4348,7 +4356,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4366,7 +4374,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4376,17 +4384,17 @@ msgstr "" "{ph0}03 * نماینده شما{ph1}{ph2}کد صادرات را بخوانید{ph3}{ph4}درخواست مشاهده " "شده را به {ph5} در {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "قبل از کلیک بر روی یادداشت های صادرات ، ضبط را شروع کنید." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Chrome را با اشکال زدایی از راه دور باز کنید" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4395,21 +4403,21 @@ msgstr "" "مثال یادداشت های میزبان را با یک پروفایل مرورگر جداگانه و یک پورت اشکال " "زدایی محلی باز کنید. در Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "مرورگر مثال را شروع کنید" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "کپی" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4418,7 +4426,7 @@ msgstr "" "از مسیر اجرایی مرورگر نصب شده خود در macOS یا Windows استفاده کنید . شما می " "توانید URL صفحه را با صفحه دیگری که می خواهید بازرسی کنید جایگزین کنید." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4427,7 +4435,7 @@ msgstr "" "REA به این مرورگر موجود متصل می شود. شما کنترل صفحه را حفظ می کنید ، عمل را " "انجام می دهید و مرورگر را پس از اتمام بسته می کنید." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "از مامور خود بخواهید که یک عمل را تماشا کند" @@ -4440,7 +4448,7 @@ msgstr "از مامور خود بخواهید که یک عمل را تماشا #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4452,7 +4460,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4464,7 +4472,7 @@ msgstr "" "{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4474,7 +4482,7 @@ msgstr "" "مثال سریع. به نماینده خود نقطه پایان اشکال زدایی را بدهید, {ph0}، و URL " "صفحه. بگذارید قبل از کلیک ضبط را شروع کند." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4484,23 +4492,23 @@ msgstr "" "نماینده شما هدف صفحه را کشف می کند ، یک پنجره مشاهده را شروع می کند و شواهد " "حاصل را می خواند. سپس می تواند اسکریپت پشت صادرات را بررسی کند." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "یا از ترمینال ضبط کنید" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "شناسه هدف صفحه را پیدا کنید:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "صفحه را پیدا کنید" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4510,14 +4518,14 @@ msgstr "" "هدف را با Notesl مثال یادداشت ها انتخاب کنید. جایگزین کنید {ph0} در زیر با " "ID آن ، سپس اجرا:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "ده ثانیه ی بعد رو ضبط کن" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4527,7 +4535,7 @@ msgstr "" "اجازه دهید دستور برای چند ثانیه متصل شود ، سپس روی {ph0}یادداشت های " "صادراتی{ph1} در اون مرورگر نتیجه پس از پایان پنجره مشاهده می رسد." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4537,49 +4545,49 @@ msgstr "" "نتیجه گرفته شده شامل صفحه انتخاب شده ، فعالیت شبکه در طول آن پنجره و شکل " "پاسخ JSON است. درخواست های قبلی خارج از این دستگیری است." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "درخواست و اسکریپت صادرات را بخوانید" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "با REA 4.1.0 در مثال یادداشت های محلی ضبط شده است" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "واقعیت ثبت شده" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "ارزش" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "درخواست" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "پاسخ" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "درخواست آغازگر" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * اسکریپت" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "ساختار پاسخ" @@ -4587,19 +4595,19 @@ msgstr "ساختار پاسخ" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} با {ph1} و {ph2} رشته ها" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "اسکریپت های لود شده را بخوانید" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4611,7 +4619,7 @@ msgstr "" "شود:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4623,7 +4631,7 @@ msgstr "" " اسکریپت می آید ؛ ضبط شبکه ثابت می کند که این کلیک درخواست شده است {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4635,7 +4643,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4659,65 +4667,65 @@ msgstr "" "مشاهده صادرات یادداشت با REA: یک صفحه مرورگر را انتخاب کنید ، یک کلیک را ضبط" " کنید ، درخواست را بررسی کنید و اسکریپت صادرات را دنبال کنید." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "مشاهده مرورگر" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "کپی کنید ، مرورگر نمونه را شروع کنید" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "کپی مثال prompt" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "کپی پیدا کردن صفحه" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "کپی گرفتن ده ثانیه بعدی" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "کپی خواندن اسکریپت های لود شده" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "پرش به محتوا" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}خانه{ph1} / راهنماها" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "راهنماهای REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4726,37 +4734,37 @@ msgstr "" "تجزیه و تحلیل یک تابع بومی ، صادرات Electron یا درخواست مرورگر. هر راهنما " "شامل یک پیام ، کد و نتایج است." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "اولین تحقیق" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "راه اندازی REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "عامل کدگذاری خود را وصل کنید یا از REA از ترمینال استفاده کنید." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "با REA شروع کنید" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "برنامه های کد ماشین" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "بازیابی محاسبه موقعیت صدای چپ / راست" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4766,22 +4774,22 @@ msgstr "" "تماس گیرنده را دنبال کنید ، ثابت های عددی را بخوانید و C بازیابی شده را " "بررسی کنید." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "تجزیه و تحلیل برنامه های کد ماشین راهنما" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript و Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "صادرات CSV را دنبال کنید" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4790,31 +4798,31 @@ msgstr "" "یک برنامه یادداشت های کوچک یک ویژگی را در رندر ، پیش بارگذاری و فرآیند اصلی " "گسترش می دهد. از REA برای اتصال API ، کانال IPC و file writer استفاده کنید." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "راهنمای JavaScript و Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "" "برای یک برنامه بسته بندی بزرگتر ، دنبال کنید {ph0} پل کلیپ بورد Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "رفتار مرورگر" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "مشاهده یک کلیک" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4823,7 +4831,7 @@ msgstr "" "یک مثال یادداشت های کاری را باز کنید ، یک درخواست صادرات را ضبط کنید و کد را" " پیدا کنید که پاسخ آن را به یک دانلود تبدیل می کند." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "راهنمای مشاهده مرورگر" @@ -4842,12 +4850,12 @@ msgstr "" "REA را از طریق نمونه های کوتاه کار شده یاد بگیرید: یک محاسبه بومی ، یک " "صادرات Electron CSV و یک درخواست مرورگر." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -4856,20 +4864,20 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}خانه{ph1} / {ph2}راهنماها{ph3} / JavaScript و Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "ردیابی Electron {ph0} صادرات CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4878,14 +4886,14 @@ msgstr "" "یک دکمه را دنبال کنید از API صفحه ، از طریق Electron IPC ، به CSV file " "writer کلیک کنید." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "در این راهنما" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4893,7 +4901,7 @@ msgstr "{ph0}مثال{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4901,7 +4909,7 @@ msgstr "{ph0}از نماینده خود بپرسید{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4909,7 +4917,7 @@ msgstr "{ph0}کد صادرات را ردیابی کنید{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4917,20 +4925,20 @@ msgstr "{ph0}مثال را امتحان کنید{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}نویسنده CSV را بازرسی کنید{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"یادداشت های صادراتی\" به کجا می رود؟" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4942,7 +4950,7 @@ msgstr "" " های صادراتی{ph1} یک API را در صفحه فرا می خواند ، به فرآیند اصلی می رود و " "یک CSV می نویسد . این رفتار در چندین پرونده پخش شده است." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "صادرات CSV در سراسر فرآیندهای Electron" @@ -4956,7 +4964,7 @@ msgstr "صادرات CSV در سراسر فرآیندهای Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4973,7 +4981,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4990,7 +4998,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5003,13 +5011,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} یادداشت ها را فرمت می کند → {ph1} می نویسد {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5020,14 +5028,14 @@ msgstr "" " می کند. مسیر از کد استنباط می شود ؛ یک ضبط زمان اجرا می تواند بررسی کند که " "چه چیزی اجرا می شود." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "درباره صادرات CSV بپرسید" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5045,14 +5053,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "کپی" @@ -5063,7 +5071,7 @@ msgstr "کپی" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5074,7 +5082,7 @@ msgstr "" " صادرات یادداشت در این برنامه. CSV در کجا ایجاد شده است ؟ {ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5082,7 +5090,7 @@ msgid "" "{ph0}." msgstr "مثال سریع. شامل مسیر مطلق به پوشه برنامه یا {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5093,17 +5101,17 @@ msgstr "" "فرآیند را می سازد. مامور شما از اون نقشه استفاده ميکنه تا تحقيقات رو به " "خصوصيت صادرات محدود کنه" -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "کد صادرات را ردیابی کنید" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "صفحه یک API کوچک را فرا می خواند" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5114,7 +5122,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5126,7 +5134,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5136,7 +5144,7 @@ msgstr "" "خواندن handler به سوال اصلی پاسخ می دهد: {ph0} یادداشت ها را فرمت می کند و " "فرآیند اصلی می نویسد {ph1} به پوشه دانلود کاربر." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5145,7 +5153,7 @@ msgstr "" "ضبط شده توسط REA 4.1.0 در مثال زیر قابل دانلود است. مکان های منبع همراه با " "api ، کانال و یافته های کنترل کننده است." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "مثال را خودتان تجزیه و تحلیل کنید" @@ -5153,25 +5161,25 @@ msgstr "مثال را خودتان تجزیه و تحلیل کنید" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}دانلود نمونه زیپ{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "شش فایل منبع را مرور کنید" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "تجزیه و تحلیل کاربرد استاتیک" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5181,7 +5189,7 @@ msgstr "" "مسیر را با پوشه ای که باز کرده اید جایگزین کنید. شما باید یک کانال IPC و یک " "کنترل کننده تطبیق در {ph0}. مکان های منبع در {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5192,13 +5200,13 @@ msgstr "" "عامل می تواند یک رشته ، نام API یا کانال IPC را با ابزارهای ردیابی ویژگی REA" " دنبال کند." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "نویسنده CSV را بازرسی کنید" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5208,7 +5216,7 @@ msgstr "" "دنبال کنید {ph0} به دستگیره اش کدام ورودی ها به CSV writer می رسند و اگر " "نوشتن فایل شکست بخورد چه اتفاقی می افتد ؟" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5223,7 +5231,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5237,7 +5245,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5251,7 +5259,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5276,32 +5284,32 @@ msgstr "" "ردیابی یادداشت CSV صادرات از طریق یک api رندر, پیش بار و کنترل IPC با REA . " "شامل فایل های نمونه قابل دانلود و یک نتیجه تجزیه و تحلیل تایید شده است." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript و Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "کپی مثال prompt" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "تجزیه و تحلیل برنامه های استاتیک را کپی کنید" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -5310,7 +5318,7 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5318,13 +5326,13 @@ msgstr "" "{ph0}خانه{ph1} / {ph2}راهنماها{ph3} / تجزیه و تحلیل برنامه های کد ماشین" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "بازیابی DX-Ball{ph0}محاسبه موقعیت صدای چپ / راست." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5333,14 +5341,14 @@ msgstr "" "دستورالعمل های اصلی را بررسی کنید ، ورودی و ثابت ها را شناسایی کنید ، سپس C " "بازیابی شده را بررسی کنید." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "در این راهنما" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5348,7 +5356,7 @@ msgstr "{ph0}مثال{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5356,7 +5364,7 @@ msgstr "{ph0}از نماینده خود بپرسید{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5364,7 +5372,7 @@ msgstr "{ph0}نتایج REA را بخوانید{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5372,18 +5380,18 @@ msgstr "{ph0}بازیابی و بررسی{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}از باینری خود استفاده کنید{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "موقعیت صدای استریو چپ/راست را محاسبه کنید" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5394,7 +5402,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5406,7 +5414,7 @@ msgstr "" "همچنین دستورالعمل ها و تماس گیرندگان خود را باز می گرداند که به نماینده راهی" " برای بررسی حساب گمشده می دهد." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "تازه وارد اين اصطلاحات هستي ؟" @@ -5415,7 +5423,7 @@ msgstr "تازه وارد اين اصطلاحات هستي ؟" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5427,7 +5435,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5440,7 +5448,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5453,7 +5461,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5464,7 +5472,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5474,7 +5482,7 @@ msgstr "" "{ph0}ثابت ها:{ph1} اعداد ثابت ذخیره شده در برنامه ، به عنوان بایت خام خوانده" " شده و رمزگشایی شده است." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "سه قطعه شواهد ، یک محاسبه" @@ -5485,7 +5493,7 @@ msgstr "سه قطعه شواهد ، یک محاسبه" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5502,7 +5510,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5520,7 +5528,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5530,7 +5538,7 @@ msgstr "" "{ph0}03 * بایت داده{ph1}{ph2}ثابت های عددی{ph3}{ph4}بایت های مرجع رمزگشایی " "به {ph5}, {ph6} و یک مقدار مقیاس.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5539,7 +5547,7 @@ msgstr "" "REA دستورالعمل ها ، رابطه فراخوان تابع و بایت ها را ارائه می دهد. عامل آنها " "را با هم تفسیر می کند." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "در مورد رفتار بپرسید" @@ -5548,7 +5556,7 @@ msgstr "در مورد رفتار بپرسید" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5558,19 +5566,19 @@ msgstr "" "بعد از {ph0}اتصال REA به نماینده شما{ph1} و {ph2}تنظیم یک ابزار تجزیه و " "تحلیل برنامه های کد ماشین{ph3}، ارائه فایل اجرایی محلی و یک سوال:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "از کدام ابزار تجزیه و تحلیل استفاده کنم؟" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA برای خواندن برنامه های بومی به یکی از این موارد نیاز دارد:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5584,7 +5592,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5596,7 +5604,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5605,7 +5613,7 @@ msgstr "{ph0} IDA {ph1} (Windows) : برای راه اندازی IDA موجود #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5620,14 +5628,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "کپی" @@ -5638,7 +5646,7 @@ msgstr "کپی" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5648,7 +5656,7 @@ msgstr "" "{ph0}›{ph1}{ph2}استفاده از REA برای پیدا کردن چگونه DX-Ball محاسبه موقعیت " "صدا استریو. محاسبه را توضیح دهید و کد را نشان دهید.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5659,7 +5667,7 @@ msgstr "" "REA شامل DX-Ball نیست ، بنابراین از نسخه خود استفاده کنید ، یا همان نوع سوال" " را در مورد یک برنامه کوچک Windows که دارید بپرسید." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "چطور می توانم مسیر کامل یک فایل را بدست آورم ؟" @@ -5668,7 +5676,7 @@ msgstr "چطور می توانم مسیر کامل یک فایل را بدست #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5683,7 +5691,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5695,7 +5703,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5704,17 +5712,17 @@ msgid "" msgstr "" "{ph0}هر سیستم:{ph1} فایل را به یک پنجره ترمینال بکشید و مسیر آن ظاهر می شود." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "نتایج REA را بخوانید" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "ورودی را بخوانید" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5723,13 +5731,13 @@ msgstr "" "دستورالعمل ها یک استدلال عدد صحیح را بارگذاری می کنند و آن را برای حساب نقطه" " شناور تبدیل می کنند. این ورودی غایب از اولین نمای شبه کد است." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "تماس گیرنده را دنبال کنید" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5740,12 +5748,12 @@ msgstr "" "کاشی را با 30 ضرب می کند ؛ اضافه کردن {ph0} (20) موقعیت صفحه نمایش آجر را می" " دهد." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "ثابت های مرجع را بخوانید" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5754,12 +5762,12 @@ msgstr "" "حساب ها به این آدرس ها اشاره می کنند. خواندن بایت ها ارزش های واقعی را فراهم" " می کند ؛ دستور دستورالعمل به عامل می گوید که چگونه از آنها استفاده می شود." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "عملکرد بازیابی شده را بنویسید و بررسی کنید" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5769,7 +5777,7 @@ msgstr "" "با مقیاس 1.0 ، موقعیت صفحه نمایش 0 ، 320 و 640 نقشه به -500 ، 0 و 500 قبل از" " تبدیل عدد صحیح. محاسبه مرکز صفحه را در مرکز میدان استریو قرار می دهد." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5782,20 +5790,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}بررسی کامل و مقایسه مونتاژ به C را ببینید{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "آن را با باینری خود امتحان کنید" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5809,7 +5817,7 @@ msgstr "" "سوالات مفید شروع شامل \" این فایل چگونه تجزیه می شود ؟ \"یا\" کدام تابع این " "عمل منو را مدیریت می کند ؟ ”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5818,13 +5826,13 @@ msgstr "" "اگر قبلا یک نام یا آدرس تابع را می دانید ، می توانید آن را از ترمینال پرس و " "جو کنید. برای نصب Ghidra پیکربندی شده:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "تجزیه و تحلیل عملکرد" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5838,7 +5846,7 @@ msgstr "" "جوهای MCP نماینده شما در حالی که جلسه باز است ، از باینری وارد شده استفاده " "می کند." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5861,50 +5869,50 @@ msgstr "" "بازیابی یک محاسبه بومی با REA: دستورالعمل ها را بررسی کنید ، یک تماس گیرنده " "را دنبال کنید ، ثابت ها را بخوانید و C بازسازی شده را بررسی کنید." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "تجزیه و تحلیل برنامه های کد ماشین" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "کپی مثال prompt" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "تجزیه و تحلیل تابع کپی" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "پرش به محتوا" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "راه اندازی REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5912,7 +5920,7 @@ msgstr "{ph0}راه اندازی REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5920,7 +5928,7 @@ msgstr "{ph0}RE چیست؟{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5928,7 +5936,7 @@ msgstr "{ph0}REA چگونه کمک می‌کند{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5936,7 +5944,7 @@ msgstr "{ph0}بازی دایناسور{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5944,7 +5952,7 @@ msgstr "{ph0}ماشین حساب{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5952,7 +5960,7 @@ msgstr "{ph0}REA را امتحان کنید {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5960,7 +5968,7 @@ msgstr "{ph0}بیشتر بدانید{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5968,25 +5976,25 @@ msgstr "{ph0}کمک و بازخورد{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}جامعه{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "مهندسی معکوس ، با عامل برنامه نویسی شما" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "بفهمید نرم‌افزار{ph0}چطور کار می‌کند." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5997,7 +6005,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6006,13 +6014,13 @@ msgstr "" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "میخوای عمیق تر بری ؟ {ph0}وبلاگ را بخوانید →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "این درخواست را در دستیار برنامه‌نویسی خود وارد کنید:" @@ -6025,39 +6033,39 @@ msgstr "این درخواست را در دستیار برنامه‌نویسی #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "کپی" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "یا این دستور را در ترمینال اجرا کنید:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "" "برنامهٔ تغییرات را بررسی و تأیید کنید، سپس دستیار را دوباره راه‌اندازی کنید." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "مهندسی معکوس چیست؟" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6070,7 +6078,7 @@ msgstr "فهمیدن شیوهٔ کار نرم‌افزار از راه {ph0}بر #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6082,7 +6090,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6090,7 +6098,7 @@ msgstr "پیش از REA · {ph0}خودتان{ph1} بررسی می‌کنید" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6098,7 +6106,7 @@ msgstr "{ph0}01{ph1} شاخه ها را رمزگشایی کنید" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6106,7 +6114,7 @@ msgstr "{ph0}02{ph1} تماس های ردیابی" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6116,20 +6124,20 @@ msgstr "{ph0}03{ph1} قانون را بازیابی کنید" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}اصلی x64 * دستورالعمل های انتخاب شده{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * کدام شعبه؟" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6138,29 +6146,29 @@ msgid "" msgstr "" "“{ph0}0x5b? 0x5c?{ph1} دو پرش به یک مکان این ها کدام اپراتورها هستند ؟ ”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "به شناسه های فرمان نگاه کنید ، سپس شاخه را برچسب بزنید." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "تقسیم" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "ضرب ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · تابع‌های فراخوانی‌شده چه می‌کنند؟" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6170,24 +6178,24 @@ msgstr "" "\"100 روشن است. تماس ها فقط آدرس هستن {ph0}کدام یک تقسیم می شود ؟ کدام " "مقدار وارد می شود ؟ {ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "توابع یاور را بررسی کنید و مقادیر ذخیره شده را ردیابی کنید." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "تقسیم" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * قانون چیست؟" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6197,19 +6205,19 @@ msgstr "" "\"این مسیر با ورودی دیگر ضرب می شود. پس {ph0}10 درصد به معنی 10 درصد از " "200{ph1} بعد از +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "نام operands و بررسی هر دو مسیر اپراتور." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "استدلال متخصص تصویرسازی" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6221,20 +6229,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "با REA · از {ph0}دستیارتان{ph1} می‌پرسید" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "فقط یک درخواست." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6248,42 +6256,42 @@ msgstr "از دستیار {ph0}با زبان ساده{ph1} سؤال کنید." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال سریع * ماشین حساب" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "مثال پاسخ · بر اساس یافته ها" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "بعد از + ، دکمه % طول می کشد {ph0}درصد از عدد اول{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA چه چیزی فراهم می‌کند" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "دستورالعمل های کنترل کننده ، کد و تماس های کامپایل شده." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "دستیار چه چیزی توضیح می‌دهد" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "" @@ -6291,7 +6299,7 @@ msgstr "" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6303,7 +6311,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6313,37 +6321,37 @@ msgstr "" "{ph0}بیایید دو مثال را امتحان کنیم.{ph1} سرعت بازی را تغییر دهید ، سپس به " "ماشین حساب برگردید و دکمه % آن را بازسازی کنید." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "مثال 01 * بازی دایناسور Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "چرا دایناسور سریع‌تر می‌شود؟" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "هدف" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "بازی را با {ph0}سرعت قابل تنظیم{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "چرا مهندسی معکوس it ؟" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6353,49 +6361,49 @@ msgstr "" "برای بازتولید شتاب آن ، ما نیاز داریم {ph0}قانون در بازی در حال اجرا{ph1}: " "چقدر سریع شروع می شود ، چقدر افزایش می یابد و چه زمانی متوقف می شود." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "نسخهٔ بازسازی‌شده را بازی کنید" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "بازی" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "پرش ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "شروع دوباره" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "سرعت" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "از قانون شتاب بازیابی شده استفاده کنید" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "قانون اصلی: از 6 شروع کنید ، سپس به سمت 13 افزایش دهید." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "نوار لغزنده را حرکت دهید تا سرعت خود را تنظیم کنید. فضا یا پرش یک کاکتوس را " "پاک می کند." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6403,14 +6411,14 @@ msgid "" msgstr "" "JavaScript را قادر به بازی بازسازی کنید. کد و توضیح بالا قابل خواندن است." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA چه نتیجه‌ای برگرداند" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6429,7 +6437,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6441,7 +6449,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال سریع * بازی د #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6455,7 +6463,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6467,7 +6475,7 @@ msgstr "هدف بازرسی شده: {ph0}نسخه مرورگر مشتق شده #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6477,12 +6485,12 @@ msgstr "" "{ph0}از 6 شروع کن{ph1} اضافه کردن {ph2}0.001{ph3} هر به روز رسانی بدون " "برخورد ، در حالی که سرعت زیر است {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "آزمایشگاه سرعت را باز کنید →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "کاری که هر قسمت انجام میده" @@ -6493,7 +6501,7 @@ msgstr "کاری که هر قسمت انجام میده" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6509,7 +6517,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6526,7 +6534,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6536,13 +6544,13 @@ msgstr "" "{ph0}03 * شما{ph1}{ph2}تغییر سرعت و بازی{ph3}{ph4}شتاب اصلی را امتحان کنید ،" " سپس سرعت خود را انتخاب کنید.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "اسکریپت ، چک ها و نحوه امتحان کردن تحلیل را ببینید" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6552,7 +6560,7 @@ msgstr "" "REA نسخه مرورگر HTTP را از طریق یک اتصال اشکال زدایی محلی بازرسی کرد و نسخه " "بارگذاری شده را بازگرداند {ph0}، از جمله منبع و هضم آن." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6565,7 +6573,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6581,7 +6589,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6598,7 +6606,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6606,19 +6614,19 @@ msgid "" msgstr "" "{ph0}کد سرعت بازرسی شده{ph1} · {ph2} Chromium نویسندگان * مجوز bsd{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "مثال 02 * ماشین حساب Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "دکمهٔ % ماشین‌حساب را بازسازی کنید." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6627,7 +6635,7 @@ msgstr "یک ماشین حساب کوچک بسازید که {ph0}هر دو + و #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6637,29 +6645,29 @@ msgstr "" "همان دکمه استفاده می کند {ph0}قوانین مختلف بعد از + و ×.{ph1} ما برنامه نصب " "شده را بررسی می کنیم تا دریابیم درصد به کدام شماره اعمال می شود." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "محاسبه را امتحان کنید" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "بازنشانی" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10 درصد از 200 = 20 سپس 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "تصویر تعاملی از قانون درصد بازرسی شده." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6671,7 +6679,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6685,7 +6693,7 @@ msgstr "برای این مثال, {ph0} و {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6700,7 +6708,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6712,7 +6720,7 @@ msgstr "" "قوانین را پس از + و × بازیابی کنید ، سپس یک ماشین حساب کوچک بسازید که از هر " "دو استفاده کند.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "با +" @@ -6720,13 +6728,13 @@ msgstr "با +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}10 درصد از عدد اول را بگیرید.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "با ×" @@ -6734,13 +6742,13 @@ msgstr "با ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}10% را به 0.1 تبدیل کنید.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "از برنامه نصب شده به یک دکمه کار %" @@ -6752,7 +6760,7 @@ msgstr "از برنامه نصب شده به یک دکمه کار %" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6770,7 +6778,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6782,12 +6790,12 @@ msgstr "" "بازتولید کنید{ph3}{ph4}شاخه را با منبع مایکروسافت بررسی کنید ، سپس + و × " "بالا را امتحان کنید.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "کد واقعی و نحوه بررسی پاسخ را ببینید" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6807,7 +6815,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6817,17 +6825,17 @@ msgstr "" "{ph0}درصد پیاده سازی{ph1} · {ph2}موارد تست مایکروسافت{ph3} · {ph4}راهنمای " "راه اندازی بومی{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "اولین تحقیق شما" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "REA را در یک برنامه کوچک امتحان کنید." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6836,12 +6844,12 @@ msgstr "" "نمونه یادداشت های ما را دانلود کنید ، صادرات CSV آن را ردیابی کنید و یک " "ورودی تغییر یافته را بررسی کنید." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "مثال هدایت شده را امتحان کنید" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "می‌خواهید بیشتر بدانید؟" @@ -6850,7 +6858,7 @@ msgstr "می‌خواهید بیشتر بدانید؟" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6870,13 +6878,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال prompt * وب سایت" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "بله این یکی" @@ -6889,7 +6897,7 @@ msgstr "بله این یکی" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6902,7 +6910,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}مثال سریع * بازساز #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6915,23 +6923,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}مطالعه موردی DX-Ball را ببینید →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "برای مراحل راه اندازی و تجزیه و تحلیل ، هدف خود را انتخاب کنید:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "برنامه های کد ماشین" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -6940,17 +6948,17 @@ msgstr "" "توابع ، رشته ها ، مرجع ها و روابط فراخوان تابع را در فایل های اجرایی و " "کتابخانه ها بازرسی کنید." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "تجزیه و تحلیل برنامه های کد ماشین راهنما" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript و Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -6959,17 +6967,17 @@ msgstr "" "ماژول های نقشه ، مسیرها ، IPC و وابستگی های بومی از یک پوشه برنامه یا آرشیو " "ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "گردش کار برنامه" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "مرورگر و فعالیت زمان اجرا" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -6978,12 +6986,12 @@ msgstr "" "ضبط مرورگر انتخاب شده یا فعالیت فرآیند ، سپس مقایسه نتایج در سراسر اجرا می " "شود." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "راهنمای مشاهده مرورگر" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "سؤالی دارید؟" @@ -6994,7 +7002,7 @@ msgstr "سؤالی دارید؟" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7004,12 +7012,12 @@ msgstr "" "{ph0}سوالات متداول را بخوانید{ph1}, {ph2}چت با ما در Discord {ph3} یا " "{ph4}یک شماره GitHub را باز کنید{ph5} برای اشکالات و درخواست ویژگی." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "به جامعه بپیوندید" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7032,27 +7040,27 @@ msgstr "" "برنامه های مهندسی معکوس ، باینری ها و رفتار مرورگر با عامل برنامه نویسی شما." " راهنماهای واضح را دنبال کنید و نمونه های تعاملی را با REA امتحان کنید ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "کپی REA نصب و راه اندازی prompt" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "دستور Copy setup" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "تجزیه و تحلیل ماشین حساب دستی را دنبال کنید" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "کپی ماشین حساب درصد سوال" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7061,37 +7069,37 @@ msgstr "" "دایناسور مینی بازی. در حالی که بازی متمرکز است از دکمه پرش یا فضای فشار " "استفاده کنید." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "کپی دایناسور تجزیه و تحلیل فوری" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "محاسبه را انتخاب کنید" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "کپی ماشین حساب تجزیه و تحلیل سریع" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "کپی وب سایت project prompt" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "کپی بازی بازسازی سریع" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -7100,25 +7108,25 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}خانه{ph1} / {ph2}ویترین ها{ph3} / اندروید" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "مطالعه موردی * Aegis Authenticator" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "چگونه یک authenticator{ph0}یک کد ورود ایجاد کنید?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7128,17 +7136,17 @@ msgstr "" "Android استفاده کنید ، سپس آن را با ساعتی که می توانید کنترل کنید بازسازی " "کنید." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * اندروید * انتشار رسمی APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "مشاهده Aegis در GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "از یک APK به یک کد شما می توانید تولید مثل" @@ -7149,7 +7157,7 @@ msgstr "از یک APK به یک کد شما می توانید تولید مثل" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7167,7 +7175,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7185,7 +7193,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7197,14 +7205,14 @@ msgstr "" "نسخه ی نمایشی مرورگر جدید این قانون را بازتولید می کند و آن را با موارد مرجع" " عمومی بررسی می کند.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "در این مطالعه موردی" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7212,7 +7220,7 @@ msgstr "{ph0}از نماینده خود بپرسید{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7220,7 +7228,7 @@ msgstr "{ph0}ژنراتور کد را امتحان کنید{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7228,7 +7236,7 @@ msgstr "{ph0}پیدا کردن کد با REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7236,7 +7244,7 @@ msgstr "{ph0}محاسبه را بخوانید{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7244,20 +7252,20 @@ msgstr "{ph0}بازسازی را بررسی کنید{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}APK را خودتان بازرسی کنید{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "از نماینده خود بپرسید" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7275,21 +7283,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "کپی" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7299,14 +7307,14 @@ msgstr "" "یک مثال برای APK دانلود شده ، با تجزیه و تحلیل اندروید REA پیکربندی شده است." " {ph0}APK و راه اندازی تجزیه و تحلیل را دریافت کنید ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "ژنراتور کد را امتحان کنید" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7318,33 +7326,33 @@ msgstr "" " حساب برای تولید یک کد ترکیب می کند. همان کلید و بلوک همان کد را تولید می " "کنند." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "ساعت را در طول 60 ثانیه حرکت دهید" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "زمان" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "ثانیه ها" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "ساعت نمونه قابل تنظیم ما" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "بلوک 30 ثانیه ای" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "بلوک" @@ -7353,35 +7361,35 @@ msgstr "بلوک" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 ثانیه{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "کد تولید شده" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "کلید حساب + بلوک → شش رقمی" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "زمان مثال ، در ثانیه" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 ثانیه" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 ثانیه" @@ -7390,7 +7398,7 @@ msgstr "60 ثانیه" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7402,7 +7410,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7412,7 +7420,7 @@ msgstr "" "کلید ثابت است ، عمومی {ph0}داده های تست rfc 6238{ph1}. دمو محاسبه بازیابی " "شده از APK را اجرا می کند ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7421,18 +7429,18 @@ msgstr "" "نمودار نتیجه را در 59 ثانیه نشان می دهد. JavaScript را برای تغییر ساعت فعال " "کنید." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "پیدا کردن کد با REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "APK را به سه کلاس محدود کنید" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7442,14 +7450,14 @@ msgstr "" "{ph0} دو مورد دیگر مربوط به نوار پیشرفت و حساب های وارداتی است. TOTP به " "معنی یک رمز عبور یک بار مبتنی بر زمان است." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "ژنراتور را به صفحه نمایش برنامه وصل کنید" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7460,7 +7468,7 @@ msgstr "" "می کند. بازرسی {ph0} سپس تماس نمایشگر را نشان می دهد {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7470,14 +7478,14 @@ msgstr "" "درخواست ها یک مسیر ورودی کوتاه را نشان می دهند. نام کلاس های نتیجه مشترک را " "حذف می کنند {ph0} پیشوند." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "محاسبه را بخوانید" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7491,7 +7499,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7499,7 +7507,7 @@ msgstr "{ph0}01{ph1} بلوک زمانی" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7507,7 +7515,7 @@ msgstr "{ph0}02{ph1} کلید + بلوک" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7515,7 +7523,7 @@ msgstr "{ph0}03{ph1} شش رقمی" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7527,7 +7535,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7540,7 +7548,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7554,7 +7562,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7564,7 +7572,7 @@ msgstr "" "گزیده هایی از چندین روش بازرسی شده ، با بسته بندی خط برای نمایش. پانل سمت " "راست یک خلاصه توضیحی است. {ph0} کد Aegis GPL-3.0 است.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "داخل ژنراتور" @@ -7573,7 +7581,7 @@ msgstr "داخل ژنراتور" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7583,7 +7591,7 @@ msgstr "" "APK منتشر شده قرار می دهد {ph0} در {ph1}. REA به دنبال تماس از {ph2} و این " "بدن را باز می گرداند ؛ منبع اصلی به کمک کننده زنگ می زند {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7600,20 +7608,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}با منبع انتشار تطبیق یافته مقایسه کنید{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "بازسازی را بررسی کنید" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7625,29 +7633,29 @@ msgstr "" "خروجی آنها با بازسازی مستقل در {ph0}133 مورد آزمایش{ph1}، شامل مرزهای بلوک " "زمانی و کد هایی که با صفر شروع می شوند." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "زمان مثال" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "کد شش رقمی" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 ثانیه" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 ثانیه" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7657,17 +7665,17 @@ msgstr "" "ژنراتور همچنین با شش مورد مرجع SHA-1 منتشر شده در {ph0}RFC 6238{ph1}. پیاده " "سازی مرورگر را با آنها بررسی کنید:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "چک های مرجع را اجرا کنید" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "محاسبه دمو را بخوانید" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7676,7 +7684,7 @@ msgstr "" "موارد مرجع از هشت رقم استفاده می کنند. این چک همچنین نتایج شش رقمی آنها را " "تأیید می کند." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7685,14 +7693,14 @@ msgstr "" "Verification روش های جاوا استخراج شده و دمو جدید را اجرا می کند. اندروید APK" " به صورت استاتیک بازرسی شد." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "APK را خودتان بازرسی کنید" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7704,7 +7712,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7714,18 +7722,18 @@ msgstr "" "Analysis Android به JDK 17 کامل یا بالاتر نیاز دارد. انتخاب کنید با {ph0} یا" " {ph1}. این مورد از JDK 21 استفاده کرد." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "نقطه REA در فایل ارائه دهنده و بازرسی APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7737,7 +7745,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7747,7 +7755,7 @@ msgstr "" "سوال بعدی: {ph0}چه اتفاقی می افتد وقتی یک حساب کاربری از هشت رقم یا یک فاصله" " زمانی متفاوت استفاده می کند ؟ {ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "منابع" @@ -7763,7 +7771,7 @@ msgstr "منابع" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7777,13 +7785,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}پرونده های مرجع rfc 6238{ph1} · {ph2}داده های تست دمو{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7808,37 +7816,37 @@ msgstr "" "Aegis Android APK را با REA بازرسی کنید ، محاسبه کد ورود شش رقمی خود را " "بازیابی کنید و بازسازی را با یک ساعت قابل تنظیم امتحان کنید." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "مطالعه موردی Aegis APK" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "کپی Aegis مثال prompt" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "محاسبه کد ورود را دنبال کنید" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "کپی APK دستور بازرسی" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -7847,26 +7855,26 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}خانه{ph1} / {ph2}ویترین ها{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "مطالعه موردی · DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "پرچم را در{ph0}یک باینری CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7876,17 +7884,17 @@ msgstr "" "از REA برای بازرسی یک چک کننده پرچم کوچک استفاده کنید ، قوانین آن را به " "معادلات تبدیل کنید و ورودی را پیدا کنید که برنامه اصلی را چاپ کند {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "مربع نقاب دار چک پرچم * آسان * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "چالش اصلی را مشاهده کنید" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "از یک باینری به یک پاسخ چک شده" @@ -7897,7 +7905,7 @@ msgstr "از یک باینری به یک پاسخ چک شده" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7914,7 +7922,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7932,7 +7940,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7944,20 +7952,20 @@ msgstr "" "پایتون معادلات را حل می کند. REA برنامه اصلی پذیرش نتیجه را ضبط می " "کند.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "چالش توسط جوزف است که در مخزن رسمی DownUnderCTF منتشر شده است." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "در این مطالعه موردی" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7965,7 +7973,7 @@ msgstr "{ph0}کد چک کردن را پیدا کنید{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7973,7 +7981,7 @@ msgstr "{ph0}یک ماسک بخوانید{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7981,7 +7989,7 @@ msgstr "{ph0}مونتاژ به کد قابل خواندن{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7989,7 +7997,7 @@ msgstr "{ph0}معادلات را حل کنید{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7997,20 +8005,20 @@ msgstr "{ph0}پاسخ را بررسی کنید{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}خودتان امتحان کنید{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "کد چک کردن را پیدا کنید" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8028,17 +8036,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "کپی" @@ -8049,7 +8057,7 @@ msgstr "کپی" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8061,7 +8069,7 @@ msgstr "" "استفاده کنید. نحوه کار چک ها را توضیح دهید ، سپس پاسخ را با برنامه اصلی " "تأیید کنید.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8070,12 +8078,12 @@ msgstr "" "یک مثال سریع، با چالش دانلود شده در دسترس محلی و تجزیه و تحلیل ارائه دهنده " "برنامه های کد ماشین متصل شده است." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "از دستور ورودی به تابع آن پیروی کنید" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8084,14 +8092,14 @@ msgstr "" "مرجع به مامور جایی برای تحقیق می دهد ، حتی اگر نام های اصلی تابع اجرایی حذف " "شده باشند." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "چک کننده و دو کمک کننده اش رو بخون" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8103,7 +8111,7 @@ msgstr "" "کند ، کدهای انتخاب شده را جمع می کند و نتیجه را با یک عدد ذخیره شده مقایسه " "می کند. اون {ph0}- گام های بایت در سراسر {ph1} بایت ها 26 ماسک می دهند." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8112,12 +8120,12 @@ msgstr "" "این نتایج از تجزیه و تحلیل REA تازه انتخاب شده است. مسیر هدف محلی برای نمایش" " کوتاه می شود ؛ آدرس ها به تصویر وارد شده REA مراجعه می کنند." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "یک چک یک شخصیت را نشان می دهد" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8130,13 +8138,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "بررسی هفتم فقط یک موقعیت را انتخاب می کند. {ph0}شکل باز{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "ماسک و هدف آن را از باینری بخوانید" @@ -8145,7 +8153,7 @@ msgstr "ماسک و هدف آن را از باینری بخوانید" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8157,12 +8165,12 @@ msgstr "" " دلیل است {ph1} به معنی -21 هدف یک عدد صحیح اندکی است. با هم ، این بایت ها " "به عامل می گویند که {ph2}، پس اون شخصیت {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "از دستورالعمل ها تا چک قابل خواندن" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8173,7 +8181,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8181,7 +8189,7 @@ msgstr "{ph0}01{ph1} شروع کن" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8189,7 +8197,7 @@ msgstr "{ph0}02{ph1} انتخاب کنید" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8197,7 +8205,7 @@ msgstr "{ph0}03{ph1} اضافه کردن" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8205,18 +8213,18 @@ msgstr "{ph0}04{ph1} پیشبرد" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} مقایسه کنید" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * دستورالعمل های اصلی انتخاب شده" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "قابل خواندن c * یک چک خلاصه" @@ -8224,7 +8232,7 @@ msgstr "قابل خواندن c * یک چک خلاصه" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8233,7 +8241,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8245,7 +8253,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8257,7 +8265,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8271,7 +8279,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8281,7 +8289,7 @@ msgstr "" "{ph0}05 * با هدف ذخیره شده مقایسه کنید.{ph1} تماس گیرنده مبلغ را در {ph2}. " "عدم تطابق به {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8290,12 +8298,12 @@ msgstr "" "دستورالعمل ها از طرف کمک کننده جمع آوری و تماس گیرنده اش می آید. C یک خلاصه " "توضیحی با نام های توصیفی و یک حلقه 36 سلولی مسطح است." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "معادلات 26 را حل کنید" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8306,13 +8314,13 @@ msgstr "" "کاراکتر اضافه می کند و در مجموع 1441 مورد نیاز دارد. انتخاب های همپوشانی " "معادلاتی را ارائه می دهند که یک اسکریپت کوچک پایتون می تواند با هم حل کند." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "پایتون * گزیده حل کننده" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8326,19 +8334,19 @@ msgstr "" "حروف ، ارقام ، زیرنویس ها و بریس ها. دانلود کامل شامل تمام 26 ماسک و هدف " "است." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "دانلود حل کننده کامل" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "پاسخ را با برنامه اصلی بررسی کنید" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8350,47 +8358,47 @@ msgstr "" "کند. تغییر یک کاراکتر انتخاب شده از {ph0} به {ph1} اولین مبلغ 1440 را به جای" " 1441 می سازد و برنامه آن را رد می کند." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "ورودی" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "خروجی مشاهده شده" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "کد خروج" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "پرچم حل کننده" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "یک شخصیت تغییر کرد" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "نشان دادن پرچم بازیابی شده و خروجی گرفته شده" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * خروجی برنامه اصلی" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "پرچم کپی" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8399,12 +8407,12 @@ msgstr "" "مقدار بازیابی شده همچنین با پرچم در متا داده های چالش منتشر شده سازمان " "دهندگان مطابقت دارد که پس از حل باینری بررسی شده است." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "منبع ، هویت هدف و جزئیات تجزیه و تحلیل" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8414,7 +8422,7 @@ msgstr "" "تجزیه و تحلیل تازه و دو فرآیند ضبط در 8 اکتبر 2026 ، با استفاده از REA 4.1.0" " با Ghidra 12.1.4 در Linux x64. باینری یک ELF x86-64 است که 15248 بایت است." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8436,7 +8444,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8446,12 +8454,12 @@ msgstr "" "{ph0}با منبع سازمان دهندگان مقایسه کنید{ph1} · {ph2}چالش متا داده ها و " "پرچم{ph3} · {ph4} یادداشت های شواهد REA{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "خودتان امتحان کنید" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8460,13 +8468,13 @@ msgstr "" "چالش اصلی و حل کننده را در یک پوشه دانلود کنید. از دستور بالا برای تحقیق با " "نماینده خود استفاده کنید یا اسکریپت همراه را اجرا کنید." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "ترمینال * حل و اجرا" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8477,7 +8485,7 @@ msgstr "" "اسکریپت پرچم کاندیداها را چاپ می کند ؛ آن را در دستور برنامه چسبانید. حل " "نیازها پایتون و {ph0}. اجرای فایل اجرایی اصلی نیاز به Linux x86-64 دارد." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "REA را با عامل کدگذاری خود تنظیم کنید" @@ -8498,27 +8506,27 @@ msgstr "" "توابع چک کردن را پیدا کنید ، ماسک ها را استخراج کنید و یک پرچم بازیابی شده " "را با برنامه اصلی مقایسه کنید." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "مطالعه موردی ctf flag-checker" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "کپی نمونه ctf prompt" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "معادله ماسک ctf ؛ به صورت افقی روی صفحه نمایش های کوچکتر حرکت کنید" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8529,42 +8537,42 @@ msgstr "" "می کند. فقط اون سلول به جمع کمک ميکنه کد کاراکتر مورد نیاز آن 55 است ، به " "این معنی که کاراکتر 7 است." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "بررسی CTF را دنبال کنید" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "کپی ctf مونتاژ" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Ctf قابل خواندن را کپی کنید" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "کپی ctf solver گزیده" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "کپی پرچم بازیابی شده" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "دستورات ctf solver را کپی کنید" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -8573,25 +8581,25 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}خانه{ph1} / {ph2}ویترین ها{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "مطالعه موردی * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "بازسازی DX-Ball {ph0}از فایل اجرایی آن." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8600,14 +8608,14 @@ msgstr "" "هدف یک نسخه c قابل نگهداری از بازی Windows 1996 است. REA به عامل کمک می کند" " تا اصل را بازرسی کند ، یک عملکرد در یک زمان." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8619,14 +8627,14 @@ msgstr "" "های خوانده شده را ارائه می دهد ؛ پروژه بازسازی نتیجه را اجرا و آزمایش می " "کند. {ph0}شکل باز{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "در این مطالعه موردی" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8634,7 +8642,7 @@ msgstr "{ph0}پروژه{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8642,7 +8650,7 @@ msgstr "{ph0}پان صدا{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8650,23 +8658,23 @@ msgstr "{ph0}بررسی نتیجه{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}ادامه کار{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "توابع c نگهداری شده" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "مقایسه با کد اصلی" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "توابع با تطبیق بایت های کامپایل شده" @@ -8677,7 +8685,7 @@ msgstr "توابع با تطبیق بایت های کامپایل شده" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8686,12 +8694,12 @@ msgid "" msgstr "" "بازرسی پروژه: 7 اکتبر 2026. {ph0}دفتر کل پیشرفت{ph1} · {ph2}پوشش تست{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "پروژه تا کنون" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8705,12 +8713,12 @@ msgstr "" " فراهم می کند. کار بر روی بازی قابل پخش با فیزیک توپ و بادکنک ، دست زدن به " "قدرت و ادغام Windows ادامه دارد." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "پیدا کردن محاسبه موقعیت صدا چپ / راست" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8729,17 +8737,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "کپی" @@ -8750,7 +8758,7 @@ msgstr "کپی" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8760,7 +8768,7 @@ msgstr "" "{ph0}›{ph1}{ph2}استفاده از REA برای پیدا کردن چگونه DX-Ball محاسبه موقعیت " "صدا استریو. محاسبه را توضیح دهید و کد را نشان دهید.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8770,7 +8778,7 @@ msgstr "" "یک مثال برای عامل کدگذاری شما ، با فایل اجرایی محلی در دسترس است. تحقیقات " "زیر سوالات REA و شواهد پشت پاسخ را نشان می دهد." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8784,7 +8792,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8797,12 +8805,12 @@ msgstr "" " دستورالعمل آن ورودی پشته و عملیات نقطه شناور را نشان می داد. اين اختلاف به " "مامور دليل مشخصي براي ادامه تحقيقات داد" -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "اولین نمایش decompiler" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8811,18 +8819,18 @@ msgstr "" "خروجی یک تماس تبدیل را نشان می دهد. خواندن دستورالعمل های زیر نشان می دهد " "ورودی و محاسبه تغذیه که تماس." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "پاسخ به سه سوال از طریق REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "بازیابی ورودی گمشده" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8832,14 +8840,14 @@ msgstr "" "نتیجه تابع شامل دستورالعمل ها در کنار کد شبه و تماس گیرندگان است. اینجا, " "{ph0} ورودی عدد صحیح را که از نمای decompiler گم شده است ، نشان می دهد." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "تماس گیرنده را دنبال کنید تا ورودی را درک کنید" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8849,12 +8857,12 @@ msgstr "" "REA این تماس گیرنده را در اولین نتیجه شناسایی کرد. مقیاس دستورالعمل های قبلی" " آن {ph0} با 30 ؛ اضافه کردن 20 مختصات صفحه نمایش آجر را می دهد, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "مقادیر پشت آدرس های حافظه را بخوانید" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -8863,12 +8871,12 @@ msgstr "" "بایت های بازگردانده شده دو ثابت ریاضی و مقیاس اولیه پان را ایجاد می کنند. " "عامل اکنون مقادیر مورد نیاز برای عبارت C را دارد." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "از یافته های REA به C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8879,7 +8887,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8887,7 +8895,7 @@ msgstr "{ph0}01{ph1} ورودی" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8895,7 +8903,7 @@ msgstr "{ph0}02{ph1} ضرب" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8903,7 +8911,7 @@ msgstr "{ph0}03{ph1} کسر" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8911,18 +8919,18 @@ msgstr "{ph0}04{ph1} مقیاس" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} بازگشت" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "نسخه اصلی x86 ·" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "بازسازی شده C" @@ -8932,7 +8940,7 @@ msgstr "بازسازی شده C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8952,7 +8960,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8969,7 +8977,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8986,7 +8994,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9003,7 +9011,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9015,7 +9023,7 @@ msgstr "" "در نتایج callee REA شناسایی شده است. C نتیجه را به {ph4}; مقایسه های " "اصلی-x86 مقدار برگشت داده شده را بررسی کنید." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9026,23 +9034,23 @@ msgstr "" "کامل زیر همچنین شامل فروشگاه های مداخله کننده و تنظیم و تمیز کردن عملکرد " "است." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "تجمع کامل و شواهد حمایتی" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "نتیجه REA · 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "آنچه تماس گیرنده ارائه می دهد" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9052,54 +9060,54 @@ msgstr "" "عملکرد ضربه آجر در {ph0} مختصات کاشی خود را با 30 مقیاس می دهد ، 20 را اضافه" " می کند ، سپس قبل از تماس آن را فشار می دهد:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "آنچه داده ها می خوانند تعیین می کنند" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA بایت می خواند ، رمزگشایی به عنوان دو برابر کمی-اندیان" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "آدرس" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "ارزش" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "مورد استفاده برای" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "ضرب اول" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "تفریق" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} در ابتدا" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "مقیاس پان ذخیره شده" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9115,7 +9123,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9123,12 +9131,12 @@ msgid "" "references{ph3}" msgstr "{ph0}منبع نگهداری شده{ph1} · {ph2}یادداشت های تحقیق و مرجع شواهد{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "بررسی عملکرد بازیابی شده" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9137,12 +9145,12 @@ msgstr "" "تابع بازیابی شده دو چک را می گذراند: مقادیر بازگشت آن با اصل مطابقت دارد و " "بایت های کامپایل شده آن با فایل اجرایی مطابقت دارند." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3205 مورد رفتار" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9153,12 +9161,12 @@ msgstr "" "مقایسه می کنند.آنها هر موقعیت عدد صحیح را از 0 تا 640 در پنج مقیاس پان پوشش " "می دهند: 0 ، 0.5 ، 1 ، 20 و -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 باایت تطبیق" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9169,7 +9177,7 @@ msgstr "" "عملکرد کامل پس از اعمال جابجایی های بررسی شده و بررسی ثابت های مرجع مطابقت " "دارد." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9184,18 +9192,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}جزئیات پخش کامپایلر را بخوانید{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "ادامه تحقیقات" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9206,7 +9214,7 @@ msgstr "" "شود: عملکردهای مربوطه را بررسی کنید ، وضعیت و وابستگی های آنها را بازیابی " "کنید ، سپس پیاده سازی را با اصلی مقایسه کنید." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9215,7 +9223,7 @@ msgstr "" "برای بررسی عملکرد پان صدا خودتان ، دستورالعمل های راه اندازی پروژه DX-Ball " "را دنبال کنید و هدف اصلی تطبیق یافته آن را ارائه دهید. سپس اجرا کنید:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "در پرداخت DX-Ball" @@ -9224,7 +9232,7 @@ msgstr "در پرداخت DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9237,7 +9245,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9253,7 +9261,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9277,14 +9285,14 @@ msgstr "" "بازسازی DX-Ball را از تجزیه و تحلیل باینری از طریق REA به تست های c ، " "original-x86 و تطبیق بایت های تابع کامپایل شده دنبال کنید." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "" "DX-Ball تحقیق صدا-پان; به صورت افقی روی صفحه نمایش های کوچکتر حرکت کنید" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9300,70 +9308,70 @@ msgstr "" "3205 مورد و توسط vc4.0 compiler replay که با 63 بایت مطابقت دارد ، بررسی می " "شود." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "مطالعه موردی بازسازی DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "کپی مثال prompt" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "محاسبه موقعیت صدا چپ / راست را دنبال کنید" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "کپی گزیده اصلی مونتاژ" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "کپی تابع صدا-پان" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "کپی کامل مونتاژ پان صدا" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "دستور تجزیه و تحلیل DX-Ball را کپی کنید" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "پرش به محتوا" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}خانه{ph1} / ویترین ها" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "مطالعات موردی REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9371,17 +9379,17 @@ msgid "" msgstr "" "اندروید ، بازی ، Electron و یک چالش CTF ، با کد ، ارقام و نتایج بررسی شده." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * تجزیه و تحلیل APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "چگونه یک احراز هویت یک کد ورود را تولید می کند" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9392,22 +9400,22 @@ msgstr "" " با REA ردیابی کنید ، سپس یک ساعت نمایشی را حرکت دهید تا ببینید چرا کد هر 30" " ثانیه تغییر می کند." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "مطالعه موردی اندروید را بخوانید" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "Ctf * تجزیه و تحلیل برنامه های کد ماشین" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "یک چک کننده پرچم CTF را حل کنید" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9418,22 +9426,22 @@ msgstr "" "ماسک ها و جمع ها را به معادلات تبدیل کنید ، سپس پرچم حل شده را با برنامه " "اصلی تأیید کنید." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "مطالعه موردی CTF را بخوانید" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "بومی * بازسازی" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "محاسبه DX-Ball از سمت چپ / راست موقعیت صدا" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9444,22 +9452,22 @@ msgstr "" "REA ، مرجع های تماس گیرنده و ثابت های عددی منجر به یک تابع C کوچک می شود که " "با رفتار اصلی و تمام 63 بایت کامپایل شده بررسی می شود." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "مطالعه موردی DX-Ball را بخوانید" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * ردیابی ویژگی" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "چگونه Notion متن و HTML را کپی می کند" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9470,22 +9478,22 @@ msgstr "" "IPC آن را به کلیپ بورد سیستم دنبال کنید ، سپس ببینید که چگونه یک نشانگر HTML" " کوچک داده های بلوک غنی را به یک کپی متصل می کند." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "مطالعه موردی Notion را بخوانید" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * بازسازی" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "چگونه TH04 یک حلقه گلوله را هدف قرار می دهد" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9496,17 +9504,17 @@ msgstr "" " آن را با c++ قابل خواندن مطابقت دهید ، سپس ببینید که چگونه آنها یک حلقه را " "برای بازیکن تولید می کنند." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "مطالعه موردی TH04 را بخوانید" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "راهنماهای گام به گام" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9515,7 +9523,7 @@ msgstr "" "راهنماها از طریق یک محاسبه بومی ، یک صادرات Electron و یک درخواست مرورگر قدم" " می زنند. هر کدام با یک هدف و یک هدف مشخص شروع می شود." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "راهنماها را بخوانید" @@ -9534,12 +9542,12 @@ msgstr "" "تحقیقات REA را از طریق کد ، ارقام و نمایشی دنبال کنید: یک احراز هویت Android" " ، DX-Ball ، Notion ، TH04 و یک چک کننده پرچم DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -9548,25 +9556,25 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}خانه{ph1} / {ph2}ویترین ها{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "مطالعه موردی * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "چگونه Notion کپی{ph0}متن و HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9575,12 +9583,12 @@ msgstr "" "یک تماس کلیپ بورد از API صفحه Notion را از طریق فرآیند پیش بارگذاری و اصلی " "به نویسنده کلیپ بورد Electron ردیابی کنید." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion دسکتاپ 7.6.1 * JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "پل داخل بسته دسکتاپ Notion" @@ -9592,7 +9600,7 @@ msgstr "پل داخل بسته دسکتاپ Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9609,7 +9617,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9626,7 +9634,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9643,7 +9651,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9654,13 +9662,13 @@ msgstr "" "ارائه شده را می نویسد.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "یک کانال به دو طرف می پیوندد: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9669,14 +9677,14 @@ msgstr "" "کد بسته بندی شده از همان کانال در فرآیند پیش بارگذاری و اصلی استفاده می کند." " حل کردن بسته بندی ها نشان می دهد که Electron پشت این نام ها صدا می زند." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "در این مطالعه موردی" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9684,7 +9692,7 @@ msgstr "{ph0}پل کلیپ بورد را دنبال کنید{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9692,19 +9700,19 @@ msgstr "{ph0}حفظ ساختار یک بلوک{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}نمونه ها و منابع بیشتر{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "عملیات کپی به کجا می رود ؟" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9724,17 +9732,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "کپی" @@ -9745,7 +9753,7 @@ msgstr "کپی" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9755,19 +9763,19 @@ msgstr "" "{ph0}›{ph1}{ph2}از REA برای ردیابی نحوه کپی متن و HTML Notion در کلیپ بورد " "سیستم استفاده کنید. کد را در هر مرحله نشان دهید.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " "coding agent." msgstr "یک مثال با بسته برنامه محلی Notion در دسترس برنامه نویس شما." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA می یابد که از کجا شروع به خواندن" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9778,13 +9786,13 @@ msgstr "" "درخواست IPC را ارسال می کند قرار می دهد. هر دو یافته با محدوده منبع در بسته " "کوچک شده همراه است:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "یافته های REA → دو مکان برای باز کردن" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9797,7 +9805,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9811,12 +9819,12 @@ msgstr "" " دقيقي ميده که بايد در بسته اصلي دنبالش بگرده چهار بخش زیر مسیر اتصال آن را " "نشان می دهد." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "چهار قطعه کد کوتاه" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9825,13 +9833,13 @@ msgstr "" "ساده شده از JavaScript بسته بندی شده ، با نام متغیر قابل خواندن. اعضای غیر " "مرتبط حذف می شوند." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "از API در معرض صفحه شروع کنید" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9841,13 +9849,13 @@ msgstr "" "این عضو نام کانال را ارائه می دهد. اجرای {ph0} به ما می گوید که چگونه " "درخواست از روند صفحه خارج می شود." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "بسته بندی پیش بارگذاری را حل کنید" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9857,14 +9865,14 @@ msgstr "" "تابع بازگردانده شده آرگومنت ها را از طریق IPC درخواست و پاسخ Electron ارسال " "می کند. حالا می تونیم دنبالش بگردیم {ph0} در سمت اصلی فرآیند." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "نحوه ثبت نام گیرنده را بررسی کنید" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9874,12 +9882,12 @@ msgstr "" "فرآیند اصلی از یک بسته بندی دیگر استفاده می کند. اون {ph0} روش ثبت یک {ph1} " "گیرنده برای اون کانال" -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "نوشتن و چک فرستنده آن را پیدا کنید" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9890,13 +9898,13 @@ msgstr "" " کلیپ بورد Electron منتقل می کند. کانال و دو بسته بندی حل شده روش در معرض را" " به این تماس متصل می کنند." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "بلوک کپی شده چگونه ساختار خود را حفظ می کند ؟" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9906,27 +9914,27 @@ msgstr "" "ویرایشگر وب Notion متن و HTML را از طریق {ph0}. این داده های بلوک را به صورت" " محلی نگه می دارد و یک ID را در HTML کپی شده برای اتصال آنها قرار می دهد." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "لینک های HTML برای ذخیره داده های بلوک" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "شناسه HTML را بخوانید" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "همان شناسه محلی را پیدا کنید" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "بازیابی داده های بلوک Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -9935,7 +9943,7 @@ msgstr "" "متن تصویری و شناسنامه. تست ماژول ضبط شده داده های بلوک را هنگام مطابقت IDs " "بازیابی می کند ؛ یک ورودی قدیمی فقط متن و HTML را باز می گرداند." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -9944,23 +9952,23 @@ msgstr "" "در paste ، Notion به دنبال شناسه HTML است و آن را با نسخه ذخیره شده بررسی می" " کند. تطبیق شناسه بازیابی داده های بلوک." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "فرمت کلیپ بورد ثبت شده از دارایی های وب در 13 ژوئیه 2026 ذخیره شده است." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "نمونه ها و منابع بیشتر" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "مثال دیگر: جداول Markdown" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -9969,12 +9977,12 @@ msgstr "" "Notion تجزیه و تحلیل Markdown به داده های بلوک. این مثال نشان می دهد که " "چگونه یک جدول به عنوان عنوان و ردیف داده تبدیل می شود." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "جدول از طریق تجزیه کننده Markdown Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -9983,13 +9991,13 @@ msgstr "" "خروجی ضبط شده از یک تجزیه کننده Markdown استخراج شده. جدول به ردیف ها و سلول" " ها تبدیل می شود." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "مسیر دیگر: اتصال آفلاین SQLite" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10002,7 +10010,7 @@ msgstr "" "کند و یک پورت به رندر و دیگری به یک فرآیند ابزار SQLite می دهد. دسته های " "بیانیه های بعدی و نتایج از آن بندر عبور می کنند." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10011,7 +10019,7 @@ msgstr "" "پس از این انتقال توضیح می دهد که کار پایگاه داده کجا اجرا می شود و چرا " "ردیابی تنها درخواست اولیه IPC مکالمه بعدی را از دست می دهد." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "منابع و نحوه خواندن گزیده ها" @@ -10019,7 +10027,7 @@ msgstr "منابع و نحوه خواندن گزیده ها" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10037,7 +10045,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10053,7 +10061,7 @@ msgstr "" " را اجرا می کنند ؛ خروجی های آنها این پروب ها را به جای یک جلسه رابط کاربری " "دسکتاپ ضبط شده توصیف می کند." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10067,7 +10075,7 @@ msgstr "" "خواندن پیاده سازی های بسته بندی خود در بسته متصل می شوند." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10085,7 +10093,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10099,7 +10107,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10125,52 +10133,52 @@ msgstr "" "Electron ، با گزیده های کوتاه کد و نگاهی به قالب کلیپ بورد غنی آن دنبال " "کنید." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "مطالعه موردی Notion Electron" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "کپی Notion تجزیه و تحلیل prompt" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "کپی Notion پیش بارگذاری گزیده" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "کپی Notion فراخوان گزیده بسته بندی" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "کپی Notion handler wrapper گزیده" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "کپی Notion کلیپ بورد گیرنده گزیده" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "بازیابی اطلاعات غنی کلیپ بورد در paste" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "بازگشت به بالا" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "پرش به محتوا" @@ -10179,25 +10187,25 @@ msgstr "پرش به محتوا" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}خانه{ph1} / {ph2}ویترین ها{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "مطالعه موردی * Touhou 4: داستان سرزمین لوتوس" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "بازسازی TH04{ph0}الگوهای گلوله." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10207,17 +10215,17 @@ msgstr "" "dos اصلی استفاده کنید ، سپس دستورالعمل های آن را به C read قابل خواندن دنبال" " کنید." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 · 16 بیتی DOS · c++ و مونتاژ" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "بازسازی TH04 را مشاهده کنید" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "از دستورالعمل های اصلی تا منبع چک شده" @@ -10228,7 +10236,7 @@ msgstr "از دستورالعمل های اصلی تا منبع چک شده" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10244,7 +10252,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10261,7 +10269,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10277,7 +10285,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10289,7 +10297,7 @@ msgstr "" "کامپایلر ضبط شده کد تولید گلوله ای را که شامل این کمک کننده است ، پوشش می " "دهد.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10298,14 +10306,14 @@ msgstr "" "REA کد اصلی و شواهد تجزیه و تحلیل آن را باز می گرداند. پروژه TH04 منبع " "نگهداری شده و چک های کامپایلر را تامین می کند." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "در این مطالعه موردی" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10313,7 +10321,7 @@ msgstr "{ph0}حلقه گلوله{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10321,7 +10329,7 @@ msgstr "{ph0}چه REA باز می گردد{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10329,7 +10337,7 @@ msgstr "{ph0}مونتاژ به C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10337,18 +10345,18 @@ msgstr "{ph0}بررسی منبع{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}پروژه کامل{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "چگونه یک حلقه به بازیکن هدف می گیرد" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10367,16 +10375,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}عامل برنامه نویسی شما" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "کپی" @@ -10387,7 +10395,7 @@ msgstr "کپی" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10398,7 +10406,7 @@ msgstr "" "گلوله و هدف آن را در بازیکن. محاسبه را توضیح دهید و کد را نشان " "دهید.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10406,7 +10414,7 @@ msgid "" msgstr "یک مثال سریع ، با فایل اجرایی اصلی و پرداخت بازسازی در دسترس محلی." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10420,7 +10428,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10430,12 +10438,12 @@ msgstr "" "یک تصویر از ریاضیات زاویه بازیابی شده برای شمارش 16 ، جهت بازیکن 40 و چرخش " "قالب 0. {ph0}شکل باز{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "قالب شلیک در منبع بازیابی شده" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "حمله حلقه ای الی * منبع گزیده" @@ -10444,7 +10452,7 @@ msgstr "حمله حلقه ای الی * منبع گزیده" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10454,13 +10462,13 @@ msgstr "" "این خطوط الگوی را قبل از دشواری و تنظیم عملکرد انتخاب می کنند. {ph0}منبع " "حمله رو بخون{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "چه REA باز می گردد" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10472,12 +10480,12 @@ msgstr "" "REA دستورالعمل ها ، کد شبه و مرجع خود را باز می گرداند. سه قسمت از این نتیجه" " الگوی را توضیح می دهد." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "قبل از خواندن کد آن ، تصویر DOS را بررسی کنید" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10486,7 +10494,7 @@ msgstr "" "چک کد بارگذاری شده و سوابق جابجایی را به فایل اجرایی ارائه شده متصل می کند. " "مسیر بالا برای نمایش کوتاه شده است." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "ضرب و تقسیم حلقه را بخوانید" @@ -10494,7 +10502,7 @@ msgstr "ضرب و تقسیم حلقه را بخوانید" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10506,12 +10514,12 @@ msgstr "" "از شمارش خوانده شده از {ph1}. نام های منبع نگهداری شده که فیلد {ph2}. دنباله" " کامل در زیر ظاهر می شود." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "پیدا کردن جایی که الگوی به سمت بازیکن می چرخد" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10524,12 +10532,12 @@ msgstr "" " قابل خواندن می کنند ؛ REA به نماینده اجازه می دهد عملیات اصلی پشت آنها را " "بررسی کند." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "از مونتاژ به c قابل خواندن++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10542,7 +10550,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10550,7 +10558,7 @@ msgstr "{ph0}01{ph1} شاخص" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10558,7 +10566,7 @@ msgstr "{ph0}02{ph1} فضا" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10566,7 +10574,7 @@ msgstr "{ph0}03{ph1} هدف" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10574,18 +10582,18 @@ msgstr "{ph0}04{ph1} چرخش" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} فروشگاه" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * دستورالعمل های اصلی 16 بیتی" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "قابل خواندن c summary * هدف-خلاصه حلقه" @@ -10593,7 +10601,7 @@ msgstr "قابل خواندن c summary * هدف-خلاصه حلقه" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10607,7 +10615,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10622,7 +10630,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10637,7 +10645,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10652,7 +10660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10665,7 +10673,7 @@ msgstr "" "به میدان زاویه تخم ریزی ارزش ها بعد از 255 بسته بندی می شوند ، درست مثل " "بازیگران بدون بایت. منبع اطراف نیز این زاویه و سرعت را به سرعت تبدیل می کند." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10676,7 +10684,7 @@ msgstr "" "یک خلاصه قابل خواندن است. چک های کامپایلر زیر برای منبع نگهداری شده در پروژه" " مرتبط اعمال می شود." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "حلقه نگهداری شده و منبع هدف را بخوانید" @@ -10693,7 +10701,7 @@ msgstr "حلقه نگهداری شده و منبع هدف را بخوانید" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10702,12 +10710,12 @@ msgid "" msgstr "" "{ph0}ماکرو حلقه{ph1} · {ph2}منبع هدف و سرعت{ph3} · {ph4}نمایش زاویه{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "بررسی منبع نگهداری شده" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10716,12 +10724,12 @@ msgstr "" "چک های ضبط شده پروژه TH04 کد تولید گلوله ، از جمله این کمک کننده را با " "زنجیره ابزار توربو C 4 4.0 J خود جمع آوری می کند." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 بایت تطبیق" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10729,12 +10737,12 @@ msgid "" msgstr "" "کد تولید گلوله کامپایل شده با بخش 2139 بایت از فایل اجرایی اصلی مطابقت دارد." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "دو ساخت تمیز" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10747,65 +10755,65 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "ثبت شده در 3 اکتبر 2026. {ph0}چک های کامپایلر را بخوانید{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "محدوده هویت و تجزیه و تحلیل هدف" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "هدف اصلی" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156,258 بایت, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "ورود کمک کننده" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} در REA ' s تصویر لود" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "فایل اصلی جبران" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}، بازگشت توسط {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "بازرسی کد ثبت شده" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 اکتبر 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10815,7 +10823,7 @@ msgstr "" "کننده. آنها همچنین سهم نقشه و جابجایی همپوشانی آن را مقایسه می کنند." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10830,7 +10838,7 @@ msgstr "" "های گزارش شده قرار دارند." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10845,7 +10853,7 @@ msgstr "" "یک بازرسی REA تازه از همان هدف اصلی را اضافه می کند. هویت بازی عرضه شده توسط" " فهرست مخزن آن قرار گرفته است ، با منبع مستقل پاک و پاک هنوز باز است." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10855,12 +10863,12 @@ msgstr "" "شکل محاسبه زاویه را نشان می دهد. کنترل های کامل بازی ، زمان بندی و رفتار سخت" " افزاری PC-98 دارای بررسی های زمان اجرا جداگانه در پروژه بازسازی هستند." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "بازسازی کامل TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10873,7 +10881,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10885,7 +10893,7 @@ msgstr "{ph0}مخزن TH04 را کاوش کنید{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10900,7 +10908,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10916,7 +10924,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10941,22 +10949,22 @@ msgstr "" "را بازیابی کنید تا ببینید که چگونه یک حلقه گلوله فاصله دارد و به بازیکن هدف " "قرار می گیرد." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "در این صفحه" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 گلوله-الگوی مطالعه موردی" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "کپی TH04 مثال prompt" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -10964,7 +10972,7 @@ msgstr "" "TH04 حلقه های گلوله ثابت و هدفمند ؛ به صورت افقی روی صفحه نمایش های کوچکتر " "حرکت کنید" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10976,27 +10984,27 @@ msgstr "" " یک جهت بازیکن 40 هر جهت را با همان مقدار چرخش می دهد ؛ اولین گلوله برجسته " "به سمت بازیکن اشاره می کند. هر دو فاصله 16 واحد زاویه ای یا 22.5 درجه دارند." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "کپی TH04 قالب شلیک" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "محاسبه حلقه هدف TH04 را دنبال کنید" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "کپی TH04 assembly گزیده" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "کپی قابل خواندن هدف-محاسبه حلقه" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "بازگشت به بالا" @@ -11106,7 +11114,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "سرعت ثابت: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11115,7 +11123,7 @@ msgstr "" "قانون بازیابی شده را تکرار کرد. هر چهار مقدار با چک بازی اصلی کنترل شده " "مطابقت دارند وقتی به سه اعشاری گرد می شوند." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11478,591 +11486,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "فاصله یکسان: 256 × 16 = 16 واحد زاویه = 22.5 درجه" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "نمونه‌ها" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "وبلاگ" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "شروع کنید" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "راهنماها" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "کد منبع" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "مجوز MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "به جامعه بپیوندید" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "ما را در X دنبال کنید" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * منبع اسکریپت انتخاب شده" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "کد منبع" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "خروجی قالب مورد انتظار" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "دستورالعمل ها" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "تماس گیرنده" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "ثابت ها" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "تابع C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "دکمه" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API پیش بارگذاری" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "فایل CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "کلیک شما" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "درخواست ضبط شده" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "اسکریپت صادرات" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA نتیجه * خلاصه.گزیده ای از ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA گزیده دستورالعمل * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA گزیده تماس گیرنده * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "نتایج بایت REA * به عنوان دو برابر اندک تفسیر می شود" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "بازیابی C * گزیده" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "ببینید REA چطور کار می‌کند ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "ویترین ها →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "تنظیمات انتخاب شده از اسکریپت بازرسی شده" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "خلاصه قابل خواندن از % handler" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * دستورالعمل های اصلی انتخاب شده" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "شناسه های اپراتور * منبع مایکروسافت" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "@Reatools را در X دنبال کنید" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "نماینده → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → عامل * نتایج انتخاب شده" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → عامل * روش ها و تماس گیرندگان" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * جاوا تجزیه شده انتخاب شده" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "خلاصه قابل خواندن * تفسیر نماینده" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP ، بدن کامل" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "دانلود Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "دانلود analysis provider اندروید" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "نماینده → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → عامل * نتایج انتخاب شده" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → عامل * دستورالعمل های انتخاب شده" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "نماینده → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → عامل * ورودی های هفتم" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "اجرایی اصلی * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "دانلود چالش اصلی" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "دانلود حل کننده" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "نتیجه REA * گزیده شبه کد" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "نماینده → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → عامل * گزیده دستورالعمل" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → نماینده * گزیده تماس گیرنده" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "عامل → REA * دو {ph0} درخواست ها" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "نتایج بایت REA · رمزگشایی به عنوان دو برابر" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "با هدف خود شروع کنید" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "تولید کد" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "قانون بازیابی شده" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "ساعت قابل تنظیم" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "باینری" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "چک کردن کد" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "معادلات" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "درست است!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "قابل اجرا" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "یافته های REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "بازیابی C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "اعتبار سنجی" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "برنامه بسته بندی شده" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Api در معرض" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "بسته بندی IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "کلیپ بورد" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "کد اصلی DOS" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA دستورالعمل" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "محاسبه زاویه" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "حلقه گلوله" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Api صفحه در معرض" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "رندر IPC تماس" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "ارسال به کلیپ بورد سیستم" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "ذخیره شده به صورت محلی توسط Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "ورودی Markdown" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "خروجی تجزیه کننده ساختاری · گزیده" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "برنامه خود را تجزیه و تحلیل کنید" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "نماینده → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → عامل * زمینه های انتخاب شده" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "نماینده → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → عامل * گزیده دستورالعمل" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "نتیجه عملکرد مشابه * گزیده aim" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "C نگهداری شده مربوطه++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "حلقه ماکرو * TH04 شاخه ، گزیده" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "زاویه و سرعت * منبع گزیده" @@ -12095,7 +12111,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12113,7 +12129,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12134,7 +12150,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12155,7 +12171,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12174,7 +12190,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12193,7 +12209,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12204,14 +12220,14 @@ msgstr "" "من کلان کنید.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "بازسازی · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12222,7 +12238,7 @@ msgstr "" "انتخاب کنید و تغییرات پیشنهادی را بررسی کنید." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12231,7 +12247,7 @@ msgstr "یک مثال ارائه شده · {ph0} و npm * عامل کدگذار #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12249,7 +12265,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12264,7 +12280,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12283,7 +12299,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12294,7 +12310,7 @@ msgstr "" " {ph7} و فایل را می نویسد.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12309,7 +12325,7 @@ msgstr "{ph0} * خطوط 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12322,7 +12338,7 @@ msgstr "" "نشان دهید.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12333,7 +12349,7 @@ msgstr "" "شود. این قالب را مستقیما با {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12341,7 +12357,7 @@ msgstr "{ph0} · CSV قالب ساز" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12350,7 +12366,7 @@ msgstr "" "شما نیاز دارید {ph0} 22 (22.19+), 24 (24.11+) یا 26+ npm همراه با {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12358,7 +12374,7 @@ msgstr "ندارم {ph0}، یا مطمئن نیستید ؟ " #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12371,7 +12387,7 @@ msgstr "" "لیتر:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12385,7 +12401,7 @@ msgstr "{ph0} * نمونه منبع گزیده" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12396,9 +12412,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12406,7 +12422,7 @@ msgstr "{ph0} * منبع نمونه" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12420,7 +12436,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12433,7 +12449,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12446,7 +12462,7 @@ msgstr "مثلاً: {ph0}چرا ماشین‌حساب برای {ph1} عدد 220 #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12457,7 +12473,7 @@ msgstr "" "220 می دهند؟{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12466,7 +12482,7 @@ msgstr "REA * بارگذاری شده {ph0} * خطوط انتخاب شده" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12484,7 +12500,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12503,7 +12519,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12516,28 +12532,28 @@ msgstr "" "بتوانم زمان را در آن تغییر دهم.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * عضو API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * کمک کننده IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "اصلی/{ph0} * handler helper" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12547,12 +12563,1365 @@ msgstr "اصلی/{ph0} * گیرنده کلیپ بورد" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "شروع کنید {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "تغییر به حالت روشن" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "تغییر به حالت تیره" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"برای بررسی بدنهٔ درخواست‌ها و پاسخ‌های HTTP، از {ph0}Fiddler Everywhere: " +"ضبط‌های SAZ، سرور MCP و مهارت‌های عمومی{ph1} استفاده کنید. برای Evidence ضبط" +" در REA به‌صورت آفلاین، خروجی SAZ ?? HAR 1.2 بگیرید، یا سرور MCP نرم‌افزار " +"Everywhere را متصل کنید تا ترافیک ضبط‌شده را با عامل خود بررسی کنید." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "مدل‌های تخصصی{ph0}یادداشت" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "آیا مهندسی معکوس به مدل بزرگ‌تری نیاز دارد؟" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"تأملاتی بر پایهٔ بازسازی Touhou دربارهٔ مدل‌های عمومی، مدل‌های تخصصی و " +"یادگیری از بازخورد کامپایلر." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "توسط N0zoM1z0 · 13 اکتبر 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "پرش به محتوا" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}صفحه اصلی{ph1} / {ph2}وبلاگ{ph3} / مدل‌ها و مهندسی معکوس" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "انشا" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "آیا مهندسی معکوس به مدل بزرگتری نیاز دارد؟" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "توسط N0zoM1z0 · 13 اکتبر 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "نکات اصلی" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}قابلیت مدل بر فرضیه‌هایی که یک عامل هوش مصنوعی می‌تواند ارائه دهد تأثیر" +" می‌گذارد.{ph1} جلسات بعدی مشکلاتی را که کار قبلی حل نشده رها کرده بود حل " +"کرد." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}یک کامپایلر آشنا الگوهای مشخصی را برای یادگیری یک مدل تخصصی ارائه " +"می‌کند.{ph1} برخی از تطابق دقیق کد ماشین به الگوهای کد منبع خاص و قابل " +"استفاده مجدد بستگی دارد." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}دانش مخزن را در یک مقایسه منصفانه لحاظ کنید.{ph1} یک مدل کوچکتر با " +"بازیابی دانش خوب ممکن است اطلاعات کافی برای پیشرفت داشته باشد." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}مدل را آموزش دهید تا آزمایش مفید بعدی را انتخاب کند و بررسی‌کننده تأیید" +" آن را آزمایش کنید.{ph1} بازخورد فقط در حدی مفید است که بررسی‌کننده موارد " +"درست را تأیید کند." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}نتایج بازسازی تایید شده را در کنار زمان و هزینه ارزیابی کنید.{ph1} این " +"چیزی است که من می‌خواهم برای گردش کار کامل عامل هوش مصنوعی اندازه‌گیری کنم." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "در این مقاله" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}مدل‌های قوی‌تر چه چیزی را تغییر دادند؟{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}چرا تخصص داشته باشید؟{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}این تجربه در کجا باید ذخیره شود؟{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}یادگیری آزمایش مفید بعدی{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}مهندسی معکوس و یادگیری تقویتی{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}هنگامی که بررسی کننده تأیید اشتباه است{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}مقایسه ای که ارزش اجرا دارد{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}این چه نوع عامل هوش مصنوعی را پیشنهاد می کند؟{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "مدل‌های قوی‌تر چه چیزی را تغییر دادند؟" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"از آگوست 2026، من در حال بررسی میزان مهندسی معکوس یک عامل با دسترسی به یک " +"برنامه و راهی برای بررسی کار آن هستم. بیشتر تجربه من از بازسازی بازی ها به " +"خصوص Touhou ناشی می شود. همانطور که من مدل‌ها را تغییر داده‌ام، مخازن رکوردی" +" از آنچه هر جلسه توانسته است بازیابی کند را نگه داشته است." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"هدف بیشتر این کار بازسازی دقیق است: ما منبع نگهداری شده را تحت یک زنجیره " +"ابزار تاریخی با نسخه های ثابت کامپایل می کنیم و بررسی می کنیم که آیا تابع " +"هدف را بازتولید می کند یا خیر. هنگامی که مدل بعدی در جایی که کار قبلی متوقف " +"شده بود موفق می شود، تغییرات منبع نشان می دهد که چه چیزی این پیشرفت را ممکن " +"کرده است." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "متغیرهای موقت به طول عمر همپوشانی نیاز داشتند" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"بیشتر منطق یک تابع حمله TH09 قبلاً بازسازی شده بود، اما کامپایلر همچنان " +"نتایج موقت را متفاوت از نسخه اصلی ذخیره می کرد. مشکل باقی‌مانده این بود که " +"این نتایج چقدر طول می‌کشد تا زنده بمانند و چه زمانی می‌توان از ذخیره‌سازی " +"آنها استفاده مجدد کرد." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"یک {ph0}GPT-6-Sol رکورد جلسه{ph1} این عدم تطابق را پس از آزمایش چندین ترتیب " +"کد منبع معمولی گزارش کرد. وقتی {ph2}GPT-6.1-Sol دوباره مشکل را بررسی " +"کرد{ph3}، یک فرضیه مفید در مورد طول عمر این متغیرهای موقت ارائه کرد." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"این تابع نتایج موقتی تولید کرد و آنها را در موقعیت های انیمیشن کپی کرد. در " +"C++، یک نتیجه موقت زنده می ماند تا زمانی که عبارت استفاده شده از آن تمام " +"شود. گروه‌بندی عملیات واقعی در یک عبارت، آن نتایج را با هم زنده نگه می‌دارد،" +" بنابراین کامپایلر دیگر نمی‌تواند از فضای ذخیره‌سازی یکسان برای همه آنها " +"استفاده مجدد کند." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"یک نتیجه همچنان فضای ذخیره‌سازی را با مقداری به اشتراک گذاشته است که بعداً " +"برای بررسی‌های برخورد استفاده می‌شود. دادن این ارزش به طول عمر خودش، " +"همپوشانی باقیمانده را حل کرد. پس از چندین آزمایش هدفمند، {ph0}کامپایل مجدد " +"تمیز از منبع تأیید کرد که تابع کامل مطابقت دارد{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"من علاقه مندم که چگونه این کشف و آزمایش ها از یکدیگر حمایت کردند. فرضیه در " +"مورد طول عمر اشیاء موقت به عامل هوش مصنوعی مسیر جدیدی داد. بازخورد کامپایلر " +"به آن کمک کرد تا این فرضیه را به ترتیب کد منبع که مطابقت دارد، اصلاح کند." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "یک نمودار کنترل جریان متفاوت" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"تابع دوم TH09 نشان می دهد که چرا آن جهت جدید می تواند مهم باشد. در اینجا، " +"مانع این بود که چگونه چندین شعبه کار نهایی خود را به اشتراک گذاشتند. کار " +"قبلی {ph0}GPT-6.1-Sol{ph1} بخش‌هایی از تابع را مطابقت داد، اما شاخه‌ها " +"همچنان متفاوت از نسخه اصلی به یکدیگر متصل شدند." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra نمودار کنترل جریان اطراف را تغییر داد{ph1}. مسیرهای اصلی " +"اکنون به یک به‌روزرسانی نهایی مشترک و بازگشت منجر می‌شوند. در آن ساختار " +"منبع، کامپایلر شاخه ها را به همان روش اصلی ترکیب می کند. تابع کامل مطابقت " +"داشت و {ph2}بررسی بازسازی جداگانه آن را تأیید کرد{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}تغییر نمایش، فضای جستجوی سازنده‌تری را باز کرد.{ph1} هر دو مورد دلیلی " +"برای جدی گرفتن قابلیت مدل کلی به من می‌دهد: یک نماینده می‌تواند قبل از یافتن" +" راهی بهتر برای بیان کار اطراف، برای مدت طولانی تغییرات محلی را امتحان کند." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"در همان زمان، جلسات بعدی با منبع قبلی شروع شد و خرابی ها ثبت شد. این کار " +"انباشته بخشی از مزیت آنها بود. تاریخ به ما اجازه می دهد تا کشفیات و بررسی " +"های آنها را بررسی کنیم. یک مقایسه کنترل شده به تفکیک اثر مدل از تجربه ای که " +"به ارث برده است کمک می کند." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"این چیزی است که سوال را برای من جالب می کند. برخی پیشرفت ها از یافتن " +"نمایندگی جدید حاصل شد. بسیاری از کارهای باقی مانده شامل آزمایش ترتیبات مختلف" +" کد منبع در برابر یک کامپایلر آشنا بود. چه مقدار از این به توانایی استدلال " +"گسترده نیاز دارد؟ یک مدل با کار مکرر با آن کامپایلر و کد چقدر می تواند یاد " +"بگیرد؟" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "چرا یک مدل تخصصی هوش مصنوعی ممکن است خوب عمل کند؟" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou دلیل مشخصی به ما می دهد که انتظار داشته باشیم آن تجربه کمک کند. بیشتر" +" کد بازی از همان نویسنده، ZUN می آید، بنابراین عادت های تکرار شونده یک فرض " +"شروع منطقی هستند. مخازن با مثال‌های مفید این موضوع را تأیید می‌کنند: " +"حلقه‌های مرتبط و ترتیبات کمکی فرضیه‌هایی را در بین بازی‌ها ارائه کرده‌اند." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"وقتی کامپایلر را وارد کنیم، این الگوهای منبع خاص تر می شوند. تحت یک نسخه خاص" +" و مجموعه ای از گزینه ها، تغییرات کوچک در منبع می تواند تفاوت های قابل تکرار" +" در کد ماشین ایجاد کند. برخی از این تفاوت ها به طرز شگفت آوری مبهم هستند." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"به عنوان مثال، در TH095، {ph0}حتی نام یک متغیر محلی می‌تواند بر جایی که " +"VC7.1 آن را ذخیره کرده است، تأثیر بگذارد{ph1}. انتقال اعلان آن طرح ذخیره " +"سازی را حل نکرد. با این حال، یک تابع پس زمینه قبلی یک الگوی نامگذاری را نشان" +" داده بود که بر انتخاب کامپایلر تأثیر می گذاشت. این فرضیه امیدوارکننده تری " +"را برای {ph2}بازسازی {ph3}{ph4} پیشنهاد کرد." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"استفاده مجدد از آن الگو برای متغیر اندازه فایل، طرح مورد نیاز را بدون افزودن" +" فضای ذخیره سازی ایجاد کرد. سپس تابع کامل مطابقت داشت." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"این یک جزئیات بسیار خاص است که یک مدل هوش مصنوعی همه منظوره ممکن است زمانی " +"که برای اولین بار با مشکل مواجه می شود از آن مطلع نباشد. یک مدل تخصصی برای " +"این کامپایلر می‌تواند موارد بسیاری از این قبیل را ببیند و یاد بگیرد که کدام " +"تغییرات کد منبع ارزش آزمایش را دارند." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"این فرصت به ویژه در مسائل تطبیق نهایی که ما قبلاً رفتار را درک کرده ایم، " +"واضح است. سپس می‌پرسیم این کامپایلر کدام ترتیب کد منبع معمولی را به " +"دستورالعمل‌های مشاهده شده تبدیل می‌کند. تخصص می تواند به مدل کمک کند تا آن " +"اشکال را به طور کارآمدتر پیشنهاد کند، در حالی که هدف هنوز تعیین می کند که " +"کدام فرضیه ها باقی می مانند." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"الگوهای مفید باید زمینه خود را حفظ کنند. TH08 از نسخه Visual C++ قبلی نسبت " +"به TH095 و TH09 استفاده می کند. TH04 از یک کامپایلر متفاوت از دوران DOS " +"استفاده می کند. {ph0}بازسازی کد بازیکن{ph1} آن به فرضیه‌های مختلفی در مورد " +"الگوهای کد منبع و نحوه پیوند کد کامپایل‌شده به یک فایل اجرایی نیاز داشت. " +"داشتن یک نویسنده یک انتظار اولیه را به ما می‌دهد، اما هر هدف به ما می‌گوید " +"که آیا کاربرد دارد یا خیر. یک مدل تخصصی باید این زمینه ها را متمایز کند." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "این تجربه در کجا باید ذخیره شود؟" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"قبل از تصمیم به آموزش آن الگوها از طریق آموزش مدل، به دانشی که قبلاً در مخزن" +" نگهداری می‌کنیم نگاهی می‌اندازم. در {ph0}مقاله قبلی{ph1}، درباره تبدیل شدن " +"آن به حافظه کاری پروژه نوشتم. این حافظه شامل درس های کامپایلر، همراه با منبع" +" و آزمایش های ناموفق است که آنها را مفید ساخته است." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"با بازیابی آن رکورد، یک نماینده می تواند با یک نتیجه شناخته شده شروع کند و " +"نحوه رسیدن ما به آن را بررسی کند. همچنین می تواند از جایگزین هایی که قبلاً " +"در همان زمینه شکست خورده اند اجتناب کند. نقطه شروع بدون تغییر پارامترهای " +"آموزش دیده مدل بهبود می یابد." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"هنگام بازسازی عملکرد TH09 برای ایجاد دشمن، یک جلسه {ph0}GPT-6-Luna-max{ph1} " +"یک فرضیه را از کد منبع TH08 مرتبط گرفت. آن کد قبلی نحوه سازماندهی حلقه و " +"مدیریت خرابی های داخل آن را پیشنهاد می کرد. شواهد خود TH09 جزئیات مربوط به " +"بازی را ارائه کرد. بازسازی از منبع تأیید کرد که عملکرد کامل مطابقت دارد." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"مدل نمی‌دانست که ویژگی کامپایلر\" و \"مدل نمی‌تواند از آن استفاده " +"کند\" مشکلات متفاوتی هستند.{ph1} بازیابی ممکن است مشکل اول را حل کند، اما " +"تبدیل این واقعیت به یک نامزد مفید هنوز کار می‌برد. و اگر کد منبع کاندید شکست" +" بخورد، مدل باید تصمیم بگیرد که نتیجه برای تلاش بعدی چه معنایی دارد. دانستن " +"الگوی مربوطه تنها آغاز آن فرآیند است." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"به همین دلیل، من یک مدل هوش مصنوعی همه منظوره کوچکتر را با بازیابی خوب در هر" +" مقایسه قرار می دهم. ارائه همان کتابخانه تجربی به ما کمک می کند تا تشخیص " +"دهیم که آموزش چه چیزی را اضافه می کند: تولید نامزد بهتر، تصمیم گیری بهتر پس " +"از بازخورد، یا هر دو." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "یادگیری آزمایش مفید بعدی" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"آن تصمیمات پس از بازخورد همان چیزی است که من بیشتر دوست دارم مطالعه کنم. در " +"بازسازی عاملی، مدل توضیحی را پیشنهاد می کند و آن را در برابر برنامه آزمایش " +"می کند. حتی زمانی که کد منبع نامزد ناموفق باشد، نتیجه می تواند احتمالات " +"باقیمانده را محدود کند و آزمایش بعدی مفیدتری را پیشنهاد کند." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"مثال موقت نتایج را دوباره در نظر بگیرید. منبع نهایی آن ترتیبی را نشان می دهد" +" که کارآمد است، اما مسیر رسیدن به آن منبع حاوی اطلاعات بیشتری است. هر یک از " +"آزمایش‌های زیر به شناسایی آنچه که هنوز باید تغییر کند کمک کرد." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "آزمایش کنید" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "آنچه نتیجه آن به ما آموخت" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "روش دیگری را برای کپی کردن نتایج امتحان کنید" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "کد کپی تغییر می کند، اما عملکرد همچنان متفاوت است." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "از مقادیر برگشتی مستقیما استفاده کنید" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"کپی کردن از الگوی اصلی پیروی می کند، اما ذخیره سازی موقت همچنان متفاوت است." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "همه متغیرهای موقت را همزمان معتبر نگه دارید" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"آنها فضای ذخیره جداگانه ای دریافت می کنند، اما هنوز هم مقداری که بعداً برای " +"بررسی برخورد استفاده می شود، همپوشانی دارد." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "مقدار collision-check را جدا نگه دارید" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "یک کامپایل مجدد تمیز از منبع، مطابقت کامل را تأیید می کند." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"آزمایش‌های منتخب از بازسازی عملکرد حمله در بالا، گروه‌بندی شده بر اساس آنچه " +"به ما آموختند." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"یک رکورد آموزشی که این توالی را حفظ می کند می تواند بیشتر از منبع نهایی به " +"تنهایی آموزش دهد. هر تغییر پیشنهادی را به یک نتیجه مشاهده شده و تصمیم بعدی " +"مرتبط می کند. حفظ تغییرات بی اثر نیز مهم است: آنها به عامل بعدی می گویند که " +"کدام فرضیه قبلاً در آن زمینه آزمایش شده است." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}من می‌خواهم مدل یاد بگیرد که چگونه از بازخورد استفاده کند.{ph1} یک " +"نتیجه خنثی دلیلی برای تجدید نظر در تغییر است. تغییر عدم تطابق ممکن است به " +"دلیل دیگری اشاره کند. وقتی ویرایش‌های محلی آموزنده نیستند، عامل باید بتواند " +"بازنمایی منبع را بازبینی کند یا شواهد را دوباره بررسی کند." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"یادگیری انجام آن انتخاب ها مستلزم استقلال است. گاهی اوقات گام بعدی مفید، " +"بررسی تماس گیرنده دیگر به جای کامپایل ویرایش دیگری است. یک توالی سفت و سخت " +"از بازنویسی های مورد نیاز این انتخاب را حذف می کند، همراه با بخشی از رفتاری " +"که می خواهیم مدل یاد بگیرد." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "چرا مهندسی معکوس برای یادگیری تقویتی جالب است" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"بازسازی با دامنه مشخص محیطی عملی برای مطالعه این تصمیم‌ها فراهم می‌کند. با " +"ثابت نگه داشتن نسخه هدف و کامپایلر، بسیاری از آزمایش‌های کد منبع بازخورد " +"سریع و تکرارپذیر می‌دهند. عامل می‌تواند کد پیشنهادی را کامپایل کند، تفاوت‌ها" +" را بررسی کند و گام بعدی را انتخاب کند." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"یادگیری تقویتی می تواند این فرآیند تصمیم گیری را از طریق بازخوردی که دریافت " +"می کند آموزش دهد. یک نامزد پذیرفته شده توسط یک چک تعریف شده یک نتیجه مشخص به" +" ما می دهد، در حالی که توالی تلاش ها به ما امکان می دهد مشاهده کنیم که چقدر " +"کار برای رسیدن به آن لازم است." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"در حال حاضر تحقیقاتی وجود دارد که از این جهت حمایت می کند. " +"{ph0}LLM4Decompile{ph1} مدل های تخصصی برای دیکامپایل را مطالعه می کند. " +"{ph2}AutoDecompiler{ph3} با استفاده از بازخورد کامپایلر و اجرا، اصلاح چند " +"نوبتی را آموزش می‌دهد. مطالعات آنها بر بازیابی عملکردی متمرکز است. برای این " +"کار، من از آنها به عنوان نقطه شروع برای کار مرتبط یافتن منبعی که با خروجی یک" +" کامپایلر تاریخی مطابقت دارد استفاده می کنم." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"با این حال، برای رسیدن به چنین وظیفه ای به خوبی تعریف شده، ممکن است ابتدا " +"نیاز داشته باشیم که یک تابع دارای چه منابعی است یا یک روش جدید برای مشاهده " +"رفتار برنامه هنگام اجرا را طراحی کنیم. به عنوان مثال، در TH08، یک {ph0}تفاوت" +" برخورد منجر به نحوه مدیریت برنامه اصلی با محاسبات ممیز شناور شد{ph1}. قبل " +"از اینکه عامل بتواند یک تصحیح مفید را آزمایش کند، باید تعیین می کرد که چه " +"چیزی را باید اندازه گیری کند." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"این یک نقش دیگر را برای یک مدل به طور گسترده نشان می دهد: کمک به قابل بررسی " +"کردن مشکل در وهله اول. هنگامی که آن چک وجود داشت، می‌توانیم بررسی کنیم که یک" +" خط‌مشی جستجوی آموخته شده تا چه حد می‌تواند با آن برسد." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "هنگامی که بررسی کننده تأیید اشتباه است" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"وقتی یک بررسی را برای آموزش به کار می‌بریم، دامنه آن هم بخشی از محیط یادگیری" +" می‌شود. من چنین مرجع یا ابزار بررسی را اوراکل می‌نامم. حتی پاسخ تکرارپذیر " +"را باید در محدوده چیزی فهمید که واقعاً بررسی می‌کند." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 نشان داد که مشکلات می‌توانند بیرون از دامنه بررسی پنهان بمانند. بعضی " +"توابع بازسازی‌شده با وجود ثابت‌های ممیز شناور اشتباه، مقایسه دقیق را قبول " +"شدند. مقایسه‌کننده پیش از بررسی دستورها آدرس‌های جابه‌جا‌شده را تنظیم " +"می‌کرد، اما مقدار اشاره‌شده را فقط وقتی بررسی می‌کرد که برای اعتبارسنجی " +"صریحاً ثبت شده بود. ارجاع‌های دیگر به ثابت‌ها می‌توانستند بدون بررسی مقدار " +"قبول شوند." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"برای رفع این شکاف، یک {ph0}ممیزی گسترده‌تر{ph1} ثابت‌های نادرستی را در " +"توابعی که قبلاً تأیید شده بودند پیدا کرد. در یک محاسبه، کد منبع بازسازی شده " +"{ph2} را اضافه کرد، در حالی که کد اصلی {ph3} را اضافه کرد." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}مدلی که توسط چک راستی‌آزمایی قدیمی پاداش می‌گیرد، می‌تواند یاد بگیرد که" +" یک بازسازی نادرست ایجاد کند.{ph1} ما یک مدل RL را با استفاده از آن " +"بررسی‌کننده آموزش ندادیم. نقصی که مشاهده کردیم در خود چک بود. اما اگر از آن " +"به عنوان پاداش استفاده می کردیم، همان نقطه کور بخشی از محیط آموزشی می شد." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"یک تست عملکردی می تواند نقطه کور مشابهی داشته باشد. {ph0}تحقیق با استفاده از" +" fuzzing دیفرانسیل در دیکامپایلرهای LLM{ph1} تفاوت‌های رفتاری را خارج از " +"آزمون‌های ارائه شده یافت. بنابراین ما باید یک آزمون قبولی را بر حسب مواردی " +"که انجام می دهد درک کنیم. به طور مشابه، یک تطابق دستورالعمل باید از نظر بایت" +" ها و داده هایی که تأیید می کند درک شود." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"قبل از استفاده از هر نوع بررسی تأیید به عنوان پاداش، آن را با نتایج عمداً " +"نادرست آزمایش می‌کنم. من همچنین پذیرش نهایی را از کد منبعی که عامل هوش " +"مصنوعی می تواند ویرایش کند جدا نگه می دارم. مدل باید با بازسازی صحیح برنامه،" +" تأیید صحت داشته باشد. در غیر این صورت، کپی کردن یک آرایه بایتی از هدف می " +"تواند یک سیستم امتیازدهی ساده لوح را بدون بازیابی کد منبع مفید فریب دهد." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}بهبود یادگیرنده و بهبود بررسی‌کننده تأیید آن مربوط به یک مسئله تحقیقاتی" +" است.{ph1} همانطور که یادگیرنده در بهینه‌سازی بازخوردی که ما به آن می‌دهیم " +"بهتر می‌شود، درک آن بازخورد نیز مهم‌تر می‌شود." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "مقایسه ای که ارزش اجرا دارد" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"با انجام این بررسی‌ها، مقایسه را روی یک خانواده کار ثابت VC7.1 شروع می‌کنم. " +"اول، من خطوط پایه را برای یک مدل هوش مصنوعی همه منظوره قوی و یک مدل کوچکتر " +"ایجاد می کنم. افزودن دانش مخزن به مدل کوچکتر، تغییرات بازیابی را نشان می " +"دهد. از آنجا، تخصص تحت نظارت و یک نسخه آموزش داده شده RL به ما اجازه می دهد " +"بررسی کنیم که آموزش چه چیزی را اضافه می کند." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"برای اینکه این مقایسه ها آموزنده باشد، هر مدل شواهد و ابزارهای هدف یکسانی را" +" دریافت می کند. برای مقایسه‌های آموزشی خاص، مدل پایه و دانش موجود را نیز " +"ثابت نگه می‌دارم. آزمایش‌های مکرر به تمایز یک استراتژی جستجوی قابل اعتماد از" +" راه‌حل نامزدی که به طور تصادفی موفق می‌شود کمک می‌کند." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"سپس دو شرط شروع را جدا می‌کنم: بازسازی یک تابع از دستورالعمل‌های آن، و بستن " +"چند تفاوت آخر در منبع حفظ شده. یک مدل هوش مصنوعی تخصصی ممکن است در کار دوم " +"عالی باشد در حالی که یک مدل هوش مصنوعی همه منظوره بسیاری از کارهای مورد نیاز" +" برای رسیدن به آن را انجام می دهد. اندازه گیری آنها به طور جداگانه این تقسیم" +" کار را آشکار می کند." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"هر دو کار به نمونه‌های آزمایشی نیاز دارند که از آموزش و بازیابی حذف شوند. کد" +" موتور اشتراک گذاری بازی های مرتبط Touhou. حذف یک بازی از تمرین همچنان می " +"تواند عملکردهای تقریباً یکسانی را در مجموعه تمرینی باقی بگذارد. در عوض، من " +"کل گروه‌های کد منبع مرتبط را حذف می‌کنم و پاسخ‌های تأیید شده‌شان را هم از " +"داده‌های آموزشی و هم از کتابخانه بازیابی خارج می‌کنم." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"برای این مثال‌ها، نتیجه، مطابقت‌های کامل و تأیید شده مستقل خواهد بود. " +"بودجه‌های برابر برای پیشنهادهای نامزد یا تلاش‌های کامپایل به مقایسه کیفیت " +"جستجو کمک می‌کند. اندازه‌گیری زمان و هزینه کل، از جمله کامپایل، نشان می‌دهد " +"که آیا این کیفیت گردش کار کارآمدی ایجاد می‌کند یا خیر. هزینه های آموزشی باید" +" جداگانه اندازه گیری شود." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"هر دو اندازه گیری مهم است. یک پروپوزال ارزان می‌تواند منجر به گردش کار " +"گران‌قیمتی شود اگر باعث کامپایل‌های بیشتری شود که اطلاعات مفیدی ارائه " +"نمی‌کند. برعکس، یک مدل کندتر ممکن است اقتصادی تر باشد اگر آزمایش مفیدی را " +"زودتر پیدا کند. مقایسه باید شامل این هزینه ها باشد." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"شمارش نتایج پذیرفته شده همچنین پیشرفت متوسط را در چشم انداز نگه می دارد. یک " +"TH09 {ph0}replay-save نامزد{ph1} امیدوارکننده به نظر می‌رسید، زیرا تابع " +"کامپایل‌شده اندازه مورد انتظار را داشت، اما یک مقایسه کامل همچنان تفاوت‌های " +"اساسی را پیدا کرد. تغییرات در نحوه چیدمان دستورالعمل ها توسط کامپایلر می " +"تواند بدون حل مشکل اساسی، نامزد را نزدیک تر کند. چنین تشخیص‌هایی می‌توانند " +"آزمایش بعدی را راهنمایی کنند، اما من هر پاداشی را برای «نزدیک‌تر شدن» در " +"برابر بررسی پذیرش کامل تأیید می‌کنم." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"من به الگوی این نتایج علاقه مند هستم. اگر یک مدل تخصصی هوش مصنوعی در یک " +"خانواده کامپایلر آشنا به خوبی عمل کند، آیا این مزیت از تغییر زنجیره ابزار " +"باقی می ماند؟ و هنگامی که هر دو مدل هوش مصنوعی بازیابی خوبی داشته باشند، " +"آموزش هنوز چقدر اضافه می کند؟ پاسخ‌ها به ما کمک می‌کنند تصمیم بگیریم که هر " +"نوع مدل در کجا مفیدتر است." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "این چه نوع عامل هوش مصنوعی را پیشنهاد می کند؟" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"اگر مدل ها در مراحل مختلف کمک کننده باشند، یک ترتیب مفید ممکن است عاملی " +"گسترده با دسترسی به یک مدل تخصصی هوش مصنوعی باشد. هنگامی که یک کار به یک " +"جستجوی کامپایلر آشنا تبدیل می شود، می تواند مدل تخصصی هوش مصنوعی را برای " +"نامزدها بپرسد. اگر نتایج منطقی نباشند، عامل گسترده‌تر می‌تواند به شواهد هدف " +"بازگردد یا خود اندازه‌گیری را بررسی کند." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"در آن ترتیب، تخصص به ابزاری تبدیل می‌شود که عامل می‌تواند با توسعه تحقیقات " +"انتخاب کند. عامل آزادی تغییر جهتی را حفظ می کند که پیشرفت های قبلی را ممکن " +"کرده است." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"این به طور طبیعی از تغییر صنعتی که در مقاله قبلی توضیح دادم ناشی می شود. " +"توانایی انجام آزمایش‌های بسیار بیشتر، نحوه سازماندهی کار را تغییر می‌دهد. " +"همچنین دلیلی به ما می دهد تا بپرسیم کدام تصمیمات نیاز به قضاوت گسترده دارند " +"و کدام یک از طریق تجربه مکرر با یک هنر خاص بهبود می یابند." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"تا اینجا قوی‌ترین مدل عمومی جای خود را در گردش کار من پیدا کرده، چون مسائلی " +"را حل کرده که قبلاً حل نشده مانده بودند. همین موفقیت‌ها مرا به بررسی دقیق‌تر" +" فرایند ترغیب می‌کنند: چه مقدار به گستردگی توانایی مدل وابسته بود، و چه " +"مقدار را مدلی آموزش‌دیده برای همین نوع بازسازی می‌تواند انجام دهد؟" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}مخزن‌ها راهی برای آزمایش سؤال به ما می‌دهند.{ph1} من می‌خواهم از آن " +"رکورد برای ساخت مقایسه و دیدن آنچه یاد می‌گیریم استفاده کنم." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "مدارک و اسناد مدل" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"مثال‌ها مقایسه‌های سطح عملکرد تاریخی ثبت شده در commit‌های مرتبط را توصیف " +"می‌کنند. بررسی های زمان اجرای کل بازی نقاط عطف جداگانه ای هستند. منبع و " +"سوابق مطابق در 13 اکتبر 2026 بررسی شدند." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"برچسب TH09 {ph0} به معنای GPT-6-Astra است. مدل مرتبط با {ph1} در طول زمان " +"تغییر کرد، به طوری که برچسب به تنهایی نمی تواند مدل مورد استفاده در یک اجرای" +" خاص را شناسایی کند. نام مدل صریح در سایر کامیت‌های ذکرشده، انتساب ثبت شده " +"را ارائه می کند. این تاریخچه ها شامل اندازه گیری ثابت هزینه یا تلاش برای هر " +"اجرا نمی شود." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 طول عمر اشیای موقت:{ph1} {ph2}بررسی زمینه اولیه{ph3} و " +"{ph4}بازسازی کامل تأیید شده توسط یک کامپایل مجدد تمیز از منبع{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front پاسخ به تماس:{ph1} {ph2}مناطق تشخیصی که مطابقت نداشتند{ph3}،" +" نمودار جریان کنترل جدید {ph4}Astra{ph5} و {ph6}بررسی مجدد پذیرفته شده " +"آن{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}دانش کامپایلر:{ph1} {ph2}استفاده دوباره از رفتار دسته‌بندی شناسه‌ها در " +"TH095{ph3}، {ph4}کد منبع بازیکن TH04 و ترتیب لینک{ph5} و {ph6}بازسازی کامل " +"تابع ایجاد دشمن TH09 توسط Luna{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}بررسی و تشخیص:{ph1} {ph2}TH08 ممیزی ثابت ممیز شناور{ph3}، {ph4}TH08 " +"بررسی عددی{ph5} و {ph6}TH09 بازسازی صرفه جویی در پخش{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"مقایسه‌های پیشنهادی مدل‌های تخصصی و آموزش RL آزمایش‌های آینده هستند. تاریخچه" +" پروژه به آنها انگیزه می دهد. هیچ مدل تخصصی آموزش دیده ای برای این مقاله " +"ارزیابی نشد." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "آیا مهندسی معکوس به مدل بزرگتری نیاز دارد؟ | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"آنچه که بازسازی Touhou در مورد مدل های عمومی، مدل های تخصصی و یادگیری ارائه " +"فرضیه های بهتر از بازخورد کامپایلر به من آموخت." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "در این صفحه" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "مدل ها و مقاله مهندسی معکوس" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "آزمایش های بازسازی منتخب" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "بازگشت به بالا" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}یادداشت‌های تفصیلی شواهد{ph1} شامل مقایسه‌های ثبت‌شده و زمینه آزمایش‌ها" +" هستند." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "نویسنده: N0zoM1z0 · ۱۳ اکتبر ۲۰۲۶ · پیش‌نویس برای بازبینی" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "راهنمای نصب" diff --git a/website/locales/fr/messages.po b/website/locales/fr/messages.po index 322e3b9d2..1664f4bd5 100644 --- a/website/locales/fr/messages.po +++ b/website/locales/fr/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Aller au contenu" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Accueil{ph1} / Blogue" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blogue." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Réflexions sur l'ingénierie inverse." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Reconstruction du jeu{ph0}Essai" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "La révolution industrielle dans l'ingénierie inverse" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -53,34 +53,35 @@ msgstr "" "TH04 m'ont appris sur les agents, la vérification et les connaissances qui " "se combinent dans les projets." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Lire l'article" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Par N0zoM1z0 · 10 octobre 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -101,6 +102,8 @@ msgstr "" " avec REA et les agents d'IA." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -136,112 +139,117 @@ msgstr "" "REA-Découvrez comment fonctionne le logiciel. Ingénierie inverse avec votre " "agent de codage." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Accueil REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Navigation principale" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA sur GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Rejoindre REA sur Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Suivre REA sur X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -250,35 +258,35 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Accueil{ph1} / {ph2}Blogue{ph3} / La reconstruction de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Essai * La reconstruction de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "La révolution industrielle dans l'ingénierie inverse." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Par N0zoM1z0 · 10 octobre 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "À retenir" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -291,7 +299,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -305,7 +313,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -318,7 +326,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -331,7 +339,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -342,65 +350,65 @@ msgstr "" "RE.{ph1} Les méthodes sont encore en train de prendre forme. Il reste encore" " beaucoup à explorer." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Comment l'expérience se compose" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Direction humaine{ph1} * Objectif et critères d'acceptation" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Autonomie" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agent" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Choisissez une expérience.{ph0}Proposer une hypothèse." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Vérification" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Référence de validation" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Essai contre a{ph0}référence concrète." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Dépôt" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Mémoire de travail" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -409,7 +417,7 @@ msgstr "Code, preuves,{ph0}contrôles et leçons." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -418,26 +426,26 @@ msgstr "Inadéquation{ph0}{ph1}Réviser l'hypothèse{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Un meilleur{ph0}{ph1}point de départ{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Réutilisation" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Passe{ph1} * Conservez le résultat et ses preuves" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -446,14 +454,14 @@ msgstr "" "Chaque projet laisse le suivant avec un meilleur point de départ. Cela " "inclut la correction des chèques lorsque nous découvrons une lacune." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "Dans cet article" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -461,7 +469,7 @@ msgstr "{ph0}Août 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -469,7 +477,7 @@ msgstr "{ph0} TH08: la suite{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -477,7 +485,7 @@ msgstr "{ph0}Deux approches{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -485,7 +493,7 @@ msgstr "{ph0} TH095: préparation combinée{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -493,7 +501,7 @@ msgstr "{ph0} TH04: à travers les architectures{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -501,7 +509,7 @@ msgstr "{ph0}D'exact à lisible{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -509,18 +517,18 @@ msgstr "{ph0}Le virage industriel{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Ce qui devient possible{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Ce qui a changé en août 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -535,7 +543,7 @@ msgstr "" "signifiait passer plus de temps sur la prochaine fonction. Cela signifiait " "aussi garder une image de plus en plus grande dans ma tête." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -549,7 +557,7 @@ msgstr "" "méthode peut être utile ailleurs, mais chaque champ doit établir ce qu'il " "peut vérifier par rapport à une référence fiable." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -562,7 +570,7 @@ msgstr "" "programme et aux outils de développement ordinaires. La reconstruction de " "Touhou m'a donné un projet substantiel pour le découvrir." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -580,7 +588,7 @@ msgstr "" "d'attention à l'orientation du projet et à la fiabilité de ses " "vérifications." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -591,7 +599,7 @@ msgstr "" "demander ce qui survivrait au-delà du projet actuel. Le prochain jeu " "bénéficierait-il de tout ce que nous venions d'apprendre?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: s'appuyer sur le travail humain" @@ -600,7 +608,7 @@ msgstr "TH08: s'appuyer sur le travail humain" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -614,7 +622,7 @@ msgstr "" "base substantielle. Il est venu avec la connaissance de la construction et " "un historique des contributions que j'ai conservé dans la suite." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -625,7 +633,7 @@ msgstr "" "continuation indépendante a commencé le 13 août. Le 19 août, le grand livre " "enregistrait la source des 1 107 fonctions de jeu identifiées." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -636,7 +644,7 @@ msgstr "" "onze jours après le début de la continuation. Une édition Web a suivi. La " "version native Linux 64 bits est arrivée le 30 août." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -652,7 +660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -670,12 +678,12 @@ msgstr "" "une route exercée atteint l'état attendu. L'agent propose une explication et" " la teste; un décalage lui donne quelque chose de spécifique à étudier." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Une correspondance exacte avec la mauvaise constante" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -687,7 +695,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -700,7 +708,7 @@ msgstr "" "puissance du joueur par rapport {ph0}. L'original utilisé {ph1}, le seuil de" " puissance maximale." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -716,14 +724,14 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "" "{ph0}Pourtant, la fonction avait déjà réussi la comparaison exacte.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -739,7 +747,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -756,7 +764,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -771,7 +779,7 @@ msgstr "" "virgule flottante. Il a trouvé douze autres références incorrectes dans cinq" " fonctions acceptées." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -785,7 +793,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -795,7 +803,7 @@ msgstr "" "{ph0}La référence de vérification (oracle) devait également être " "reconstruite.{ph1} La réparer faisait partie de la réparation du jeu." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -814,7 +822,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -831,7 +839,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -841,7 +849,7 @@ msgstr "" "{ph0}Un lot réussi nous a donné à la fois du code récupéré et un meilleur " "environnement pour le lot suivant.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Deux idées différentes de reconstruction" @@ -850,7 +858,7 @@ msgstr "Deux idées différentes de reconstruction" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -862,7 +870,7 @@ msgstr "" "ce genre de travail. L'avis annonce que d'autres développements auront lieu " "en privé jusqu'à leur achèvement. Un passage se lit comme suit:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -872,7 +880,7 @@ msgstr "" "cet espace, tirée de notre travail, donne une mauvaise image des futurs " "efforts de décompilation…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -890,7 +898,7 @@ msgstr "" "discuter concerne la manière dont la reconstruction devrait se dérouler et " "la manière dont une contribution devrait être jugée." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -904,7 +912,7 @@ msgstr "" "personne. La confiance dans le contributeur importait parce qu'une grande " "partie du raisonnement se produisait pendant qu'ils travaillaient." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -915,7 +923,7 @@ msgstr "" "construisent des outils. Ce qui a changé pour moi, c'est qu'un agent pouvait" " utiliser ces connaissances pour poursuivre seul la prochaine enquête." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -930,7 +938,7 @@ msgstr "" " autre personne puisse examiner pourquoi nous avons choisi une " "implémentation, même si un agent a fait la majeure partie du travail." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -943,7 +951,7 @@ msgstr "" "Cela soulève de vraies questions sur le crédit. Cela change également ce que" " les mainteneurs doivent savoir avant d'accepter une contribution." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -959,7 +967,7 @@ msgstr "" "Différentes communautés peuvent choisir la part de ce changement qu'elles " "souhaitent assumer." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -984,7 +992,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -997,14 +1005,14 @@ msgstr "" " raccourci. TH08's {ph4}crédits et provenance{ph5} enregistrez la limite de " "continuation." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: l'expérience commence à s'accumuler" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1019,7 +1027,7 @@ msgstr "" " le jeu. Mais nous en savions déjà beaucoup plus sur la façon de commencer " "une reconstruction et de la faire avancer." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1033,7 +1041,7 @@ msgstr "" "i386 a été marquée jouable le 10 septembre, environ douze jours après " "l'initialisation." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1045,7 +1053,7 @@ msgstr "" "L'expérience était déjà présente dans les outils et dans la manière dont le " "projet était organisé." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1060,7 +1068,7 @@ msgstr "" "les voir travailler ensemble. Cette leçon a aidé à façonner la façon dont " "nous avons abordé la construction de l'ensemble du programme de TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1073,7 +1081,7 @@ msgstr "" " peut continuer à m'aider après que je sois passé à autre chose. L'agent " "suivant peut utiliser le résultat sans répéter l'enquête qui y a conduit." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1089,7 +1097,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1101,7 +1109,7 @@ msgstr "" "match.{ph1} Nous pouvons consacrer plus d'efforts au prochain projet sur ce " "qui est réellement nouveau à propos de sa cible." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1114,7 +1122,7 @@ msgstr "" "poursuivre le travail. Ils n'ont pas à reconstituer l'historique complet du " "projet pour savoir pourquoi la source ressemble à ce qu'elle est." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: le flux de travail survit à une architecture différente" @@ -1123,7 +1131,7 @@ msgstr "TH04: le flux de travail survit à une architecture différente" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1140,7 +1148,7 @@ msgstr "" "ReC98{ph3} nous a donné des connaissances précieuses et du matériel source " "ici aussi." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1153,7 +1161,7 @@ msgstr "" "sauvegardes. Le travail actuel est un port natif 64 bits. L'établissement " "d'une version DOS fonctionnelle donne d'abord à ce port une référence." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1166,7 +1174,7 @@ msgstr "" "vérifié notre travail. Mais l'agent pourrait toujours suivre une question " "jusqu'à un résultat et laisser ce résultat guider l'expérience suivante." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1181,7 +1189,7 @@ msgstr "" "les preuves et les vérifications sont disponibles, un agent peut résoudre la" " question autant qu'il l'a fait sur un titre Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1193,7 +1201,7 @@ msgstr "" "de travailler. L'architecture définissait le problème; le flux de travail " "nous donnait encore un moyen de le résoudre." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1210,7 +1218,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1220,12 +1228,12 @@ msgstr "" "État du projet au 10 octobre 2026: {ph0}Reconstruction DOS et tests " "manuels{ph1} · {ph2}port 64 bits{ph3}. Le port reste en développement." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Du code exact au code lisible" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1234,7 +1242,7 @@ msgstr "" "Une fois qu'une reconstruction fonctionne, je veux que quelqu'un d'autre " "puisse la comprendre." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1249,7 +1257,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1266,7 +1274,7 @@ msgstr "" "preuves. Nous gardons le raisonnement avec la source afin que la personne " "suivante puisse voir d'où vient cette interprétation." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1281,14 +1289,14 @@ msgstr "" "cet état. Pour déplacer le comportement en toute sécurité, nous devons " "récupérer la relation derrière l'ancien accès mémoire." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "L'ordre que j'utilise maintenant est:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1304,7 +1312,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1321,7 +1329,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1337,7 +1345,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1352,7 +1360,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1369,7 +1377,7 @@ msgstr "" "vérifie que le programme reconstruit se construit toujours et se comporte " "correctement le long des chemins que nous exerçons." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1383,7 +1391,7 @@ msgstr "" "vérifications disponibles donne à l'agent un échec concret à enquêter avant " "de poursuivre un refactor." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1401,7 +1409,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1420,7 +1428,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1431,12 +1439,12 @@ msgstr "" "sémantique rend les connaissances récupérées utilisables.{ph1} Un port peut " "alors s'appuyer sur les deux." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Qu'est-ce qui en fait un changement industriel" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1450,7 +1458,7 @@ msgstr "" " pouvais faire. Un meilleur outil pourrait aider avec chaque fonction " "ultérieure qui en avait besoin." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1464,7 +1472,7 @@ msgstr "" " prescrive chaque étape, une grande partie du travail reste liée à mon " "attention." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1478,7 +1486,7 @@ msgstr "" " pour réessayer. Je dois encore décider si les preuves accumulées " "soutiennent une étape importante du projet." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1493,7 +1501,7 @@ msgstr "" "vérifications de références. L'agent peut les utiliser pour tester la source" " qu'il propose et voir où son explication tient la route." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1511,7 +1519,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1532,7 +1540,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1550,7 +1558,7 @@ msgstr "" "réparer et revoir les résultats qu'il a affectés. Le projet suivant peut " "alors hériter d'un outil plus puissant." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1566,7 +1574,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1579,7 +1587,7 @@ msgstr "" "leurs leçons. Travailler sur un jeu peut améliorer les conditions de départ " "d'un autre." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1591,12 +1599,12 @@ msgstr "" "utiliser. L'amélioration de ces outils change ce que la personne suivante—ou" " l'agent suivant—peut accomplir." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Les projets que nous pouvons maintenant envisager" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1608,7 +1616,7 @@ msgstr "" "attention que je ne pourrais raisonnablement lui accorder. De nombreux " "projets resteraient des idées." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1626,7 +1634,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1637,7 +1645,7 @@ msgstr "" "commentaires et connaissances accumulés permettraient à un agent de " "travailler de manière fiable sur ce sujet?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1648,12 +1656,12 @@ msgstr "" " seuls. Chacun peut améliorer la façon dont nous abordons le suivant. Je " "veux continuer à explorer jusqu'où cela peut nous mener." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Jalons et sources du projet" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1688,7 +1696,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1722,7 +1730,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1741,7 +1749,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1765,7 +1773,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1787,7 +1795,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1803,7 +1811,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1825,7 +1833,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1840,7 +1848,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1862,27 +1870,27 @@ msgstr "" "Touhou avec des agents d'IA et à la manière dont les connaissances se " "combinent entre TH08, TH095 et PC-98 TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Expérience portée entre les projets" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Essai de reconstruction de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -1891,18 +1899,18 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Accueil{ph1}{ph2}/{ph3}Laboratoire de vitesse des dinosaures" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Inspecter → reconstruire → modifier" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Reconstruisez la règle de vitesse du dinosaure." @@ -1911,7 +1919,7 @@ msgstr "Reconstruisez la règle de vitesse du dinosaure." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1924,15 +1932,15 @@ msgstr "" "avons utilisé sa règle pour construire ce mini-jeu avec {ph2}vitesse " "réglable.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Sur cette page" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1940,7 +1948,7 @@ msgstr "{ph0}Jouez et changez la vitesse{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1948,7 +1956,7 @@ msgstr "{ph0}Lire la règle récupérée{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1956,18 +1964,18 @@ msgstr "{ph0}Vérifiez la reconstruction{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Essayez l'analyse{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Jouez et changez la vitesse" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1979,49 +1987,49 @@ msgstr "" "vitesse fixe. Sélectionnez la règle récupérée pour démarrer à 6 et accélérer" " progressivement à nouveau." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Jouer à la reconstruction" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Jouer" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Sauter ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Recommencer" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Vitesse" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Utilisez la règle d'accélération récupérée" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Règle d'origine: commencez à 6, puis augmentez vers 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Déplacez le curseur pour définir votre propre vitesse. L'espace ou le saut " "efface un cactus." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2030,7 +2038,7 @@ msgstr "" "Activez JavaScript pour lire la reconstruction. Le code et l'explication ci-" "dessus restent lisibles." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Lire le script REA renvoyé" @@ -2038,7 +2046,7 @@ msgstr "Lire le script REA renvoyé" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2053,7 +2061,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2063,18 +2071,18 @@ msgstr "" "Les paramètres sont {ph0}, {ph1} et {ph2}. Le jeu exécute cette branche sur " "une mise à jour sans collision." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Utilisez la même règle dans le nouveau jeu" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Copier" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2092,19 +2100,19 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "" "{ph0}Télécharger la règle de vitesse{ph1} · {ph2}Lire le code du jeu{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Vérifiez la reconstruction" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2115,27 +2123,27 @@ msgstr "" "obstacles et la planification automatique désactivés. Comparez ces vitesses " "enregistrées avec une relecture de la règle récupérée." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Mises à Jour" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Jeu original" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Règle reconstruite" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Exécutez le contrôle de vitesse" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2144,14 +2152,14 @@ msgstr "" "Valeurs arrondies à trois décimales. La branche vérifie avant d'ajouter, de " "sorte que l'incrément final peut prendre une vitesse juste au-dessus de 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Essayez l'analyse vous-même" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2160,7 +2168,7 @@ msgstr "{ph0}Mettre en place REA{ph1} avec votre agent de codage." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2169,7 +2177,7 @@ msgstr "" "Suivez le {ph0}étapes de connexion du navigateur{ph1}, en utilisant {ph2} " "comme l'URL de la page." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2186,7 +2194,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2198,7 +2206,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2212,7 +2220,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2227,7 +2235,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2253,12 +2261,12 @@ msgstr "" "Lisez la règle de vitesse du jeu de dinosaures avec REA , reconstruisez-la, " "puis modifiez la vitesse et jouez." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Reconstruction de la vitesse des dinosaures" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2267,52 +2275,52 @@ msgstr "" "Mini-jeu de dinosaure. Utilisez le bouton de saut ou appuyez sur Espace " "pendant que le jeu est concentré." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Copier la règle de vitesse reconstruite" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copie de l'invite d'analyse des dinosaures" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Aller au contenu" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Accueil{ph1} / Foire aux QUESTIONS" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "FOIRE aux questions sur REA." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Configuration, mises à jour, analyse et dépannage." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Thèmes" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2320,7 +2328,7 @@ msgstr "{ph0}Configuration et mises à jour{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2328,7 +2336,7 @@ msgstr "{ph0}Analyse{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2336,31 +2344,31 @@ msgstr "{ph0}Dépannage{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Données et partage{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Configuration et mises à jour" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Comment installer REA ?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * configuration de l'agent" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Copier" @@ -2368,7 +2376,7 @@ msgstr "Copier" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2382,12 +2390,12 @@ msgstr "" "chemin du fichier à analyser et une question. Le {ph0}guide de " "configuration{ph1} présente les prérequis et votre première analyse." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Quels agents de codage peuvent utiliser REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2402,18 +2410,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Connectez votre agent de codage{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Comment mettre REA à jour ?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2422,13 +2430,13 @@ msgstr "" "REA publie fréquemment, y compris des corrections de bogues. Si vous avez " "installé le modèle CLI avec le modèle npm :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * installé sur le CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2438,14 +2446,14 @@ msgstr "" "Suivez la commande d'actualisation de la configuration imprimée par la mise " "à jour. Si vous configurez votre agent via {ph0}, cours:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * configuration de l'agent d'actualisation" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2458,14 +2466,14 @@ msgstr "" "passer à la nouvelle version. Pour une commande CLI ponctuelle, ajoutez la " "commande après {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Installe la compétence à partir de skills.sh assez?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2478,24 +2486,24 @@ msgstr "" "la compétence correspondante, redémarrez votre agent afin qu'il puisse " "appeler les outils." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Analyse" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Que puis-je analyser avec REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Commencez avec le type de logiciel que vous avez:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2507,7 +2515,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2519,7 +2527,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2529,7 +2537,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2541,12 +2549,12 @@ msgstr "" "Android, les micrologiciels et les ressources packagées. {ph0}Voir les " "études de cas{ph1} pour des enquêtes travaillées." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Ai-je besoin des modèles Hopper , Ghidra ou IDA ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2559,7 +2567,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2572,12 +2580,12 @@ msgstr "" " hôte et votre cible déterminent quel fournisseur peut être utilisé. " "{ph0}Mettre en place une analyse des programmes en code machine{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Puis-je utiliser REA sans agent de codage?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2586,14 +2594,14 @@ msgstr "" "Oui. Le CLI utilise les mêmes workflows d'analyse. Pour une application " "locale JavaScript ou Electron :" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * analyse statique des applications" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2605,13 +2613,13 @@ msgstr "" "d'installation." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Quel code REA renvoie-t-il ?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2627,7 +2635,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2640,12 +2648,12 @@ msgstr "" "{ph2}Vérificateur de drapeau CTF{ph3} montrez comment ce processus " "fonctionne." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Que demander à mon agent ?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2662,7 +2670,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2670,7 +2678,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2680,18 +2688,18 @@ msgstr "" "Remplacez le chemin par votre cible. Les {ph0}guides touristiques{ph1} " "fournissez des invites pour des exemples natifs, Electron et de navigateur." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Dépannage" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Pourquoi mon agent ne peut-il pas voir les outils REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2701,7 +2709,7 @@ msgstr "" "Redémarrez ou reconnectez votre agent après la configuration. Vérifiez son " "enregistrement REA avec {ph0}; pour le modèle Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * vérifiez un client" @@ -2709,7 +2717,7 @@ msgstr "Terminal * vérifiez un client" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2720,14 +2728,14 @@ msgstr "" " rapport indique un enregistrement manquant ou périmé, exécutez la " "configuration pour ce client:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * réparer la configuration d'un client" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2739,14 +2747,14 @@ msgstr "" "correct mais que les outils restent absents, vérifiez l'erreur de connexion " "MCP du client. {ph0}Plus de diagnostics de configuration{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Dois-je d'abord démarrer Hopper?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2759,14 +2767,14 @@ msgstr "" "de la licence avant l'analyse sans surveillance. {ph0}Voir configuration du " "fournisseur natif{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Que faire si je rencontre un bug ?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2778,7 +2786,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2791,17 +2799,17 @@ msgstr "" "Incluez le nom du fournisseur lorsque le problème implique l'analyse de " "programmes en code machine." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Données et partage" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "Est-ce que REA télécharge mon application?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2811,7 +2819,7 @@ msgstr "" "et la politique de données de son fournisseur modèle s'applique à ces " "résultats." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Comment puis-je partager un exemple ou contribuer?" @@ -2820,7 +2828,7 @@ msgstr "Comment puis-je partager un exemple ou contribuer?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2836,7 +2844,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2861,77 +2869,77 @@ msgstr "" "Réponses aux questions courantes sur REA: installation, mises à jour, outils" " d'analyse, agents de codage, dépannage et exemples de partage." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Questions fréquemment posées sur REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Copier la commande d'installation REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Copier la commande de mise à jour REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Commande d'actualisation de la configuration de l'agent de copie" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Copier la commande d'analyse REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Copier l'exemple d'invite d'analyse" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Commande de diagnostic de client de copie" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Copier la commande d'installation étendue" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Aller au contenu" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Accueil{ph1} / Votre première enquête" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Découvrez où{ph0}les notes exportées disparaissent." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2940,14 +2948,14 @@ msgstr "" "Utilisez REA pour inspecter une petite application, suivez son bouton " "Exporter les notes et vérifiez vous-même un détail." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "Dans cet exercice" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2955,7 +2963,7 @@ msgstr "{ph0}1. Mettre en place{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2963,7 +2971,7 @@ msgstr "{ph0}2. Renseignez - vous sur l'exportation{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2971,7 +2979,7 @@ msgstr "{ph0}3. Suivez la réponse{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2979,13 +2987,13 @@ msgstr "{ph0}4. Vérifier une prédiction{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Poser une autre question{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Connectez votre agent à REA" @@ -2998,29 +3006,29 @@ msgstr "1. Connectez votre agent à REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Copier" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Ou exécutez cette commande dans votre terminal:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3029,14 +3037,14 @@ msgstr "" "Passez en revue le plan, approuvez la configuration, puis redémarrez votre " "agent. Déjà connecté? Continuez ci-dessous." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Demandez où le CSV est écrit" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3048,7 +3056,7 @@ msgstr "" "des notes{ph1} bouton. Votre agent peut inspecter son code sans installer ni" " lancer Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3060,14 +3068,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Télécharger un exemple de ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3078,12 +3086,12 @@ msgstr "" "archive vous-même. Donnez-lui le chemin vers le {ph0} dossier et la même " "question d'exportation." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Suivez la réponse jusqu'au code" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "" @@ -3093,7 +3101,7 @@ msgstr "" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3105,12 +3113,12 @@ msgstr "" "en CSV et écrit {ph1} dans le dossier Téléchargements de l'utilisateur. Les " "colonnes sont {ph2} et {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Du bouton au rédacteur de fichiers" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3119,7 +3127,7 @@ msgstr "" "L'analyse statique de REA associe le message à son gestionnaire. La " "destination est lue à partir du code." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3131,19 +3139,19 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "" "{ph0}Voir la trace complète du code et le résultat REA enregistré{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Vérifier une prédiction" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3152,19 +3160,19 @@ msgstr "" "Une virgule sépare les colonnes CSV. Que se passe-t-il lorsqu'un titre de " "note contient lui-même une virgule ou des guillemets?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Exécutez le chèque vous-même" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Ouvrez un terminal dans le déballé {ph0} dossier:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3174,17 +3182,17 @@ msgstr "" "ou Zsh. Votre agent peut exécuter le même JavaScript dans le shell de votre " "plate-forme." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Poser une autre question" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Essayez un suivi dans la même conversation:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3193,7 +3201,7 @@ msgstr "" "Que se passe-t-il si le fichier ne peut pas être écrit? Suivez l'erreur pour" " revenir à la page." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3206,7 +3214,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3221,7 +3229,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3235,7 +3243,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3260,65 +3268,65 @@ msgstr "" "demandez où vont les notes exportées et vérifiez le formateur CSV avec un " "exemple de titre." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Votre première enquête sur le REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Copier l'invite d'installation de REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Commande Copier le programme d'installation" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Invite d'enquête sur les notes de copie" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Copier l'invite de vérification CSV" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Commande de vérification du formateur de copie" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Aller au contenu" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Accueil{ph1} / Commencer" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Configurez le modèle REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3326,49 +3334,49 @@ msgstr "" "Connectez REA à votre agent de codage ou inspectez une application locale à " "partir de votre terminal." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Ouvrez un terminal et vérifiez:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Borne" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Copier" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell)est également compatible avec:{ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3381,7 +3389,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3392,17 +3400,17 @@ msgstr "" " ce système\"{ph1} quand tu cours {ph2}, exécutez ceci une fois et " "réessayez:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Si vous utilisez le modèle Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Autrement:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Fermez le Terminal, ouvrez-le à nouveau, puis:" @@ -3410,7 +3418,7 @@ msgstr "Fermez le Terminal, ouvrez-le à nouveau, puis:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3422,7 +3430,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3434,7 +3442,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3444,14 +3452,14 @@ msgstr "" "Vous préférez un installateur régulier? Téléchargez la version LTS à partir " "de {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Options de configuration" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3459,7 +3467,7 @@ msgstr "{ph0}Connectez votre agent de codage{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3467,7 +3475,7 @@ msgstr "{ph0}Utilisez le modèle CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3475,18 +3483,18 @@ msgstr "{ph0}Mettre en place une analyse des programmes en code machine{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Obtenir de l'aide{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Connectez votre agent de codage" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3498,12 +3506,12 @@ msgstr "" "Windsurf, Grok Build, et d'autres pris en charge MCP clients. Le connecteur " "de Grok Bot est ajouté à partir de son chat." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Nouveau sur les agents de codage?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3515,7 +3523,7 @@ msgstr "" "exécuter des commandes, et il demande avant d'apporter des modifications. " "REA lui donne des outils de rétro-ingénierie." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3527,7 +3535,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3540,7 +3548,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3553,7 +3561,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3563,7 +3571,7 @@ msgstr "" "{ph0}{ph1}OpenCode{ph2}{ph3}, code source ouvert. Connectez le fournisseur " "de modèle de votre choix." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3581,18 +3589,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Ou exécutez la configuration vous-même" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Comment ouvrir un terminal?" @@ -3601,7 +3609,7 @@ msgstr "Comment ouvrir un terminal?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3617,7 +3625,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3631,7 +3639,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3646,7 +3654,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3656,7 +3664,7 @@ msgstr "" "Collez une commande avec {ph0} {ph1} (macOS: {ph2} {ph3}; Linux terminaux: " "{ph4} {ph5} {ph6}), puis appuyez sur Entrée." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3668,12 +3676,12 @@ msgstr "" " une sauvegarde de la configuration existante. Il demande avant d'appliquer " "les modifications." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Redémarrez votre client une fois la configuration terminée." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Comment puis-je redémarrer mon client?" @@ -3682,7 +3690,7 @@ msgstr "Comment puis-je redémarrer mon client?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3698,7 +3706,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3708,7 +3716,7 @@ msgstr "" "{ph0}Agents terminaux{ph1} (Claude Code, Codex, Gemini CLI): quittez la " "session et recommencez-la." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3718,7 +3726,7 @@ msgstr "" "application JavaScript ou Electron, vous pouvez commencer par:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3729,12 +3737,12 @@ msgstr "" "points d'entrée, les appels et les dépendances impliqués, avec les " "emplacements sources de vos résultats." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Remplacez le chemin par votre cible locale." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Comment puis-je obtenir le chemin d'accès complet d'un dossier?" @@ -3743,7 +3751,7 @@ msgstr "Comment puis-je obtenir le chemin d'accès complet d'un dossier?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3759,7 +3767,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3772,7 +3780,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3782,19 +3790,19 @@ msgstr "" "{ph0}Tout système:{ph1} faites glisser le dossier dans une fenêtre de " "terminal et son chemin apparaît." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "Dans un terminal, mettez des guillemets autour d'un chemin qui contient des " "espaces." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Utilisez le modèle CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3803,14 +3811,14 @@ msgstr "" "Analysez un dossier d'application JavaScript ou Electron ou une archive ASAR" " sans exécuter l'application:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Analyse statique des applications" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3820,13 +3828,13 @@ msgstr "" "Remplacez le chemin par le répertoire de votre application extraite ou {ph0}" " dossier. Sur Windows, un chemin tel que {ph1} travaille ici." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Où puis-je trouver une application .fichier asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3838,7 +3846,7 @@ msgstr "" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3850,7 +3858,7 @@ msgstr "{ph0}Windows:{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3863,14 +3871,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0}Linux:{ph1} souvent {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3878,7 +3886,7 @@ msgstr "" "Certaines applications s'installent ailleurs. Recherchez le dossier de " "l'application pour {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3890,31 +3898,31 @@ msgstr "" "résoudre sont marquées dans le résultat." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Si vous souhaitez un permanent {ph0} commande dans votre shell:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Installez le CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Continuez avec le guide d'application JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Mettre en place une analyse des programmes en code machine" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3924,12 +3932,12 @@ msgstr "" "Choisissez et configurez-en un ci-dessous, puis donnez à REA votre " "exécutable ou bibliothèque." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Choisissez un outil: Ghidra, Hopper ou IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3941,17 +3949,17 @@ msgstr "" "nécessite un décompilateur natif pour votre architecture hôte. Définissez " "les chemins avant d'exécuter le programme d'installation:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Connectez votre installation de Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra de la connexion · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3963,12 +3971,12 @@ msgstr "" "client sélectionné. Sur Linux arm64, vous devrez peut-être créer séparément " "le décompilateur natif de Ghidra." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Connectez le modèle Ghidra sur le modèle Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3979,12 +3987,12 @@ msgstr "" " et DLL natives x86 et x64 PE sur des lecteurs NTFS locaux fixes. Utilisez " "un Ghidra 12.1 existant.installation x et un JDK 64 bits 21 ou plus récent:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra connexion · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3992,7 +4000,7 @@ msgstr "" "Remplacez les deux chemins par vos installations, puis passez en revue le " "plan de configuration." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -4002,7 +4010,7 @@ msgstr "" "dessus; il détecte une installation existante ou propose un plan " "d'installation pour votre approbation." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -4012,7 +4020,7 @@ msgstr "" "de démonstration ou l'activation de la licence avant une analyse sans " "surveillance." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -4023,7 +4031,7 @@ msgstr "" "MCP existant pour une interface graphique attachée ou une base de données " "sans en-tête. Les analyses sans tête Linux et macOS restent non vérifiées." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Connecter un enregistrement IDA existant à un MCP" @@ -4033,7 +4041,7 @@ msgstr "Connecter un enregistrement IDA existant à un MCP" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4045,13 +4053,13 @@ msgstr "" "{ph2} dans un fichier JSON. Un existant {ph3} objet avec un {ph4} l'entrée " "est également acceptée. Pointez REA sur ce fichier avant l'installation:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA connexion · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4069,7 +4077,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4081,18 +4089,18 @@ msgstr "" "requête CLI. Pour un agent, inclure {ph1} dans l'environnement " "d'enregistrement de REA et sélectionnez IDA lors de l'ouverture du binaire." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Pour une configuration Ghidra existante, inspectez une fonction avec:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Analyse de fonction" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." @@ -4100,13 +4108,13 @@ msgstr "" "Remplacer {ph0} avec le nom ou l'adresse de la fonction que vous souhaitez " "inspecter." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "" "Fonctionnement de l'analyse des sessions de programmes en code machine" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4119,7 +4127,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4129,18 +4137,18 @@ msgstr "" "{ph0}Suivez un exemple d'analyse de programmes en code machine{ph1} pour " "voir comment le résultat de la fonction conduit à un calcul récupéré." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Obtenir de l'aide" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Si votre agent ne voit pas REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4150,27 +4158,27 @@ msgstr "" "Redémarrez ou reconnectez le client après l'installation. Vérifiez sa " "connexion REA avec {ph0}; pour le modèle Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Vérifiez un client" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Si un fournisseur a besoin d'attention" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Vérifiez le fournisseur que vous utilisez. Pour Ghidra:" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Vérifiez un fournisseur" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4181,7 +4189,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4194,7 +4202,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4208,7 +4216,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4222,7 +4230,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4247,112 +4255,112 @@ msgstr "" "JavaScript ou Electron à partir du terminal. Configuration, premières " "questions et guides du fournisseur natif." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Copier la vérification de la version Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Copier Node.js commande d'installation pour Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Copier la commande de stratégie d'exécution PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Copier Homebrew Node.js commande d'installation" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Copier la commande d'installation fnm pour macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Copier Node.js 24 commandes pour macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Copier la commande d'installation fnm pour Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Copier Node.js 24 commandes pour Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "Guide de démarrage du REA" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Copier l'invite d'installation de REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Commande de configuration de l'agent de copie" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Copier la commande d'analyse JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Copier la commande d'installation de CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Copier la commande de connexion à Ghidra pour macOS et Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Copiez la connexion Ghidra pour le PowerShell Windows" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Copiez la connexion IDA pour le PowerShell Windows" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Copier la commande d'analyse de fonction native" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Commande de diagnostic de client de copie" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Commande de diagnostic du fournisseur de copie" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -4361,7 +4369,7 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" @@ -4370,13 +4378,13 @@ msgstr "" "navigateur" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Voyez ce qui se passe{ph0}lorsque vous cliquez." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4385,14 +4393,14 @@ msgstr "" "Utilisez une petite application de navigateur pour connecter une action, sa " "demande réseau et le JavaScript qui génère un téléchargement." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "Dans ce guide" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4400,7 +4408,7 @@ msgstr "{ph0}L'exemple{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4408,7 +4416,7 @@ msgstr "{ph0}Ouvrez le navigateur{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4416,7 +4424,7 @@ msgstr "{ph0}Demandez à votre agent{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4424,13 +4432,13 @@ msgstr "{ph0}Capture à partir de CLI{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Lire la requête et le script{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Que se passe-t-il lorsque vous cliquez sur Exporter?" @@ -4440,7 +4448,7 @@ msgstr "Que se passe-t-il lorsque vous cliquez sur Exporter?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4452,7 +4460,7 @@ msgstr "" "notes{ph3} bouton. Cliquer dessus se charge {ph4}, formate les deux notes en" " CSV et lance un téléchargement." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Du clic au téléchargement CSV" @@ -4463,7 +4471,7 @@ msgstr "Du clic au téléchargement CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4480,7 +4488,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4499,7 +4507,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4509,17 +4517,17 @@ msgstr "" "{ph0}03 · Votre agent{ph1}{ph2}Lire le code d'exportation{ph3}{ph4}Connectez" " la requête observée à {ph5} dans {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Démarrez la capture avant de cliquer sur Exporter les notes." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Ouvrez Chrome avec le débogage à distance" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4528,21 +4536,21 @@ msgstr "" "Ouvrez l'exemple hosted Notes avec un profil de navigateur distinct et un " "port de débogage local. Sur le modèle Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Démarrez l'exemple de navigateur" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Copier" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4552,7 +4560,7 @@ msgstr "" " ou Windows . Vous pouvez remplacer l'URL de la page par une autre page que " "vous souhaitez inspecter." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4561,7 +4569,7 @@ msgstr "" "REA se connecte à ce navigateur existant. Vous gardez le contrôle de la " "page, effectuez l'action et fermez le navigateur lorsque vous avez terminé." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Demandez à votre agent de regarder une action" @@ -4574,7 +4582,7 @@ msgstr "Demandez à votre agent de regarder une action" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4586,7 +4594,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4598,7 +4606,7 @@ msgstr "" "construit?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4608,7 +4616,7 @@ msgstr "" "Exemple d'invite. Donnez à votre agent le point de terminaison de débogage, " "{ph0}, et l'URL de la page. Laissez-le démarrer la capture avant de cliquer." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4619,23 +4627,23 @@ msgstr "" "et lit les preuves résultantes. Il peut ensuite inspecter le script derrière" " l'exportation." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Ou capture depuis le terminal" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Trouver l'ID cible de la page:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Trouver la page" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4645,14 +4653,14 @@ msgstr "" "Choisissez la cible avec l'URL de l'exemple de Notes. Remplacer {ph0} ci-" "dessous avec son identifiant, puis exécutez:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Capturez les dix prochaines secondes" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4663,7 +4671,7 @@ msgstr "" " {ph0}Exporter des notes{ph1} dans ce navigateur. Le résultat arrive après " "la fin de la fenêtre d'observation." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4674,49 +4682,49 @@ msgstr "" "de cette fenêtre et la forme de la réponse JSON. Les demandes antérieures " "sont en dehors de cette capture." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Lire la requête et exporter le script" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Enregistré avec REA 4.1.0 sur l'exemple des notes locales" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Fait capturé" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Valeur" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Demande" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Réponse" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Initiateur de la demande" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * scénario" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Structure de la réponse" @@ -4724,19 +4732,19 @@ msgstr "Structure de la réponse" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} avec {ph1} et {ph2} champs" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Lire les scripts chargés" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4748,7 +4756,7 @@ msgstr "" "les données sont utilisées:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4761,7 +4769,7 @@ msgstr "" "ce clic demandé {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4773,7 +4781,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4799,65 +4807,65 @@ msgstr "" "navigateur, capturez un clic, inspectez la demande et suivez le script " "d'exportation." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Observation du navigateur" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Copier démarrez l'exemple de navigateur" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Copier l'exemple d'invite" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Copier trouver la page" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Copie capture les dix prochaines secondes" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Copier lire les scripts chargés" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Aller au contenu" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Accueil{ph1} / Guides" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Guides d'utilisation REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4866,37 +4874,37 @@ msgstr "" "Analysez une fonction native, un export Electron ou une requête de " "navigateur. Chaque guide comprend une invite, un code et des résultats." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Première enquête" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Mettre en place REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Connectez votre agent de codage ou utilisez REA à partir du terminal." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Premiers pas avec REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Programmes en code machine" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Récupérer un calcul de la position du son gauche/droite" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4906,22 +4914,22 @@ msgstr "" "suivez un appelant, lisez les constantes numériques et vérifiez le C " "récupéré." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Guide d'analyse des programmes en code machine" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Suivre une exportation CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4931,14 +4939,14 @@ msgstr "" "de rendu, le préchargement et le processus principal. Utilisez REA pour " "connecter l'API, le canal IPC et le graveur de fichiers." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Guide des modèles JavaScript et Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4946,17 +4954,17 @@ msgstr "" "Pour une application packagée plus grande, suivez {ph0} Pont de presse-" "papiers de Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Comportement du navigateur" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Observez un clic" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4965,7 +4973,7 @@ msgstr "" "Ouvrez un exemple de notes de travail, capturez une demande d'exportation et" " recherchez le code qui transforme sa réponse en téléchargement." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Guide d'observation du navigateur" @@ -4984,12 +4992,12 @@ msgstr "" "Apprenez REA à travers de courts exemples travaillés: un calcul natif, un " "export Electron CSV et une requête de navigateur." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -4998,7 +5006,7 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" @@ -5006,13 +5014,13 @@ msgstr "" "{ph0}Accueil{ph1} / {ph2}Guides Touristiques{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Tracer un Electron{ph0}CSV exporter." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -5021,14 +5029,14 @@ msgstr "" "Suivez un clic de bouton depuis l'API de la page, via Electron IPC, vers le " "graveur de fichiers CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "Dans ce guide" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -5036,7 +5044,7 @@ msgstr "{ph0}L'exemple{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5044,7 +5052,7 @@ msgstr "{ph0}Demandez à votre agent{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5052,7 +5060,7 @@ msgstr "{ph0}Tracer le code d'exportation{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5060,20 +5068,20 @@ msgstr "{ph0}Essayez l'exemple{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Inspectez le graveur CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Où va “Exporter les notes\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5085,7 +5093,7 @@ msgstr "" "des notes{ph1} appelle une API dans la page, traverse le processus principal" " et écrit un CSV . Le comportement est réparti sur plusieurs fichiers." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "L'exportation de CSV à travers les processus Electron" @@ -5099,7 +5107,7 @@ msgstr "L'exportation de CSV à travers les processus Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5116,7 +5124,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5133,7 +5141,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5146,13 +5154,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} formate les notes → {ph1} écrit {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5163,14 +5171,14 @@ msgstr "" "l'API exposée. Le chemin est déduit du code; une capture d'exécution peut " "vérifier ce qui s'exécute." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Renseignez - vous sur l'exportation CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5188,14 +5196,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Copier" @@ -5206,7 +5214,7 @@ msgstr "Copier" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5217,7 +5225,7 @@ msgstr "" "des notes dans cette application. Où est créé le CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5227,7 +5235,7 @@ msgstr "" "Exemple d'invite. Inclure le chemin absolu vers le dossier de l'application " "ou {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5238,17 +5246,17 @@ msgstr "" "d'entrée, des modules et des limites de processus. Votre agent utilise cette" " carte pour restreindre l'enquête à la fonction d'exportation." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Tracer le code d'exportation" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "La page appelle une petite API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5259,7 +5267,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5271,7 +5279,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5282,7 +5290,7 @@ msgstr "" "notes et le processus principal écrit {ph1} dans le dossier Téléchargements " "de l'utilisateur." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5292,7 +5300,7 @@ msgstr "" "emplacements sources accompagnent les résultats de l'API, du canal et du " "gestionnaire." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Analysez l'exemple vous-même" @@ -5300,25 +5308,25 @@ msgstr "Analysez l'exemple vous-même" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Télécharger un exemple de ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Parcourez les six fichiers sources" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Analyse statique des applications" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5329,7 +5337,7 @@ msgstr "" "trouver un canal IPC et un gestionnaire correspondant dans {ph0}. Les " "emplacements sources sont en {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5340,13 +5348,13 @@ msgstr "" " ou son chemin ASAR. Un agent peut suivre une chaîne littérale, un nom d'API" " ou un canal IPC avec les outils de traçage des fonctionnalités de REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Inspectez le graveur CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5356,7 +5364,7 @@ msgstr "" "Suivre {ph0} à son gestionnaire. Quelles entrées atteignent le graveur CSV " "et que se passe-t-il si l'écriture du fichier échoue?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5371,7 +5379,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5385,7 +5393,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5399,7 +5407,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5425,32 +5433,32 @@ msgstr "" "et un gestionnaire IPC avec REA . Inclut des fichiers d'exemple " "téléchargeables et un résultat d'analyse vérifié." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Copier l'exemple d'invite" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Copie de l'analyse statique des applications" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -5459,7 +5467,7 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5468,14 +5476,14 @@ msgstr "" " code machine" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "" "Récupérez les DX-Ball{ph0}calcul de la position sonore gauche / droite." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5484,14 +5492,14 @@ msgstr "" "Inspectez les instructions d'origine, identifiez l'entrée et les constantes," " puis vérifiez le C récupéré." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "Dans ce guide" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5499,7 +5507,7 @@ msgstr "{ph0}L'exemple{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5507,7 +5515,7 @@ msgstr "{ph0}Demandez à votre agent{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5515,7 +5523,7 @@ msgstr "{ph0}Lire les résultats du REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5523,18 +5531,18 @@ msgstr "{ph0}Récupérer et vérifier{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Utilisez votre propre binaire{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Calculer le positionnement du son stéréo gauche/droite" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5545,7 +5553,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5557,7 +5565,7 @@ msgstr "" "appel à {ph1}. REA renvoie également ses instructions et ses appelants, ce " "qui donne à l'agent un moyen d'enquêter sur l'arithmétique manquante." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Nouveau dans ces conditions?" @@ -5566,7 +5574,7 @@ msgstr "Nouveau dans ces conditions?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5578,7 +5586,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5591,7 +5599,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5604,7 +5612,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5616,7 +5624,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5626,7 +5634,7 @@ msgstr "" "{ph0}Constantes:{ph1} nombres fixes stockés dans le programme, lus sous " "forme d'octets bruts et décodés." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Trois éléments de preuve, un calcul" @@ -5637,7 +5645,7 @@ msgstr "Trois éléments de preuve, un calcul" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5655,7 +5663,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5673,7 +5681,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5683,7 +5691,7 @@ msgstr "" "{ph0}03 * Octets de données{ph1}{ph2}Les constantes numériques{ph3}{ph4}Les " "octets référencés décodent en {ph5}, {ph6} et une valeur d'échelle.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5692,7 +5700,7 @@ msgstr "" "REA fournit les instructions, la relation fonction-appel et les octets. " "L'agent les interprète ensemble." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Renseignez-vous sur le comportement" @@ -5701,7 +5709,7 @@ msgstr "Renseignez-vous sur le comportement" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5712,19 +5720,19 @@ msgstr "" "outil d'analyse des programmes en code machine{ph3}, fournir l'exécutable " "local et une question:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Quel outil d'analyse dois-je utiliser?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA a besoin de l'un d'entre eux pour lire des programmes natifs:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5738,7 +5746,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5751,7 +5759,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5762,7 +5770,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5778,14 +5786,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Copier" @@ -5796,7 +5804,7 @@ msgstr "Copier" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5807,7 +5815,7 @@ msgstr "" "positionnement du son stéréo. Expliquez le calcul et montrez le " "code.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5819,7 +5827,7 @@ msgstr "" "copie ou posez le même genre de question à propos d'un autre petit programme" " Windows que vous avez." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Comment puis-je obtenir le chemin complet d'un fichier?" @@ -5828,7 +5836,7 @@ msgstr "Comment puis-je obtenir le chemin complet d'un fichier?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5844,7 +5852,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5857,7 +5865,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5867,17 +5875,17 @@ msgstr "" "{ph0}Tout système:{ph1} faites glisser le fichier dans une fenêtre de " "terminal et son chemin apparaît." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Lire les résultats du REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Lire l'entrée" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5887,13 +5895,13 @@ msgstr "" "arithmétique à virgule flottante. C'est l'entrée absente de la première vue " "pseudocode." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Suivez l'appelant" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5904,12 +5912,12 @@ msgstr "" "multiplient la coordonnée de la tuile par 30; en ajoutant {ph0} (20) donne " "la position de l'écran de la brique." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Lire les constantes référencées" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5919,12 +5927,12 @@ msgstr "" "les valeurs réelles; l'ordre des instructions indique à l'agent comment " "elles sont utilisées." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Écrivez et vérifiez la fonction récupérée" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5935,7 +5943,7 @@ msgstr "" " -500, 0 et 500 avant la conversion d'entiers. Le calcul place le centre de " "l'écran au centre du champ stéréo." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5948,20 +5956,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Voir l'enquête complète et la comparaison assemblage-C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Essayez-le avec votre propre binaire" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5975,7 +5983,7 @@ msgstr "" "fonctionnalité à étudier. Les questions de départ utiles incluent “Comment " "ce fichier est-il analysé?“ou \" Quelle fonction gère cette action de menu?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5984,13 +5992,13 @@ msgstr "" "Si vous connaissez déjà un nom ou une adresse de fonction, vous pouvez " "l'interroger à partir du terminal. Pour une installation Ghidra configurée:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Analyse de fonction" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -6004,7 +6012,7 @@ msgstr "" "session. Les requêtes MCP de votre agent réutilisent le binaire importé " "pendant que cette session est ouverte." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -6028,50 +6036,50 @@ msgstr "" "Récupérez un calcul natif avec REA: inspectez les instructions, suivez un " "appelant, lisez les constantes et vérifiez le C reconstruit." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Analyse de programmes en code machine" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Copier l'exemple d'invite" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Analyse de la fonction de copie" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Aller au contenu" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Mettre en place REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6079,7 +6087,7 @@ msgstr "{ph0}Mettre en place REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6087,7 +6095,7 @@ msgstr "{ph0}Qu'est-ce que RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6095,7 +6103,7 @@ msgstr "{ph0}Comment REA vous aide{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6103,7 +6111,7 @@ msgstr "{ph0}Jeu de dinosaure{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6111,7 +6119,7 @@ msgstr "{ph0}Calculatrice{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6119,7 +6127,7 @@ msgstr "{ph0}Essayez le modèle REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6127,7 +6135,7 @@ msgstr "{ph0}Aller plus loin{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6135,25 +6143,25 @@ msgstr "{ph0}Aide et commentaires{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Communauté{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Ingénierie inverse, avec votre agent de codage" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Découvrez comment{ph0}fonctionne un logiciel." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6164,7 +6172,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6172,13 +6180,13 @@ msgstr "Vous connaissez déjà RE? {ph0}Passer aux guides d'analyse →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Vous voulez aller plus loin? {ph0}Lire le Blog →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Copiez ce prompt dans votre agent de programmation :" @@ -6191,39 +6199,39 @@ msgstr "Copiez ce prompt dans votre agent de programmation :" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Copier" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Ou exécutez cette commande dans le terminal :" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "" "Vérifiez et approuvez les changements prévus, puis redémarrez votre agent." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Qu’est-ce que la rétro-ingénierie ?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6238,7 +6246,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6250,7 +6258,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6258,7 +6266,7 @@ msgstr "Avant REA · Vous enquêtez {ph0}vous-même{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6266,7 +6274,7 @@ msgstr "{ph0}01{ph1} Décoder les branches" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6274,7 +6282,7 @@ msgstr "{ph0}02{ph1} Tracer les appels" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6284,20 +6292,20 @@ msgstr "{ph0}03{ph1} Récupérer la règle" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Instructions d'origine x64 · sélectionnées{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * Quelle branche?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6307,29 +6315,29 @@ msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Deux sauts au même endroit. De quels opérateurs " "s'agit-il?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Recherchez les identifiants de commande, puis étiquetez la branche." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Diviser ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Multiplier ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Que font les fonctions appelées ?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6339,24 +6347,24 @@ msgstr "" "\"100 est clair. Les appels ne sont que des adresses. {ph0}Lequel divise? " "Quelle valeur entre?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Inspectez les fonctions d'assistance et tracez les valeurs stockées." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Diviser" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * Quelle est la règle?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6366,19 +6374,19 @@ msgstr "" "\"Ce chemin se multiplie par l'autre entrée. Donc {ph0}10% signifie 10% de " "200{ph1} après +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Nommez les opérandes et vérifiez les deux chemins d'opérateur." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Raisonnement d'expert illustratif" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6390,20 +6398,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Avec REA · Vous demandez à {ph0}votre agent{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Un seul prompt." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6417,21 +6425,21 @@ msgstr "Posez votre question à l’agent {ph0}avec des mots simples.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Exemple d'invite * Calculatrice" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Exemple de réponse · basé sur les résultats" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6439,22 +6447,22 @@ msgid "" msgstr "" "Après +, le bouton % prend {ph0}un pourcentage du premier nombre.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA fournit" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Les instructions du gestionnaire, le code décompilé et les appels." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Votre agent explique" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "" @@ -6462,7 +6470,7 @@ msgstr "" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6475,7 +6483,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6485,37 +6493,37 @@ msgstr "" "{ph0}Essayons deux exemples.{ph1} Modifiez la vitesse d'un jeu, puis revenez" " à la calculatrice et reconstruisez son bouton%." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Exemple 01 * Jeu de dinosaures de Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Pourquoi le dinosaure accélère-t-il ?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Objectif" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Reconstruisez le jeu avec {ph0}vitesse réglable.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Pourquoi faire de l'ingénierie inverse?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6526,49 +6534,49 @@ msgstr "" "course{ph1}: à quelle vitesse il démarre, combien il augmente et quand il " "s'arrête." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Jouer à la reconstruction" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Jouer" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Sauter ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Recommencer" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Vitesse" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Utilisez la règle d'accélération récupérée" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Règle d'origine: commencez à 6, puis augmentez vers 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Déplacez le curseur pour définir votre propre vitesse. L'espace ou le saut " "efface un cactus." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6577,14 +6585,14 @@ msgstr "" "Activez JavaScript pour lire la reconstruction. Le code et l'explication ci-" "dessus restent lisibles." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA a renvoyé" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6603,7 +6611,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6616,7 +6624,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6630,7 +6638,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6644,7 +6652,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6654,12 +6662,12 @@ msgstr "" "{ph0}Commencez à 6 heures.{ph1} Ajouter {ph2}0.001{ph3} chaque mise à jour " "sans collision, alors que la vitesse est inférieure {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Ouvrir le laboratoire de vitesse →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Ce que fait chaque partie" @@ -6670,7 +6678,7 @@ msgstr "Ce que fait chaque partie" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6687,7 +6695,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6704,7 +6712,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6714,13 +6722,13 @@ msgstr "" "{ph0}03 * Vous{ph1}{ph2}Changez la vitesse et jouez{ph3}{ph4}Essayez " "l'accélération d'origine, puis choisissez votre propre rythme.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Voir le script, les vérifications et comment essayer l'analyse" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6731,7 +6739,7 @@ msgstr "" "locale et a renvoyé le fichier chargé {ph0}, y compris sa source et son " "résumé." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6745,7 +6753,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6762,7 +6770,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6780,7 +6788,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6789,19 +6797,19 @@ msgstr "" "{ph0}Code de vitesse inspecté{ph1} · {ph2} Auteurs de Chromium * Licence " "BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Exemple 02 · Windows Calculatrice" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Recréez le bouton % de la calculatrice." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6812,7 +6820,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6823,29 +6831,29 @@ msgstr "" "inspectons l'application installée pour trouver à quel numéro le pourcentage" " est appliqué." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Essayez le calcul" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Réinitialiser" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% de 200 = 20. Alors 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Illustration interactive de la règle du pourcentage inspecté." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6857,7 +6865,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6871,7 +6879,7 @@ msgstr "Pour cet exemple, {ph0} et {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6887,7 +6895,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6899,7 +6907,7 @@ msgstr "" "Windows. Récupérez les règles après + et×, puis créez une petite " "calculatrice qui utilise les deux.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Avec +" @@ -6907,13 +6915,13 @@ msgstr "Avec +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Prenez 10% du premier nombre.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Avec ×" @@ -6921,13 +6929,13 @@ msgstr "Avec ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Transformez 10% en 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "De l'application installée à un bouton % fonctionnel" @@ -6939,7 +6947,7 @@ msgstr "De l'application installée à un bouton % fonctionnel" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6957,7 +6965,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6969,12 +6977,12 @@ msgstr "" "règles{ph3}{ph4}Vérifiez la branche avec la source de Microsoft, puis " "essayez + et × ci-dessus.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Voir le vrai code et comment la réponse a été vérifiée" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6995,7 +7003,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7005,17 +7013,17 @@ msgstr "" "{ph0}Pourcentage de mise en œuvre{ph1} · {ph2}Scénarios de test de " "Microsoft{ph3} · {ph4}Guide de configuration natif{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Votre première enquête" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Essayez REA sur une petite application." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -7024,12 +7032,12 @@ msgstr "" "Téléchargez notre exemple de Notes, tracez son exportation CSV et vérifiez " "une entrée modifiée." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Essayez l'exemple guidé" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Vous voulez aller plus loin ?" @@ -7038,7 +7046,7 @@ msgstr "Vous voulez aller plus loin ?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7059,13 +7067,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Exemple d'invite * Site Web" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Oui, celui-ci." @@ -7078,7 +7086,7 @@ msgstr "Oui, celui-ci." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7093,7 +7101,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7107,24 +7115,24 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Voir l'étude de cas DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "" "Pour les étapes de configuration et d'analyse, choisissez votre cible:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Programmes en code machine" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7133,17 +7141,17 @@ msgstr "" "Inspectez les fonctions, les chaînes, les références et les relations " "d'appel de fonction dans les exécutables et les bibliothèques." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Guide d'analyse des programmes en code machine" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7152,17 +7160,17 @@ msgstr "" "Mappez les modules, les routes, l'IPC et les dépendances natives à partir " "d'un dossier d'application ou d'une archive ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Flux de travail des applications" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Activité du navigateur et de l'exécution" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7171,12 +7179,12 @@ msgstr "" "Capturez l'activité du navigateur ou du processus sélectionné, puis comparez" " les résultats entre les exécutions." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Guide d'observation du navigateur" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Des questions ?" @@ -7187,7 +7195,7 @@ msgstr "Des questions ?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7198,12 +7206,12 @@ msgstr "" "{ph4}ouvrir un problème GitHub{ph5} pour les bugs et les demandes de " "fonctionnalités." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Rejoindre la communauté" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7227,27 +7235,27 @@ msgstr "" "navigateur avec votre agent de codage. Suivez des guides clairs et essayez " "des exemples interactifs avec REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Copier l'invite d'installation de REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Commande Copier le programme d'installation" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Suivez l'analyse manuelle de la calculatrice" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Question sur le pourcentage de la calculatrice de copie" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7256,37 +7264,37 @@ msgstr "" "Mini-jeu de dinosaure. Utilisez le bouton de saut ou appuyez sur Espace " "pendant que le jeu est concentré." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copie de l'invite d'analyse des dinosaures" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Choisissez le calcul" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Invite d'analyse de la calculatrice de copie" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Copier l'invite de projet de site Web" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Copie de l'invite de reconstruction du jeu" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -7295,26 +7303,26 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Accueil{ph1} / {ph2}Vitrines{ph3} / Androïde" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Étude de cas · Authentificateur Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "" "Comment fonctionne un authentificateur{ph0}générer un code de connexion?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7324,17 +7332,17 @@ msgstr "" "trouver le calcul dans un Android APK , puis reconstruisez-le avec une " "horloge que vous pouvez contrôler." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 · Android * Version officielle APK · 6,9 Mo" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Voir le modèle Aegis sur le modèle GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "D'un APK à un code que vous pouvez reproduire" @@ -7345,7 +7353,7 @@ msgstr "D'un APK à un code que vous pouvez reproduire" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7363,7 +7371,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7381,7 +7389,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7393,14 +7401,14 @@ msgstr "" "code.{ph3}{ph4}Une nouvelle démo de navigateur reproduit la règle et la " "compare à des cas de référence publics.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "Dans cette étude de cas" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7408,7 +7416,7 @@ msgstr "{ph0}Demandez à votre agent{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7416,7 +7424,7 @@ msgstr "{ph0}Essayez le générateur de code{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7424,7 +7432,7 @@ msgstr "{ph0}Trouver le code avec REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7432,7 +7440,7 @@ msgstr "{ph0}Lire le calcul{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7440,20 +7448,20 @@ msgstr "{ph0}Vérifiez la reconstruction{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Inspectez vous-même le APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Demandez à votre agent" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7471,21 +7479,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Copier" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7495,14 +7503,14 @@ msgstr "" "Un exemple d'invite pour le APK téléchargé, avec l'analyse Android de REA " "configurée. {ph0}Obtenez le APK et la configuration de l'analyse ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Essayez le générateur de code" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7514,33 +7522,33 @@ msgstr "" "combine le numéro de bloc avec la clé de compte pour générer un code. La " "même clé et le même bloc produisent le même code." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Déplacez l'horloge sur 60 secondes" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Temps" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "secondes" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Notre horloge d'exemple réglable" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "bloc de 30 secondes" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Bloquer" @@ -7549,35 +7557,35 @@ msgstr "Bloquer" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 secondes{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Code généré" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Clé de compte + bloc → six chiffres" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Exemple de temps, en secondes" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 secondes" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 secondes" @@ -7586,7 +7594,7 @@ msgstr "60 secondes" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7598,7 +7606,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7608,7 +7616,7 @@ msgstr "" "La clé est fixe, publique {ph0}Données de test RFC 6238{ph1}. La démo " "implémente le calcul récupéré à partir du APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7617,18 +7625,18 @@ msgstr "" "Le diagramme montre le résultat à 59 secondes. Activez JavaScript pour " "changer l'horloge." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Trouver le code avec REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Limitez le APK à trois classes" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7639,14 +7647,14 @@ msgstr "" "progression et les comptes importés. TOTP signifie un mot de passe à usage " "unique basé sur le temps." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Connectez le générateur à l'écran de l'application" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7657,7 +7665,7 @@ msgstr "" "méthode de base. Inspection {ph0} puis affiche l'appel d'affichage {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7667,14 +7675,14 @@ msgstr "" "Les requêtes affichent un chemin d'entrée raccourci. Les noms de classe de " "résultat omettent le commun {ph0} préfixe." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Lire le calcul" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7689,7 +7697,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7697,7 +7705,7 @@ msgstr "{ph0}01{ph1} Bloc de temps" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7705,7 +7713,7 @@ msgstr "{ph0}02{ph1} Clé + bloc" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7713,7 +7721,7 @@ msgstr "{ph0}03{ph1} Six chiffres" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7725,7 +7733,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7739,7 +7747,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7754,7 +7762,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7765,7 +7773,7 @@ msgstr "" "l'affichage. Le panneau de droite est un résumé explicatif. {ph0} Le code " "Aegis est sous licence GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "À l'intérieur du générateur" @@ -7774,7 +7782,7 @@ msgstr "À l'intérieur du générateur" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7784,7 +7792,7 @@ msgstr "" "Les mises APK publiées {ph0} dans {ph1}. REA suit l'appel de {ph2} et " "renvoie ce corps; la source d'origine appelle l'assistant {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7801,20 +7809,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Comparer avec la source de publication correspondante{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Vérifiez la reconstruction" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7827,29 +7835,29 @@ msgstr "" "indépendante sur {ph0}133 cas de test{ph1}, y compris les limites des blocs " "de temps et les codes commençant par zéro." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Exemple de temps" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Code à six chiffres" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 secondes" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1 111 111 109 secondes" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7860,17 +7868,17 @@ msgstr "" "dans {ph0}Référence RFC 6238{ph1}. Vérifiez l'implémentation du navigateur " "par rapport à eux:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Exécuter des vérifications des références" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Lire le calcul de la démo" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7879,7 +7887,7 @@ msgstr "" "Les cas de référence utilisent huit chiffres. La vérification vérifie " "également leurs résultats à six chiffres." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7888,14 +7896,14 @@ msgstr "" "La vérification exécute les méthodes Java extraites et la nouvelle démo. " "L'Android APK a été inspecté statiquement." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Inspectez vous-même le APK" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7908,7 +7916,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7918,18 +7926,18 @@ msgstr "" "L'analyse Android nécessite un JDK 17 complet ou une version ultérieure. " "Sélectionnez-le avec {ph0} ou {ph1}. Cette affaire utilisait JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Pointez REA sur le fichier fournisseur et inspectez le APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "Modèle: macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7942,7 +7950,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7952,7 +7960,7 @@ msgstr "" "Une question suivante: {ph0}que se passe-t-il lorsqu'un compte utilise huit " "chiffres ou un intervalle de temps différent?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Sources" @@ -7968,7 +7976,7 @@ msgstr "Sources" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7982,7 +7990,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" @@ -7990,7 +7998,7 @@ msgstr "" "{ph0}Cas de référence RFC 6238{ph1} · {ph2}Données de test de " "démonstration{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -8016,37 +8024,37 @@ msgstr "" "connexion à six chiffres et essayez une reconstruction avec une horloge " "réglable." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK étude de cas" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Copier l'invite d'exemple Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Suivez le calcul du code de connexion" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Copie de la commande d'inspection APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -8055,26 +8063,26 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Accueil{ph1} / {ph2}Vitrines{ph3} / FCT" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Étude de cas * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Trouvez le drapeau dans{ph0}un binaire CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8085,17 +8093,17 @@ msgstr "" " ses règles en équations et trouver une entrée qui fait imprimer le " "programme d'origine {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "vérificateur de drapeau carrés masqués * Facile * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Voir le défi original" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "D'une réponse binaire à une réponse vérifiée" @@ -8106,7 +8114,7 @@ msgstr "D'une réponse binaire à une réponse vérifiée" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8124,7 +8132,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8142,7 +8150,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8154,21 +8162,21 @@ msgstr "" "Correct!{ph3}{ph4}Un script Python résout les équations. REA capture le " "programme d'origine acceptant le résultat.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" "Le défi est de joseph, publié dans le référentiel officiel de DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "Dans cette étude de cas" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8176,7 +8184,7 @@ msgstr "{ph0}Trouver le code de vérification{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8184,7 +8192,7 @@ msgstr "{ph0}Lire un masque{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8192,7 +8200,7 @@ msgstr "{ph0}Assemblage en code lisible{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8200,7 +8208,7 @@ msgstr "{ph0}Résoudre les équations{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8208,20 +8216,20 @@ msgstr "{ph0}Vérifiez la réponse{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Essayez-le vous-même{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Trouver le code de vérification" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8239,17 +8247,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Copier" @@ -8260,7 +8268,7 @@ msgstr "Copier" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8272,7 +8280,7 @@ msgstr "" "l'indicateur. Expliquez le fonctionnement des vérifications, puis vérifiez " "la réponse avec le programme d'origine.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8281,12 +8289,12 @@ msgstr "" "Un exemple d'invite, avec le défi téléchargé disponible localement et une " "analyse du fournisseur de programmes en code machine connecté." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Suivez l'invite de saisie jusqu'à sa fonction" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8295,14 +8303,14 @@ msgstr "" "La référence donne à l'agent un endroit pour enquêter, même si les noms de " "fonctions d'origine de l'exécutable ont été supprimés." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Lire le vérificateur et ses deux aides" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8315,7 +8323,7 @@ msgstr "" "avec un nombre stocké. Ses {ph0}- étapes d'octets à travers {ph1} les octets" " donnent 26 masques." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8325,12 +8333,12 @@ msgstr "" "chemin cible local est raccourci pour l'affichage; les adresses se réfèrent " "à l'image importée de REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Un chèque révèle un caractère" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8344,7 +8352,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." @@ -8352,7 +8360,7 @@ msgstr "" "La septième vérification sélectionne une seule position. {ph0}Figure " "ouverte{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Lire le masque et sa cible à partir du binaire" @@ -8361,7 +8369,7 @@ msgstr "Lire le masque et sa cible à partir du binaire" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8374,12 +8382,12 @@ msgstr "" "Ensemble, ces octets indiquent à l'agent que {ph2}, donc ce personnage est " "{ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Des instructions à un chèque lisible" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8390,7 +8398,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8398,7 +8406,7 @@ msgstr "{ph0}01{ph1} Démarrer" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8406,7 +8414,7 @@ msgstr "{ph0}02{ph1} Sélectionner" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8414,7 +8422,7 @@ msgstr "{ph0}03{ph1} Ajouter" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8422,18 +8430,18 @@ msgstr "{ph0}04{ph1} Avance" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Comparer" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * instructions d'origine sélectionnées" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Résumé lisible de C * one-check" @@ -8441,7 +8449,7 @@ msgstr "Résumé lisible de C * one-check" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8449,7 +8457,7 @@ msgstr "{ph0}01 * Commencez à zéro.{ph1} {ph2} détient la somme courante." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8461,7 +8469,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8473,7 +8481,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8487,7 +8495,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8497,7 +8505,7 @@ msgstr "" "{ph0}05 * Comparer avec la cible stockée.{ph1} L'appelant reçoit la somme en" " {ph2}. Un décalage saute à {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8507,12 +8515,12 @@ msgstr "" " Le C est un résumé explicatif avec des noms descriptifs et une boucle " "aplatie de 36 cellules." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Résoudre les 26 équations" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8524,13 +8532,13 @@ msgstr "" " 1441. Les sélections qui se chevauchent donnent des équations qu'un petit " "script Python peut résoudre ensemble." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Extrait du solveur Python ·" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8544,19 +8552,19 @@ msgstr "" "avec des lettres, des chiffres, des traits de soulignement et des accolades." " Le téléchargement complet comprend les 26 masques et cibles." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Télécharger le solveur complet" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Vérifiez la réponse avec le programme d'origine" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8569,47 +8577,47 @@ msgstr "" "{ph1} fait la première somme 1440 au lieu de 1441, et le programme la " "rejette." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Entrée" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Production observée" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Code de sortie" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Drapeau du solveur" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Un personnage a changé" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Afficher l'indicateur récupéré et la sortie capturée" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * sortie du programme d'origine" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Copier l'indicateur" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8619,12 +8627,12 @@ msgstr "" "défi publiées par les organisateurs, vérifiées après la résolution du " "binaire." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Détails de la source, de l'identité de la cible et de l'analyse" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8635,7 +8643,7 @@ msgstr "" "utilisant REA 4.1.0 avec Ghidra 12.1.4 sur Linux x64. Le binaire est un ELF " "x86-64 dépouillé, 15 248 octets." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8658,7 +8666,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8668,12 +8676,12 @@ msgstr "" "{ph0}Comparez avec la source des organisateurs{ph1} · {ph2}Contester les " "métadonnées et l'indicateur{ph3} · {ph4}REA notes de preuve{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Essayez-le vous-même" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8683,13 +8691,13 @@ msgstr "" "l'invite ci-dessus pour enquêter avec votre agent ou exécutez le script " "inclus." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * résoudre et exécuter" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8701,7 +8709,7 @@ msgstr "" " résolution des besoins Python et {ph0}. L'exécution de l'exécutable " "d'origine nécessite Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Configurez REA avec votre agent de codage" @@ -8722,29 +8730,29 @@ msgstr "" " DownUnderCTF. Retrouvez les fonctions de vérification, extrayez les masques" " et comparez un drapeau récupéré avec le programme d'origine." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Étude de cas sur le vérificateur de drapeau de la FCT" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Copier l'invite d'exemple CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "" "Équation du masque CTF; faites défiler horizontalement sur des écrans plus " "petits" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8755,42 +8763,42 @@ msgstr "" " 14. Seule cette cellule contribue à la somme. Son code de caractère requis " "est 55, ce qui signifie que le caractère est 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Suivez la vérification du FCT" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Copier l'assemblage de la FCT" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Copier le chèque CTF lisible" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Copier l'extrait du solveur CTF" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Copier l'indicateur récupéré" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Copier les commandes du solveur CTF" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -8799,25 +8807,25 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Accueil{ph1} / {ph2}Vitrines{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Étude de cas * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Reconstruction DX-Ball{ph0}de son exécutable." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8826,14 +8834,14 @@ msgstr "" "L'objectif est une version C maintenable du jeu Windows de 1996. REA aide " "l'agent à inspecter l'original, une fonction à la fois." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 · D · REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8845,14 +8853,14 @@ msgstr "" "les appelants et les lectures de données; le projet de reconstruction " "implémente et teste le résultat. {ph0}Figure ouverte{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "Dans cette étude de cas" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8860,7 +8868,7 @@ msgstr "{ph0}Le projet{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8868,7 +8876,7 @@ msgstr "{ph0}Panoramique sonore{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8876,23 +8884,23 @@ msgstr "{ph0}Vérification du résultat{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Continuer le travail{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "fonctions C maintenues" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "comparaisons avec le code d'origine" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "fonctions avec octets compilés correspondants" @@ -8903,7 +8911,7 @@ msgstr "fonctions avec octets compilés correspondants" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8913,12 +8921,12 @@ msgstr "" "Point de contrôle du projet: 7 octobre 2026. {ph0}Registre de " "progression{ph1} · {ph2}Couverture des tests{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Le projet à ce jour" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8934,12 +8942,12 @@ msgstr "" "physique de la balle et de la pagaie, la manipulation de la mise sous " "tension et l'intégration de Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Trouver le calcul de la position sonore gauche / droite" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8958,17 +8966,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Copier" @@ -8979,7 +8987,7 @@ msgstr "Copier" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8990,7 +8998,7 @@ msgstr "" "positionnement du son stéréo. Expliquez le calcul et montrez le " "code.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -9001,7 +9009,7 @@ msgstr "" "disponible. L'enquête ci-dessous montre les requêtes REA et les preuves " "derrière la réponse." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -9015,7 +9023,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9029,12 +9037,12 @@ msgstr "" "pile et des opérations en virgule flottante. Cet écart a donné à l'agent une" " raison concrète de continuer à enquêter." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "La première vue du décompilateur" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -9043,18 +9051,18 @@ msgstr "" "La sortie affiche un appel de conversion. La lecture des instructions ci-" "dessous révèle l'entrée et le calcul alimentant cet appel." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Réponses à trois questions via REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Récupérer l'entrée manquante" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9065,14 +9073,14 @@ msgstr "" "des appelants. Ici, {ph0} expose l'entrée entière manquante dans la vue du " "décompilateur." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Suivez l'appelant pour comprendre l'entrée" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9083,12 +9091,12 @@ msgstr "" "d'instructions précédente {ph0} par 30; l'ajout de 20 donne les coordonnées " "de l'écran de la brique, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Lire les valeurs derrière les adresses mémoire" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9098,12 +9106,12 @@ msgstr "" "l'échelle panoramique initiale. L'agent a maintenant les valeurs nécessaires" " pour l'expression C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Des découvertes de REA à C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9114,7 +9122,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9122,7 +9130,7 @@ msgstr "{ph0}01{ph1} Entrée" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9130,7 +9138,7 @@ msgstr "{ph0}02{ph1} Multiplier" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9138,7 +9146,7 @@ msgstr "{ph0}03{ph1} Soustraire" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9146,18 +9154,18 @@ msgstr "{ph0}04{ph1} Échelle" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Retour" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Extrait original x86 ·" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "C Reconstruit" @@ -9167,7 +9175,7 @@ msgstr "C Reconstruit" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9187,7 +9195,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9204,7 +9212,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9222,7 +9230,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9239,7 +9247,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9251,7 +9259,7 @@ msgstr "" "dans les résultats de l'appelé de REA. Le C convertit le résultat en {ph4}; " "les comparaisons originales-x86 vérifient la valeur renvoyée." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9262,23 +9270,23 @@ msgstr "" " et de retour. La liste complète ci-dessous comprend également les magasins " "intermédiaires et la configuration et le nettoyage des fonctions." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Assemblage complet et preuves à l'appui" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA résultat · 0x406400–0x40643f" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Ce que l'appelant fournit" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9288,54 +9296,54 @@ msgstr "" "La fonction de frappe de brique à {ph0} met à l'échelle sa coordonnée de " "tuile de 30, ajoute 20, puis la pousse avant l'appel:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Ce que les données lisent établissent" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA lectures d'octets, décodées en doubles little-endian" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Adresse" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Valeur" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Utilisé pour" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Première multiplication" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Soustraction" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} initialement" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Échelle de casserole stockée" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9351,7 +9359,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9361,12 +9369,12 @@ msgstr "" "{ph0}Source maintenue{ph1} · {ph2}Notes d'enquête et références des éléments" " de preuve{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Vérification de la fonction récupérée" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9376,12 +9384,12 @@ msgstr "" "correspondent à l'original et ses octets compilés correspondent à " "l'exécutable." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3 205 cas de comportement" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9392,12 +9400,12 @@ msgstr "" "retour avec le C maintenu. Ils couvrent chaque position entière de 0 à 640 à" " cinq échelles panoramiques: 0, 0,5, 1, 20 et -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 octets correspondants" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9409,7 +9417,7 @@ msgstr "" "appliqué les relocalisations examinées et vérifié les constantes " "référencées." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9424,18 +9432,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Lire les détails de la relecture du compilateur{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Poursuivre l'enquête" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9447,7 +9455,7 @@ msgstr "" "pertinentes, récupérez leur état et leurs dépendances, puis comparez " "l'implémentation avec l'original." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9457,7 +9465,7 @@ msgstr "" "configuration du projet DX-Ball et fournissez sa cible d'origine " "correspondante. Puis cours:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "Dans la caisse de DX-Ball" @@ -9466,7 +9474,7 @@ msgstr "Dans la caisse de DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9480,7 +9488,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9496,7 +9504,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9521,7 +9529,7 @@ msgstr "" "le C maintenu, les tests x86 d'origine et les octets de fonction compilés " "correspondants." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9529,7 +9537,7 @@ msgstr "" "DX-Ball étude panoramique du son; défilement horizontal sur des écrans plus " "petits" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9545,70 +9553,70 @@ msgstr "" "d'origine dans 3 205 cas et par relecture du compilateur VC4.0 correspondant" " à 63 octets." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Étude de cas sur la reconstruction du DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Copier l'exemple d'invite" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Suivez le calcul de la position sonore gauche / droite" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Copier l'extrait original de l'assemblage" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Fonction Copier le son-panoramique" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Copier l'assemblage complet du panoramique sonore" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Copier la commande d'analyse DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Aller au contenu" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Accueil{ph1} / Vitrines" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "Études de cas REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9617,17 +9625,17 @@ msgstr "" "Android, jeux, Electron et un défi CTF, avec code, chiffres et résultats " "vérifiés." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Pour Android · APK analyse" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Comment un authentificateur génère un code de connexion" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9638,22 +9646,22 @@ msgstr "" "Tracez les méthodes de génération avec REA, puis déplacez une horloge de " "démonstration pour voir pourquoi le code change toutes les 30 secondes." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Lire l'étude de cas Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Analyse des programmes en code machine" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Résoudre un vérificateur de drapeau CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9664,22 +9672,22 @@ msgstr "" " vérification, transformez les masques et les sommes en équations, puis " "vérifiez le drapeau résolu avec le programme d'origine." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Lire l'étude de cas de la FCT" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Reconstruction indigène ·" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "Calcul de la position sonore gauche/droite de DX-Ball" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9691,22 +9699,22 @@ msgstr "" "numériques de REA conduisent à une petite fonction C, vérifiée par rapport " "au comportement d'origine et aux 63 octets compilés." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Lire l'étude de cas DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Traçage des fonctionnalités" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Comment Notion copie du texte et du code HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9718,22 +9726,22 @@ msgstr "" "petit marqueur HTML maintient les données de bloc riches connectées à une " "copie." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Lire l'étude de cas Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 pour la reconstruction" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Comment TH04 vise un anneau de balles" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9744,17 +9752,17 @@ msgstr "" "opérations de multiplication, de division et de coordination à du C ++ " "lisible, puis voyez comment elles produisent un anneau destiné au joueur." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Lire l'étude de cas TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Guides étape par étape" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9763,7 +9771,7 @@ msgstr "" "Les guides parcourent un calcul natif, une exportation Electron et une " "requête de navigateur. Chacun commence par une invite et une cible concrète." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Lire les guides" @@ -9783,12 +9791,12 @@ msgstr "" "authentificateur Android, DX-Ball, Notion, TH04 et un vérificateur de " "drapeau DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -9797,25 +9805,25 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Accueil{ph1} / {ph2}Vitrines{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Étude de cas · Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Comment se copie Notion{ph0}texte et HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9825,12 +9833,12 @@ msgstr "" "préchargement et le processus principal, vers le rédacteur de presse-papiers" " de Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Bureau 7.6.1 · JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Le pont à l'intérieur du package de bureau de Notion" @@ -9842,7 +9850,7 @@ msgstr "Le pont à l'intérieur du package de bureau de Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9859,7 +9867,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9876,7 +9884,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9893,7 +9901,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9904,13 +9912,13 @@ msgstr "" "écrit le texte et le code HTML fournis.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Un canal relie les deux côtés: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9920,14 +9928,14 @@ msgstr "" "processus principal. La résolution des wrappers révèle les appels Electron " "derrière ces noms." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "Dans cette étude de cas" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9935,7 +9943,7 @@ msgstr "{ph0}Suivez le pont du presse-papiers{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9943,19 +9951,19 @@ msgstr "{ph0}Conserver la structure d'un bloc{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Plus d'exemples et de sources{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Où va l'opération de copie?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9975,17 +9983,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Copier" @@ -9996,7 +10004,7 @@ msgstr "Copier" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10007,7 +10015,7 @@ msgstr "" "et du code HTML dans le presse-papiers du système. Affichez le code à chaque" " étape.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -10016,12 +10024,12 @@ msgstr "" "Un exemple d'invite avec le package d'application local de Notion disponible" " pour votre agent de codage." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA trouve par où commencer la lecture" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -10032,13 +10040,13 @@ msgstr "" "page et l'appel qui envoie une requête IPC. Les deux résultats sont fournis " "avec des plages de sources dans le bundle minifié:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "Résultats REA → deux endroits pour ouvrir" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10052,7 +10060,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10066,12 +10074,12 @@ msgstr "" "donne à l'agent quelque chose de précis à rechercher dans le paquet " "principal. Les quatre extraits ci-dessous montrent l'itinéraire qu'il relie." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Quatre courts morceaux de code" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -10080,13 +10088,13 @@ msgstr "" "Simplifié à partir du JavaScript emballé, avec des noms de variables " "lisibles. Les membres non apparentés sont omis." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Commencez par l'API exposée à la page" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10096,13 +10104,13 @@ msgstr "" "Ce membre fournit le nom du canal. La mise en œuvre de {ph0} nous indique " "comment la demande quitte le processus de la page." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Résoudre le wrapper de la précharge" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10113,14 +10121,14 @@ msgstr "" "réponse de Electron. Nous pouvons maintenant chercher {ph0} du côté du " "processus principal." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Vérifiez comment le destinataire est enregistré" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10130,12 +10138,12 @@ msgstr "" "Le processus principal utilise un autre wrapper. Ses {ph0} la méthode " "enregistre un {ph1} récepteur pour ce canal." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Trouver l'écriture et sa vérification de l'expéditeur" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10147,13 +10155,13 @@ msgstr "" "canal et les deux wrappers résolus connectent la méthode exposée à cet " "appel." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Comment un bloc copié conserve-t-il sa structure?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10164,27 +10172,27 @@ msgstr "" "les données de bloc localement et place un identifiant dans le code HTML " "copié pour les connecter." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Liens HTML vers les données de bloc enregistrées" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Lire l'identifiant HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Trouver le même identifiant local" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Restaurer les données de bloc Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10194,7 +10202,7 @@ msgstr "" "données de bloc lorsque les identifiants correspondent; une entrée périmée " "ne renvoie que du texte et du HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10203,24 +10211,24 @@ msgstr "" "Lors du collage, Notion recherche l'ID HTML et le compare à la copie " "enregistrée. Les identifiants correspondants restaurent les données de bloc." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Format du presse-papiers enregistré à partir des ressources Web mises en " "cache le 13 juillet 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Plus d'exemples et de sources" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Un autre exemple: les tables de démarques" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10229,12 +10237,12 @@ msgstr "" "Notion analyse la démarque en données de bloc. Cet exemple montre comment " "une table devient des lignes d'en-tête et de données." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Un tableau via l'analyseur de démarque de Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10243,13 +10251,13 @@ msgstr "" "Sortie enregistrée à partir d'un analyseur Markdown extrait. Le tableau " "devient des lignes et des cellules." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Un autre chemin: la connexion SQLite hors ligne" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10263,7 +10271,7 @@ msgstr "" "l'autre à un processus utilitaire SQLite. Les lots de relevés suivants et " "les résultats transitent par ce port." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10273,7 +10281,7 @@ msgstr "" " pourquoi le suivi uniquement de la demande IPC initiale manque la " "conversation ultérieure." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Sources et comment lire les extraits" @@ -10281,7 +10289,7 @@ msgstr "Sources et comment lire les extraits" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10299,7 +10307,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10316,7 +10324,7 @@ msgstr "" "décrivent ces sondes plutôt qu'une session d'interface utilisateur de bureau" " capturée." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10331,7 +10339,7 @@ msgstr "" "wrapper dans le package." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10349,7 +10357,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10363,7 +10371,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10389,52 +10397,52 @@ msgstr "" "wrappers IPC et le processus principal de Electron, avec de courts extraits " "de code et un aperçu de son riche format de presse-papiers." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron étude de cas" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Copier l'invite d'analyse Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Copier l'extrait de préchargement Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Copier l'extrait d'enveloppe d'invocation Notion" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Copier l'extrait de wrapper du gestionnaire Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Copier l'extrait du récepteur du presse-papiers Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Restauration des données riches du presse-papiers sur coller" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Haut de page" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Aller au contenu" @@ -10443,25 +10451,25 @@ msgstr "Aller au contenu" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Accueil{ph1} / {ph2}Vitrines{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Étude de cas · Touhou 4: L'histoire de Lotus Land" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Reconstruction TH04's{ph0}motifs de balles." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10471,17 +10479,17 @@ msgstr "" "inspecter la fonction DOS d'origine, puis suivez ses instructions en C ++ " "lisible." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * DOS 16 bits * C++ et assemblage" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Voir le TH04 reconstruction" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Des instructions originales à la source vérifiée" @@ -10492,7 +10500,7 @@ msgstr "Des instructions originales à la source vérifiée" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10508,7 +10516,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10526,7 +10534,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10542,7 +10550,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10554,7 +10562,7 @@ msgstr "" "correspondants{ph3}{ph4}Les vérifications du compilateur enregistrées " "couvrent le code de génération de puces qui contient cette aide.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10563,14 +10571,14 @@ msgstr "" "REA renvoie le code d'origine et ses preuves d'analyse. Le projet TH04 " "fournit les vérifications de source et de compilateur maintenues." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "Dans cette étude de cas" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10578,7 +10586,7 @@ msgstr "{ph0}L'anneau de balle{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10586,7 +10594,7 @@ msgstr "{ph0}Quels sont les retours de REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10594,7 +10602,7 @@ msgstr "{ph0}Assemblage en C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10602,18 +10610,18 @@ msgstr "{ph0}Vérification de la source{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Le projet complet{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Comment un anneau vise le joueur" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10632,16 +10640,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Votre agent de codage" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Copier" @@ -10652,7 +10660,7 @@ msgstr "Copier" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10663,7 +10671,7 @@ msgstr "" "balles et le dirige vers le joueur. Expliquez le calcul et montrez le " "code.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10673,7 +10681,7 @@ msgstr "" "reconstruction disponibles localement." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10687,7 +10695,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10697,12 +10705,12 @@ msgstr "" "Une illustration des calculs d'angle récupérés pour le compte 16, la " "direction du joueur 40 et la rotation du gabarit 0. {ph0}Figure ouverte{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Le modèle de tir dans la source récupérée" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "L'attaque de l'anneau d'Elly * extrait de la source" @@ -10711,7 +10719,7 @@ msgstr "L'attaque de l'anneau d'Elly * extrait de la source" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10721,13 +10729,13 @@ msgstr "" "Ces lignes sélectionnent le motif avant le réglage de la difficulté et des " "performances. {ph0}Lire la source de l'attaque{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Quels sont les retours de REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10739,12 +10747,12 @@ msgstr "" "chaque balle. REA renvoie ses instructions, son pseudocode et ses " "références. Trois parties de ce résultat expliquent le schéma." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Vérifiez l'image DOS avant de lire son code" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10753,7 +10761,7 @@ msgstr "" "La vérification lie le code chargé et les enregistrements de relocalisation " "à l'exécutable fourni. Le chemin ci-dessus est raccourci pour l'affichage." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Lire la multiplication et la division de l'anneau" @@ -10761,7 +10769,7 @@ msgstr "Lire la multiplication et la division de l'anneau" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10773,12 +10781,12 @@ msgstr "" "division utilise le décompte lu à partir de {ph1}. Les noms de source " "conservés dans ce champ {ph2}. La séquence complète apparaît ci-dessous." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Trouvez où le motif se tourne vers le joueur" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10791,12 +10799,12 @@ msgstr "" " l'anneau. Les noms de source rendent ces adresses lisibles; REA permet à " "l'agent de vérifier les opérations d'origine derrière elles." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "De l'assemblage au C++lisible" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10810,7 +10818,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10818,7 +10826,7 @@ msgstr "{ph0}01{ph1} Indice" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10826,7 +10834,7 @@ msgstr "{ph0}02{ph1} Espace" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10834,7 +10842,7 @@ msgstr "{ph0}03{ph1} Objectif" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10842,18 +10850,18 @@ msgstr "{ph0}04{ph1} Tourner" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Magasin" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * instructions 16 bits d'origine" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Résumé lisible de l'anneau visé C++ ·" @@ -10861,7 +10869,7 @@ msgstr "Résumé lisible de l'anneau visé C++ ·" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10875,7 +10883,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10891,7 +10899,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10907,7 +10915,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10922,7 +10930,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10936,7 +10944,7 @@ msgstr "" "le cast d'octets non signés. La source environnante convertit également cet " "angle et cette vitesse en vitesse." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10948,7 +10956,7 @@ msgstr "" "vérifications du compilateur ci-dessous s'appliquent à la source maintenue " "dans le projet lié." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Lire l'anneau maintenu et la source de visée" @@ -10965,7 +10973,7 @@ msgstr "Lire l'anneau maintenu et la source de visée" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10975,12 +10983,12 @@ msgstr "" "{ph0}Macro d'anneau{ph1} · {ph2}Source de visée et de vélocité{ph3} · " "{ph4}Représentation angulaire{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Vérification de la source maintenue" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10990,12 +10998,12 @@ msgstr "" "génération de puces, y compris cet assistant, avec sa chaîne d'outils Turbo " "C++ 4.0 J épinglée." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2 139 octets correspondants" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -11004,12 +11012,12 @@ msgstr "" "Le code de génération de puces compilé correspond à une section de 2 139 " "octets de l'exécutable d'origine." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Deux constructions propres" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -11023,7 +11031,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." @@ -11031,59 +11039,59 @@ msgstr "" "Enregistré le 3 octobre 2026. {ph0}Lire les vérifications du " "compilateur{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Identité cible et portée de l'analyse" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Cible d'origine" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156 258 octets, sous-titres MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Entrée d'aide" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} dans l'image chargée de REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Décalage du fichier d'origine" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, retourné par {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Inspection du code enregistré" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 · 7 octobre 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11094,7 +11102,7 @@ msgstr "" " à la CARTE et sa relocalisation qui se chevauchent." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11110,7 +11118,7 @@ msgstr "" "rapportées." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11127,7 +11135,7 @@ msgstr "" " est épinglée par son manifeste de référentiel, avec une provenance de " "vidage vierge indépendante toujours ouverte." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11138,12 +11146,12 @@ msgstr "" "timing et le comportement du matériel PC-98 ont des vérifications " "d'exécution distinctes dans le projet de reconstruction." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "La reconstruction complète du TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11157,7 +11165,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11169,7 +11177,7 @@ msgstr "{ph0}Explorez le référentiel TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11185,7 +11193,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11201,7 +11209,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11227,22 +11235,22 @@ msgstr "" "l'assemblage et le C ++ récupéré pour voir comment un anneau de balles est " "espacé et dirigé vers le joueur." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Sur cette page" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 étude de cas de modèle de balle" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Copier l'invite d'exemple TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11250,7 +11258,7 @@ msgstr "" "TH04 anneaux de balle fixes et ciblés; faites défiler horizontalement sur " "des écrans plus petits" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11264,27 +11272,27 @@ msgstr "" " le joueur. Les deux conservent un espacement de 16 unités d'angle, soit " "22,5 degrés." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Copier le modèle de cuisson TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Suivez le calcul de la bague de visée TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Copier l'extrait d'assemblage TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Copier le calcul de l'anneau visé lisible" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Haut de page" @@ -11394,7 +11402,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Vitesse fixe: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11404,7 +11412,7 @@ msgstr "" "vérification contrôlée du jeu d'origine lorsqu'elles sont arrondies à trois " "décimales." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11774,591 +11782,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Même espacement: 256 ÷ 16 = 16 unités d'angle = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Études de cas" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Démarrer" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Guides" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Code source" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Licence MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Rejoindre la communauté" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Nous suivre sur X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * source de script sélectionnée" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Code source" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Sortie attendue du formateur" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Instructions" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Appelant" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Constantes" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Fonction C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Bouton" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API de préchargement" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "CIB" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV fichier" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Votre clic" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Demande capturée" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Exporter le script" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "Résultat de REA * résumé.extrait de la CIB" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "Extrait d'instruction REA · 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "Extrait de l'appelant REA · 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "Résultats d'octets REA * interprétés comme des doubles little-endian" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Extrait C · récupéré" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Voir comment fonctionne REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Vitrines →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Paramètres sélectionnés à partir du script inspecté" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Résumé lisible du gestionnaire %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * instructions d'origine sélectionnées" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Identifiants de l'opérateur * Source de Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Suivez @ reatools sur X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → agent · résultats sélectionnés" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → méthodes et appelants de l'agent ·" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * Java décompilé sélectionné" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Résumé lisible * interprétation de l'agent" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * Générez OTP, corps complet" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Télécharger Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Télécharger le fournisseur d'analyse Android" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → agent · résultats sélectionnés" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → agent * instructions sélectionnées" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agent → REA * lire_octets" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → agent * septième entrées" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Fichier exécutable d'origine * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Télécharger le défi original" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Télécharger le solveur" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA résultat * extrait de pseudocode" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → extrait d'instructions de l'agent ·" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → extrait de l'agent * appelant" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agent → REA * deux {ph0} demandes" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Résultats des octets REA * décodés en doubles" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Commencez par votre propre cible" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Génération de code" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Règle récupérée" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Horloge réglable" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Binaire" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Vérification du code" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Équations" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "C'est vrai!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Exécutable" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Résultats de la REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "C Récupéré" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Validation" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Application packagée" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "API exposée" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Enveloppes IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Presse-papiers" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Code de DOS d'origine" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Instructions pour le modèle REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Calcul de l'angle" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Anneau de balle" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "API de page exposée" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Appel IPC du moteur de rendu" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Envoyé au presse-papiers du système" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Enregistré localement par Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Entrée de démarque" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Sortie de l'analyseur structuré * extrait" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analysez votre propre application" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → agent * champs sélectionnés" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → extrait d'instructions de l'agent ·" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Même fonction résultat · extrait de but" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "C++maintenu correspondant" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Macro annulaire * Branche TH04, extrait" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Angle et vélocité · extrait de la source" @@ -12393,7 +12409,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12411,7 +12427,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12432,7 +12448,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12453,7 +12469,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12472,7 +12488,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12491,7 +12507,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12502,14 +12518,14 @@ msgstr "" "moi.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Reconstruction · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12520,7 +12536,7 @@ msgstr "" "agent de codage et examinez les modifications proposées." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12529,7 +12545,7 @@ msgstr "Un exemple fourni · {ph0} et npm · Votre agent de codage" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12548,7 +12564,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12564,7 +12580,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12583,7 +12599,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12594,7 +12610,7 @@ msgstr "" "formateur dans {ph7} et écrit le fichier.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12609,7 +12625,7 @@ msgstr "{ph0} * lignes 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12622,7 +12638,7 @@ msgstr "" "Afficher la prédiction et la sortie réelle.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12633,7 +12649,7 @@ msgstr "" "Cela vérifie le formateur directement avec {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12641,7 +12657,7 @@ msgstr "{ph0} · CSV formateur" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12651,7 +12667,7 @@ msgstr "" "est livré avec {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12659,7 +12675,7 @@ msgstr "Vous n'avez pas {ph0}, ou vous n'êtes pas sûr?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12672,7 +12688,7 @@ msgstr "" "installez {ph1} 24 LITRES:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12686,7 +12702,7 @@ msgstr "{ph0} * exemple d'extrait de source" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12697,9 +12713,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12707,7 +12723,7 @@ msgstr "{ph0} * exemple de source" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12722,7 +12738,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12735,7 +12751,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12750,7 +12766,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12761,7 +12777,7 @@ msgstr "" "Pourquoi {ph3} donne-t-il 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12770,7 +12786,7 @@ msgstr "REA * chargé {ph0} * lignes sélectionnées" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12788,7 +12804,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12807,7 +12823,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12820,28 +12836,28 @@ msgstr "" "secondes. Crée une petite démo où je peux modifier l’heure.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "affichage des onglets/{ph0} * Membre de l'API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "affichage des onglets/{ph0} * Assistant IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "principale/{ph0} * aide-manutentionnaire" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12851,12 +12867,1451 @@ msgstr "principale/{ph0} * récepteur de presse-papiers" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Démarrer {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Passer au mode clair" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Passer au mode sombre" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Pour examiner les corps des requêtes et réponses HTTP, utilisez {ph0}Fiddler" +" Everywhere : captures SAZ, MCP et compétences publiques{ph1}. Exportez en " +"SAZ ou HAR 1.2 pour obtenir des Evidence de capture dans REA hors ligne, ou " +"connectez le serveur MCP d’Everywhere pour inspecter le trafic capturé avec " +"votre agent." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Modèles spécialisés{ph0}Essai" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Le reverse engineering a-t-il besoin d’un modèle plus grand ?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Ce que la reconstruction de Touhou suggère sur les modèles généralistes, les" +" modèles spécialisés et l’apprentissage à partir des retours du compilateur." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Par N0zoM1z0 · 13 octobre 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Aller au contenu" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Accueil{ph1} / {ph2}Blog{ph3} / Modèles et rétro-ingénierie" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Essai" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "L'ingénierie inverse nécessite-t-elle un modèle plus grand ?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Par N0zoM1z0 · 13 octobre 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "À retenir" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}La capacité du modèle affecte les hypothèses qu'un agent d'IA peut " +"proposer.{ph1} Les sessions ultérieures ont résolu des problèmes que les " +"travaux antérieurs n'avaient pas résolus." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Un compilateur familier propose des modèles concrets à apprendre pour " +"un modèle spécialisé.{ph1} Certaines correspondances exactes de code machine" +" dépendent de modèles de code source spécifiques et réutilisables." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Incluez les connaissances du référentiel dans une comparaison " +"équitable.{ph1} Un modèle plus petit avec une bonne récupération des " +"connaissances peut déjà contenir suffisamment d'informations pour " +"progresser." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Entraînez le modèle à choisir la prochaine expérience utile et testez " +"son vérificateur.{ph1} Les retours ne sont utiles que dans la mesure où le " +"vérificateur vérifie les bonnes choses." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Évaluez les résultats de reconstruction vérifiés en fonction du temps " +"et du coût.{ph1} C'est ce que je souhaite mesurer pour le flux de travail " +"complet de l'agent IA." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "Dans cet article" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Ce que les modèles plus performants ont changé{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Pourquoi se spécialiser ?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Où cette expérience doit-elle être stockée ?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Apprendre la prochaine expérience utile{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Ingénierie inverse et apprentissage par renforcement{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Lorsque le vérificateur est erroné{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Une comparaison qui vaut la peine d'être menée{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Quel type d’agent IA cela suggère-t-il ?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Ce que les modèles plus performants ont changé" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Depuis août 2026, j'explore combien de rétro-ingénierie un agent peut " +"effectuer avec accès à un programme et un moyen de vérifier son travail. La " +"majeure partie de mon expérience vient de la reconstruction de jeux, en " +"particulier Touhou. Au fur et à mesure que j'ai changé de modèle, les " +"référentiels ont conservé une trace de ce que chaque session a réussi à " +"récupérer." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Une grande partie du travail vise une reconstruction exacte : nous compilons" +" le code maintenu avec une chaîne d'outils de l'époque dont les versions " +"sont fixées, puis vérifions si elle reproduit la fonction cible. Quand un " +"modèle ultérieur débloque le travail, les changements du code permettent de " +"comprendre ce qui a rendu ce progrès possible." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "" +"Les variables temporaires nécessitaient des durées de vie qui se " +"chevauchaient" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Une grande partie de la logique d'une fonction d'attaque TH09 avait déjà été" +" reconstruite, mais le compilateur stockait toujours les résultats " +"temporaires différemment de l'original. Le problème restant était de savoir " +"combien de temps ces résultats devaient rester en vie et quand leur stockage" +" pouvait être réutilisé." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Un {ph0}GPT-6-Sol enregistrement de session{ph1} a signalé cette incohérence" +" après avoir testé plusieurs arrangements de code source ordinaires. Lorsque" +" {ph2}GPT-6.1-Sol a réexaminé le problème{ph3}, il a proposé une hypothèse " +"utile sur la durée de vie de ces variables temporaires." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"La fonction produisait des résultats temporaires et les copiait dans des " +"positions d'animation. En C++, un résultat temporaire reste actif jusqu'à la" +" fin de l'expression qui l'utilise. Le regroupement des opérations réelles " +"en une seule expression permettait de conserver ces résultats ensemble, de " +"sorte que le compilateur ne pouvait plus réutiliser le même stockage pour " +"chacun d'entre eux." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Un résultat partageait encore son espace de stockage avec une valeur " +"utilisée plus tard pour les collisions. Donner à cette valeur une durée de " +"vie distincte a éliminé le dernier chevauchement. Après plusieurs " +"expériences ciblées, {ph0}une recompilation propre a confirmé que la " +"fonction entière correspondait à l'original{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Je suis intéressé par la façon dont la découverte et les tests se sont " +"soutenus mutuellement. L’hypothèse sur la durée de vie des objets " +"temporaires a donné une nouvelle direction à l’agent IA. Les retours du " +"compilateur l'ont aidé à affiner cette hypothèse en un arrangement de code " +"source correspondant." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Un graphique de flux de contrôle différent" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Une deuxième fonction TH09 montre pourquoi cette nouvelle direction peut " +"être importante. Ici, l'obstacle était la façon dont plusieurs branches " +"partageaient leur travail final. Les travaux antérieurs de " +"{ph0}GPT-6.1-Sol{ph1} ont permis de faire correspondre certaines parties de " +"la fonction, mais les branches se sont toujours jointes différemment de " +"l'original." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra a modifié le graphique de flux de contrôle " +"environnant{ph1}. Les chemins principaux menaient désormais à une mise à " +"jour finale et à un retour partagés. Dans cette structure source, le " +"compilateur combinait les branches de la même manière que l'original. La " +"fonction complète correspondait et une {ph2}vérification de reconstruction " +"distincte l'a confirmée{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Changer la représentation a ouvert un espace de recherche plus " +"productif.{ph1} Les deux cas me donnent une raison de prendre au sérieux la " +"capacité générale du modèle : un agent peut continuer à essayer des " +"variantes locales pendant longtemps avant de trouver une meilleure façon " +"d'exprimer le travail environnant." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Les sessions ultérieures ont aussi hérité du code précédent et des échecs " +"documentés. Ce travail accumulé faisait partie de leur avantage. " +"L'historique permet d'examiner les découvertes et leurs vérifications ; une " +"comparaison contrôlée aiderait à séparer l'effet du modèle de celui de " +"l'expérience héritée." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"C'est ce qui rend la question intéressante pour moi. Certains progrès sont " +"venus de la recherche d'une nouvelle représentation. Une grande partie du " +"travail restant consistait à tester différentes dispositions de code source " +"par rapport à un compilateur familier. Dans quelle mesure cela nécessite-t-" +"il une grande capacité de raisonnement ? Combien un modèle pourrait-il " +"apprendre en travaillant de manière répétée avec ce compilateur et ce code ?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "" +"Pourquoi un modèle d’IA spécialisé pourrait-il fonctionner correctement ?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou nous donne une raison concrète d'attendre que cette expérience nous " +"aide. Une grande partie du code du jeu provient du même auteur, ZUN, les " +"habitudes récurrentes constituent donc une hypothèse de départ raisonnable. " +"Les référentiels confirment cela avec des exemples utiles : les boucles " +"associées et les arrangements d'assistance ont fourni des hypothèses à " +"travers les jeux." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Ces modèles de source deviennent plus spécifiques lorsque nous incluons le " +"compilateur. Sous une version et un ensemble d'options particuliers, de " +"petites modifications dans la source peuvent produire des différences " +"reproductibles dans le code machine. Certaines de ces différences sont " +"étonnamment obscures." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Dans TH095, par exemple, {ph0}même le nom d'une variable locale peut " +"affecter l'endroit où VC7.1 la stocke{ph1}. Le déplacement de sa déclaration" +" n'a pas résolu la configuration du stockage. Cependant, une fonction " +"d'arrière-plan antérieure avait révélé un modèle de dénomination qui " +"affectait le choix du compilateur. Cela suggère une hypothèse plus " +"prometteuse pour {ph2}reconstruire {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"La réutilisation de ce modèle pour la variable de taille de fichier a " +"produit la mise en page requise sans ajouter de stockage. La fonction " +"complète correspondait alors." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Il s’agit d’un détail très spécifique qu’un modèle d’IA à usage général peut" +" ne pas connaître lorsqu’il rencontre le problème pour la première fois. Un " +"modèle spécialisé pour ce compilateur pourrait détecter de nombreux cas de " +"ce type et découvrir quelles variantes du code source méritent d'être " +"testées en premier." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"L’opportunité est particulièrement évidente dans les problèmes d’appariement" +" final dont nous comprenons déjà le comportement. Nous nous demandons alors " +"quel arrangement de code source ordinaire ce compilateur transforme en " +"instructions observées. La spécialisation pourrait aider le modèle à " +"proposer ces formes plus efficacement, tandis que la cible détermine " +"toujours quelles hypothèses survivent." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Les modèles utiles doivent conserver leur contexte. TH08 utilise une version" +" Visual C++ antérieure à TH095 et TH09. TH04 utilise un compilateur " +"différent de l'ère DOS. Sa {ph0}reconstruction du code du joueur{ph1} " +"nécessitait différentes hypothèses sur les modèles de code source et sur la " +"manière dont le code compilé était lié à un exécutable. Avoir le même auteur" +" nous donne une attente initiale, mais chaque cible nous dit si elle " +"s'applique. Un modèle spécialisé devrait distinguer ces contextes." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Où cette expérience doit-elle être stockée ?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Avant de décider d'enseigner ces modèles via la formation de modèles, " +"j'examinerais les connaissances que nous conservons déjà dans le " +"référentiel. Dans l'{ph0}essai précédent{ph1}, j'ai écrit qu'il deviendrait " +"la mémoire de travail du projet. Cette mémoire comprend les leçons du " +"compilateur, ainsi que la source et les expériences ratées qui les ont " +"rendues utiles." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"En récupérant cet enregistrement, un agent peut partir d’un résultat connu " +"et inspecter comment nous l’avons atteint. Cela peut également éviter des " +"alternatives qui ont déjà échoué dans le même contexte. Le point de départ " +"s'améliore sans modifier les paramètres entraînés du modèle." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Lors de la reconstruction de la fonction de TH09 pour créer des ennemis, une" +" {ph0}session GPT-6-Luna-max{ph1} a pris une hypothèse à partir du code " +"source TH08 associé. Ce code précédent suggérait comment organiser la boucle" +" et gérer les échecs à l'intérieur. Le propre témoignage de TH09 a fourni " +"des détails spécifiques au jeu. Les reconstructions à partir des sources ont" +" confirmé que la fonction complète correspondait." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"Le modèle ne connaissait pas cette bizarrerie du compilateur\" et " +"\"le modèle n'a pas pu l'utiliser\" sont des problèmes différents.{ph1} La " +"récupération peut résoudre le premier, mais transformer ce fait en un " +"candidat utile demande encore du travail. Et si le code source candidat " +"échoue, le modèle doit décider de la signification du résultat pour sa " +"prochaine tentative. Connaître le modèle pertinent n’est que le début de ce " +"processus." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Pour cette raison, j’inclurais un modèle d’IA à usage général plus petit " +"avec une bonne récupération dans toute comparaison. Lui donner la même " +"bibliothèque d'expériences nous aiderait à identifier ce que la formation " +"ajoute : une meilleure génération de candidats, de meilleures décisions " +"après feedback, ou les deux." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Apprendre la prochaine expérience utile" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Ces décisions après retour d’information sont ce que j’aimerais le plus " +"étudier. En reconstruction agentique, le modèle propose une explication et " +"la teste par rapport au programme. Même lorsque le code source candidat " +"échoue, le résultat peut réduire les possibilités restantes et suggérer une " +"prochaine expérience plus utile." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Prenons à nouveau l'exemple des résultats temporaires. Sa source finale " +"montre l'arrangement qui a fonctionné, mais l'itinéraire vers cette source " +"contient plus d'informations. Chacune des expériences suivantes a permis " +"d’identifier ce qui devait encore changer." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Expérimenter" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Ce que son résultat nous a appris" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Essayez une autre façon de copier les résultats" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Le code de copie change, mais la fonction diffère toujours." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Utiliser directement les valeurs renvoyées" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"La copie suit le modèle d'origine, mais le stockage temporaire diffère " +"toujours." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Gardez toutes les variables temporaires valides en même temps" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Ils bénéficient d'un stockage séparé, mais l'un d'entre eux chevauche " +"toujours une valeur utilisée ultérieurement pour les contrôles de collision." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Gardez la valeur de contrôle de collision séparée" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Une recompilation propre à partir de la source confirme la correspondance " +"complète." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Expériences sélectionnées de la reconstruction de la fonction d'attaque ci-" +"dessus, regroupées selon ce qu'elles nous ont appris." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Un dossier de formation qui conserve cette séquence peut enseigner plus que " +"la seule source finale. Il relie chaque changement proposé à un résultat " +"observé et à la décision suivante. Conserver des variantes inefficaces est " +"également important : elles indiquent à un agent ultérieur quelles " +"hypothèses ont déjà été testées dans ce contexte." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Je voudrais que le modèle apprenne à utiliser les retours.{ph1} Un " +"résultat neutre est une raison pour reconsidérer la variation ; une " +"inadéquation modifiée peut indiquer une autre cause. Lorsque les " +"modifications locales cessent d’être informatives, l’agent doit être en " +"mesure de revoir la représentation source ou d’inspecter à nouveau les " +"preuves." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Apprendre à faire ces choix nécessite de l’autonomie. Parfois, l'étape " +"suivante utile consiste à inspecter un autre appelant plutôt que de compiler" +" une autre modification. Une séquence rigide de réécritures requises " +"supprimerait ce choix, ainsi qu'une partie du comportement que nous " +"souhaitons que le modèle apprenne." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "" +"Pourquoi l'ingénierie inverse est intéressante pour l'apprentissage par " +"renforcement" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"La reconstruction limitée nous offre un environnement pratique pour étudier " +"ces choix. Une fois les versions de la cible et du compilateur fixées, de " +"nombreuses expériences sources produisent des retours rapides et " +"reproductibles. L'agent peut compiler un candidat, inspecter l'inadéquation " +"et utiliser cette observation pour choisir la prochaine étape." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"L'apprentissage par renforcement pourrait entraîner ce processus de prise de" +" décision grâce aux retours qu'il reçoit. Un candidat accepté par un " +"contrôle défini nous donne un résultat concret, tandis que la séquence des " +"tentatives nous permet d'observer combien de travail il a fallu pour y " +"parvenir." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Il existe déjà des recherches soutenant cette direction. " +"{ph0}LLM4Decompile{ph1} étudie les modèles spécialisés pour la " +"décompilation. {ph2}AutoDecompiler{ph3} entraîne le raffinement multi-tours " +"à l'aide des retours du compilateur et de l'exécution. Leurs études portent " +"sur la restauration du comportement. Pour ce travail, je les utiliserais " +"comme point de départ pour la tâche connexe consistant à trouver du code " +"source qui correspond à la sortie d'un compilateur historique." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Cependant, pour atteindre une tâche aussi bien définie, nous devrons peut-" +"être d’abord établir quelles ressources possède une fonction ou concevoir " +"une nouvelle manière d’observer le comportement du programme pendant son " +"exécution. Dans TH08, par exemple, une {ph0}différence de collision a " +"conduit à la manière dont le programme d'origine gérait les calculs à " +"virgule flottante{ph1}. Avant que l’agent puisse tester une correction " +"utile, il devait déterminer quoi mesurer." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Cela suggère un autre rôle pour un modèle largement performant : contribuer " +"à rendre le problème vérifiable en premier lieu. Une fois que cette " +"vérification existe, nous pouvons étudier jusqu’où une politique de " +"recherche apprise peut aller avec elle." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Lorsque le vérificateur est erroné" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Dès qu'une vérification sert à l'entraînement, sa couverture fait partie de " +"l'environnement d'apprentissage. J'appelle oracle cette référence ou ce " +"vérificateur. Même une réponse reproductible doit être comprise à partir de " +"ce qu'elle vérifie réellement." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 a montré tout ce qui peut se cacher en dehors de cette couverture. " +"Certaines fonctions reconstruites ont réussi leurs comparaisons exactes avec" +" de mauvaises constantes flottantes. Le comparateur a ajusté les adresses " +"déplacées avant de vérifier les instructions, mais il a vérifié les valeurs " +"derrière ces adresses uniquement lorsqu'elles avaient été explicitement " +"enregistrées pour vérification. D'autres références littérales pourraient " +"passer sans que leurs valeurs soient examinées." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Pour combler cette lacune, un {ph0}audit plus large{ph1} a détecté des " +"constantes incorrectes dans les fonctions qui avaient déjà réussi la " +"vérification. Dans un calcul, le code source reconstruit a ajouté {ph2}, " +"tandis que l'original a ajouté {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Un modèle récompensé par l'ancien contrôle de vérification pourrait " +"apprendre à produire une reconstruction incorrecte.{ph1} Nous n'avons pas " +"entraîné de modèle RL à l'aide de ce vérificateur. L’échec que nous avons " +"constaté concernait le contrôle lui-même. Mais si nous l’utilisions comme " +"récompense, le même angle mort deviendrait partie intégrante de " +"l’environnement d’apprentissage." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Un test fonctionnel peut avoir un angle mort similaire. {ph0}Des recherches " +"utilisant le fuzzing différentiel sur les décompilateurs LLM{ph1} ont révélé" +" des différences de comportement en dehors des tests fournis. Il faut donc " +"comprendre une épreuve de réussite en fonction des cas qu'elle exerce. De " +"même, une correspondance d’instructions doit être comprise en termes " +"d’octets et de données qu’elle vérifie." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Avant d’utiliser l’un ou l’autre type de contrôle de vérification comme " +"récompense, je le testerais avec des résultats délibérément incorrects. Je " +"garderais également l'acceptation finale séparée du code source que l'agent " +"IA peut modifier. Le modèle doit réussir la vérification en reconstruisant " +"correctement le programme. Sinon, la simple copie d'un tableau d'octets à " +"partir de la cible pourrait tromper un système de notation naïf sans " +"récupérer le code source utile." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Améliorer le modèle et améliorer son vérificateur relèvent du même " +"problème de recherche.{ph1} Plus le modèle sait optimiser le retour que nous" +" lui donnons, plus il devient important de comprendre ce retour." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Une comparaison qui vaut la peine d'être menée" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Une fois ces contrôles en place, je commencerais la comparaison sur une " +"famille de tâches VC7.1 fixe. Premièrement, j’établirais les bases d’un " +"modèle d’IA à usage général solide et d’un modèle plus petit. L'ajout de " +"connaissances sur le référentiel au modèle plus petit montrerait les " +"changements apportés à la récupération. À partir de là, une spécialisation " +"supervisée et une version formée par RL nous permettraient d'examiner ce que" +" la formation ajoute." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Pour rendre ces comparaisons informatives, chaque modèle recevrait les mêmes" +" preuves et outils cibles. Pour les comparaisons spécifiques à la formation," +" je conserverais également le modèle de base et les connaissances " +"disponibles fixes. Des essais répétés permettraient de distinguer une " +"stratégie de recherche fiable d'une solution candidate qui réussit par " +"hasard." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Je séparerais alors deux conditions de départ : reconstruire une fonction à " +"partir de ses instructions, et fermer les dernières différences dans le " +"source maintenu. Un modèle d’IA spécialisé peut être excellent pour la " +"deuxième tâche, tandis qu’un modèle d’IA à usage général effectue une grande" +" partie du travail nécessaire pour y parvenir. Les mesurer séparément " +"révélerait cette division du travail." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Les deux tâches nécessitent des exemples de test exclus de la formation et " +"de la récupération. Les jeux Touhou associés partagent le code moteur. " +"L'exclusion d'un jeu de l'entraînement pourrait néanmoins laisser des " +"fonctions presque identiques dans l'ensemble d'entraînement. Au lieu de " +"cela, j'exclurais des groupes entiers de code source associé et garderais " +"leurs réponses vérifiées hors des données de formation et de la bibliothèque" +" de récupération." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Pour ces exemples, le résultat serait des correspondances complètes et " +"vérifiées de manière indépendante. Des budgets égaux pour les propositions " +"de candidats ou les tentatives de compilation aideraient à comparer la " +"qualité de la recherche. Mesurer le temps et le coût totaux, y compris la " +"compilation, montrerait si cette qualité produit un flux de travail " +"efficace. Les coûts de formation doivent être mesurés séparément." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Les deux mesures comptent. Une proposition bon marché peut conduire à un " +"flux de travail coûteux si elle entraîne davantage de compilations ne " +"fournissant aucune information utile. À l’inverse, un modèle plus lent peut " +"être plus économique s’il trouve plus tôt une expérience utile. La " +"comparaison doit inclure ces coûts." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Compter les résultats acceptés aide aussi à interpréter les progrès " +"intermédiaires. Un {ph0}candidat pour la sauvegarde des replays{ph1} de TH09" +" semblait prometteur : la fonction compilée avait la taille attendue. " +"Pourtant, la comparaison complète montrait encore des différences " +"importantes. Un autre ordre des instructions peut donner l’impression que le" +" candidat se rapproche sans résoudre le problème de fond. Ces diagnostics " +"guident l’expérience suivante, mais je vérifierais toute récompense pour ce " +"rapprochement avec le contrôle complet d’acceptation." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Je serais intéressé par la tendance de ces résultats. Si un modèle d’IA " +"spécialisé fonctionne bien au sein d’une famille de compilateurs familière, " +"cet avantage survit-il à un changement de chaîne d’outils ? Et une fois que " +"les deux modèles d’IA ont une bonne récupération, combien la formation " +"ajoute-t-elle encore ? Les réponses nous aideraient à décider où chaque type" +" de modèle est le plus utile." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Quel type d’agent IA cela suggère-t-il ?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Si les modèles s’avèrent utiles à différentes étapes, un arrangement utile " +"pourrait être un agent large ayant accès à un modèle d’IA spécialisé. Une " +"fois qu’une tâche devient une recherche familière du compilateur, elle peut " +"demander des candidats au modèle d’IA spécialisé. Si les résultats n’ont " +"plus de sens, l’agent au sens large pourrait revenir aux preuves cibles ou " +"enquêter sur la mesure elle-même." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"Dans cet arrangement, la spécialisation devient un outil que l’agent peut " +"choisir au fur et à mesure que l’enquête se développe. L’agent conserve la " +"liberté de changer de direction qui a rendu possible les percées " +"antérieures." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Cela découle naturellement du virage industriel que j’ai décrit dans l’essai" +" précédent. Être capable de mener beaucoup plus d’expériences change la " +"façon dont nous organisons le travail. Cela nous donne également une raison " +"de nous demander quelles décisions nécessitent un jugement large et " +"lesquelles s'améliorent grâce à une expérience répétée avec un métier " +"particulier." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Pour l'instant, le modèle général le plus puissant a gagné sa place dans mon" +" travail en résolvant des problèmes que j'avais laissés en suspens. Ces " +"réussites me donnent envie d'étudier le processus : quelle part dépend de " +"ses capacités générales, et quelle part pourrait être confiée à un modèle " +"formé pour ce type de reconstruction ?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Les référentiels nous permettent de tester la question.{ph1} J'aimerais" +" utiliser cet enregistrement pour établir la comparaison et voir ce que nous" +" apprenons." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Attribution de preuves et de modèles" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Les exemples décrivent des comparaisons historiques au niveau des fonctions " +"enregistrées dans les validations liées. Les vérifications d'exécution du " +"jeu complet sont des étapes distinctes. Les enregistrements sources et " +"correspondants ont été examinés le 13 octobre 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"L'étiquette TH09 {ph0} signifie GPT-6-Astra. Le modèle associé à {ph1} a " +"changé au fil du temps, de sorte que cette étiquette à elle seule ne peut " +"pas identifier le modèle utilisé dans une exécution spécifique. Les noms de " +"modèles explicites dans les autres commits cités fournissent l'attribution " +"enregistrée. Ces historiques n'incluent pas de mesures cohérentes du coût ou" +" de l'effort pour chaque exécution." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 durées de vie des objets temporaires :{ph1} la {ph2}examen du " +"contexte précédent{ph3} et la {ph4}reconstruction complète vérifiée par une " +"recompilation propre à partir de la source{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}Callback Front de TH09 :{ph1} {ph2}régions de diagnostic non " +"concordantes{ph3}, {ph4}nouveau graphe de contrôle d'Astra{ph5} et " +"{ph6}vérification de recompilation acceptée{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Connaissance du compilateur :{ph1} {ph2}TH095 réutilisation du " +"comportement du compartiment d'identifiant{ph3}, {ph4}TH04 code source du " +"joueur et ordre de l'éditeur de liens{ph5} et {ph6}Luna reconstruction " +"complète de la fonction de création d'ennemis de TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Contrôles et diagnostics :{ph1} {ph2}TH08 audit de constantes à virgule" +" flottante{ph3}, {ph4}TH08 investigation numérique{ph5} et {ph6}TH09 " +"reconstruction permettant de sauvegarder les relectures{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Les comparaisons proposées de modèles spécialisés et de formation RL sont " +"des expériences futures. Les histoires de projets les motivent. Aucun modèle" +" spécialisé formé n'a été évalué pour cet essai." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "L'ingénierie inverse nécessite-t-elle un modèle plus grand ? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Ce que la reconstruction Touhou m'a appris sur les modèles généraux, les " +"modèles spécialisés et l'apprentissage pour proposer de meilleures " +"hypothèses à partir des retours du compilateur." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Sur cette page" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Modèles et essai d'ingénierie inverse" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Expériences de reconstruction sélectionnées" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Haut de page" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"Les {ph0}notes détaillées sur les preuves{ph1} présentent les comparaisons " +"enregistrées et le contexte des expériences." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Par N0zoM1z0 · 13 octobre 2026 · Brouillon à relire" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Guide d’installation" diff --git a/website/locales/id/messages.po b/website/locales/id/messages.po index c28fa2d1e..92d94c93a 100644 --- a/website/locales/id/messages.po +++ b/website/locales/id/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Lewati ke konten" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Rumah{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Pemikiran tentang rekayasa terbalik." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Rekonstruksi permainan{ph0}Esai" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Revolusi industri dalam rekayasa terbalik" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -53,34 +53,35 @@ msgstr "" " tentang agen, verifikasi, dan pengetahuan yang digabungkan di seluruh " "proyek." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Baca artikelnya" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Oleh N0zoM1z0 · 10 Oktober 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -101,6 +102,8 @@ msgstr "" " REA dan AI." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -136,112 +139,117 @@ msgstr "" "REA-Cari tahu cara kerja perangkat lunak. Rekayasa balik dengan agen " "pengkodean Anda." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Beranda REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Navigasi utama" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA di GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Gabung REA di Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Ikuti REA di X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -250,35 +258,35 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Rumah{ph1} / {ph2}Blog{ph3} / Rekonstruksi Touhou" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Essay * Rekonstruksi Touhou" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Revolusi industri dalam rekayasa terbalik." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Oleh N0zoM1z0 · 10 Oktober 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Poin utama" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -291,7 +299,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -305,7 +313,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -318,7 +326,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -331,7 +339,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -341,65 +349,65 @@ msgstr "" "{ph0}Kita berada di masa-masa awal revolusi industri RE.{ph1} Metodenya " "masih terbentuk. Ada banyak hal yang tersisa untuk dijelajahi." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Bagaimana pengalaman senyawa" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Arah manusia{ph1} * Tujuan dan kriteria penerimaan" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Otonomi" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agen" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Pilih eksperimen.{ph0}Mengajukan hipotesis." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Verifikasi" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Acuan verifikasi" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Uji terhadap a{ph0}referensi konkret." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Repositori" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Memori kerja" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -408,7 +416,7 @@ msgstr "Kode, bukti,{ph0}cek dan pelajaran." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -417,26 +425,26 @@ msgstr "Ketidakcocokan{ph0}{ph1}Merevisi hipotesis{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Yang lebih baik{ph0}{ph1}titik awal{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Penggunaan kembali" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Lulus{ph1} * Simpan hasil dan buktinya" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -445,14 +453,14 @@ msgstr "" "Setiap proyek meninggalkan proyek berikutnya dengan titik awal yang lebih " "baik. Itu termasuk memperbaiki pemeriksaan saat kami menemukan celah." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "Dalam artikel ini" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -460,7 +468,7 @@ msgstr "{ph0}Agustus 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -468,7 +476,7 @@ msgstr "{ph0} TH08: kelanjutan{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -476,7 +484,7 @@ msgstr "{ph0}Dua pendekatan{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -484,7 +492,7 @@ msgstr "{ph0} TH095: penggabungan{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -492,7 +500,7 @@ msgstr "{ph0} TH04: lintas arsitektur{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -500,7 +508,7 @@ msgstr "{ph0}Dari tepat hingga dapat dibaca{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -508,18 +516,18 @@ msgstr "{ph0}Pergeseran industri{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Apa yang menjadi mungkin{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Apa yang berubah pada Agustus 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -534,7 +542,7 @@ msgstr "" "menghabiskan lebih banyak waktu saya sendiri untuk acara berikutnya. Itu " "juga berarti menyimpan gambaran yang semakin besar di kepala saya." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -548,7 +556,7 @@ msgstr "" "berguna di tempat lain, tetapi setiap bidang perlu menetapkan apa yang dapat" " diperiksa terhadap referensi yang andal." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -561,7 +569,7 @@ msgstr "" "ke program dan alat pengembangan biasa. Rekonstruksi Touhou memberi saya " "sebuah proyek besar untuk mencari tahu." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -578,7 +586,7 @@ msgstr "" "Memberikan kebebasan itu membuat perbedaan: Saya dapat memberikan lebih " "banyak perhatian pada arah proyek dan apakah pemeriksaannya dapat dipercaya." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -590,7 +598,7 @@ msgstr "" "pertandingan berikutnya mendapat manfaat dari semua yang baru saja kita " "pelajari?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: membangun pekerjaan manusia" @@ -599,7 +607,7 @@ msgstr "TH08: membangun pekerjaan manusia" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -613,7 +621,7 @@ msgstr "" " landasan yang kuat. Itu datang dengan pengetahuan tentang bangunan dan " "sejarah kontribusi yang saya simpan dalam kelanjutannya." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -625,7 +633,7 @@ msgstr "" "besar mencatat sumber untuk semua 1.107 fungsi permainan yang " "teridentifikasi." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -636,7 +644,7 @@ msgstr "" "kira-kira sebelas hari setelah kelanjutan dimulai. Edisi Web menyusul. Rilis" " asli Linux 64-bit tiba pada 30 Agustus." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -652,7 +660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -671,12 +679,12 @@ msgstr "" "mengujinya; ketidakcocokan memberinya sesuatu yang spesifik untuk " "diselidiki." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Pencocokan tepat dengan konstanta yang salah" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -688,7 +696,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -701,7 +709,7 @@ msgstr "" " memeriksa kekuatan pemain terhadap {ph0}. Yang asli digunakan {ph1}, ambang" " batas daya maksimum." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -716,14 +724,14 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "" "{ph0}Namun fungsi tersebut telah melewati perbandingan yang tepat.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -739,7 +747,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -756,7 +764,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -771,7 +779,7 @@ msgstr "" " floating-point. Itu menemukan dua belas referensi yang salah di lima fungsi" " yang diterima." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -785,7 +793,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -795,7 +803,7 @@ msgstr "" "{ph0}Referensi verifikasi (oracle) juga perlu direkonstruksi.{ph1} " "Memperbaikinya adalah bagian dari memperbaiki permainan." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -814,7 +822,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -830,7 +838,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -840,7 +848,7 @@ msgstr "" "{ph0}Batch yang berhasil memberi kami kode yang dipulihkan dan lingkungan " "yang lebih baik untuk batch berikutnya.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Dua gagasan rekonstruksi yang berbeda" @@ -849,7 +857,7 @@ msgstr "Dua gagasan rekonstruksi yang berbeda" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -862,7 +870,7 @@ msgstr "" "pengembangan lebih lanjut akan dilakukan secara pribadi hingga selesai. Satu" " bagian berbunyi:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -872,7 +880,7 @@ msgstr "" "dari pekerjaan kami memberikan gambaran yang buruk untuk upaya dekompilasi " "di masa mendatang…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -890,7 +898,7 @@ msgstr "" "diskusikan adalah tentang bagaimana rekonstruksi harus dilanjutkan dan " "bagaimana kontribusi harus dinilai." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -904,7 +912,7 @@ msgstr "" "pada kontributor menjadi penting karena begitu banyak alasan yang terjadi " "saat mereka bekerja." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -916,7 +924,7 @@ msgstr "" "menggunakan pengetahuan itu untuk melanjutkan penyelidikan berikutnya dengan" " sendirinya." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -931,7 +939,7 @@ msgstr "" "ingin orang lain dapat memeriksa mengapa kami memilih implementasi, bahkan " "jika agen melakukan sebagian besar pekerjaan." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -944,7 +952,7 @@ msgstr "" "menimbulkan pertanyaan nyata tentang kredit. Ini juga mengubah apa yang " "perlu diketahui pengelola sebelum menerima kontribusi." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -960,7 +968,7 @@ msgstr "" "Komunitas yang berbeda dapat memilih seberapa banyak perubahan yang ingin " "mereka lakukan." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -986,7 +994,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -998,14 +1006,14 @@ msgstr "" "Oktober 2026, dan {ph2}kebijakan kontribusi{ph3}. Kutipannya adalah kutipan " "singkat. TH08 {ph4}kredit dan asalnya{ph5} catat batas kelanjutannya." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: pengalaman mulai bertambah" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1020,7 +1028,7 @@ msgstr "" " Tapi kami sudah tahu lebih banyak tentang bagaimana memulai rekonstruksi " "dan bagaimana membuatnya tetap bergerak." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1034,7 +1042,7 @@ msgstr "" " ditandai dapat dimainkan pada 10 September, sekitar dua belas hari setelah " "inisialisasi." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1045,7 +1053,7 @@ msgstr "" "baru bisa mendapat manfaat dari pekerjaan yang dilakukan di game lain. " "Pengalaman sudah ada dalam alat dan cara proyek diatur." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1060,7 +1068,7 @@ msgstr "" "Kita perlu melihat mereka bekerja sama. Pelajaran itu membantu membentuk " "cara kami mendekati pembuatan seluruh program TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1073,7 +1081,7 @@ msgstr "" " setelah saya melanjutkan. Agen berikutnya dapat menggunakan hasilnya tanpa " "mengulangi penyelidikan yang mengarah ke sana." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1088,7 +1096,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1100,7 +1108,7 @@ msgstr "" "selanjutnya.{ph1} Kita dapat menghabiskan lebih banyak upaya proyek " "berikutnya untuk apa yang sebenarnya baru tentang targetnya." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1113,7 +1121,7 @@ msgstr "" "melanjutkan pekerjaan. Mereka tidak perlu merekonstruksi seluruh sejarah " "proyek untuk mengetahui mengapa sumbernya terlihat seperti itu." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: alur kerja bertahan dari arsitektur yang berbeda" @@ -1122,7 +1130,7 @@ msgstr "TH04: alur kerja bertahan dari arsitektur yang berbeda" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1138,7 +1146,7 @@ msgstr "" " dari game Windows. Sudah ada {ph2}ReC98 bekerja{ph3} memberi kami " "pengetahuan dan sumber materi yang berharga di sini juga." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1151,7 +1159,7 @@ msgstr "" "Pekerjaan saat ini adalah port 64-bit asli. Membuat versi DOS yang berfungsi" " terlebih dahulu memberikan referensi pada port tersebut." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1164,7 +1172,7 @@ msgstr "" " bisa mengikuti pertanyaan sampai ke hasil dan membiarkan hasil itu memandu " "percobaan berikutnya." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1179,7 +1187,7 @@ msgstr "" "Setelah bukti dan pemeriksaan tersedia, agen dapat mengerjakan pertanyaan " "tersebut seperti yang dilakukan pada judul Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1191,7 +1199,7 @@ msgstr "" "cara kerja yang baru. Arsitektur mendefinisikan masalahnya; alur kerja masih" " memberi kami cara untuk menyelesaikannya." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1208,7 +1216,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1218,12 +1226,12 @@ msgstr "" "Status proyek per 10 Oktober 2026: {ph0}Rekonstruksi DOS dan pengujian " "manual{ph1} · {ph2}port 64-bit{ph3}. Pelabuhan masih dalam pengembangan." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Dari kode yang tepat hingga kode yang dapat dibaca" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1231,7 +1239,7 @@ msgid "" msgstr "" "Setelah rekonstruksi berhasil, saya ingin orang lain dapat memahaminya." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1246,7 +1254,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1263,7 +1271,7 @@ msgstr "" " buktinya. Kami menyimpan alasannya dengan sumbernya sehingga orang " "berikutnya dapat melihat dari mana interpretasi itu berasal." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1278,14 +1286,14 @@ msgstr "" "memiliki status tersebut. Untuk memindahkan perilaku dengan aman, kita perlu" " memulihkan hubungan di balik akses memori lama." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Urutan yang sekarang saya gunakan adalah:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1301,7 +1309,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1318,7 +1326,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1335,7 +1343,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1350,7 +1358,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1367,7 +1375,7 @@ msgstr "" "direkonstruksi masih dibangun dan berperilaku dengan benar di sepanjang " "jalur yang kita gunakan." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1381,7 +1389,7 @@ msgstr "" " tetap tersedia memberi agen kegagalan nyata untuk menyelidiki sebelum " "melakukan refactor lebih lanjut." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1399,7 +1407,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1418,7 +1426,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1429,12 +1437,12 @@ msgstr "" "membuat pengetahuan yang dipulihkan dapat digunakan.{ph1} Sebuah port " "kemudian dapat dibangun di atas keduanya." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Apa yang membuat ini menjadi pergeseran industri" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1448,7 +1456,7 @@ msgstr "" "yang lebih baik dapat membantu setiap fungsi selanjutnya yang " "membutuhkannya." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1462,7 +1470,7 @@ msgstr "" " Jika harus menunggu saya untuk menentukan setiap langkah, sebagian besar " "pekerjaan tetap terkait dengan perhatian saya." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1476,7 +1484,7 @@ msgstr "" "masih harus memutuskan apakah bukti yang terkumpul mendukung pencapaian " "proyek." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1491,7 +1499,7 @@ msgstr "" "dapat menggunakannya untuk menguji sumber yang diusulkannya dan melihat di " "mana penjelasannya bertahan." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1509,7 +1517,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1529,7 +1537,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1546,7 +1554,7 @@ msgstr "" "bersama, kami harus memperbaikinya dan meninjau kembali hasil yang " "terpengaruh. Proyek berikutnya kemudian dapat mewarisi alat yang lebih kuat." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1561,7 +1569,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1574,7 +1582,7 @@ msgstr "" "mereka. Bekerja pada satu permainan dapat meningkatkan kondisi awal untuk " "permainan lainnya." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1586,12 +1594,12 @@ msgstr "" "tersebut mengubah seberapa banyak orang berikutnya—atau agen " "berikutnya—dapat menyelesaikannya." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Proyek-proyek yang sekarang dapat kita pertimbangkan" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1603,7 +1611,7 @@ msgstr "" "lebih banyak perhatian saya sendiri daripada yang bisa saya berikan secara " "realistis. Banyak proyek akan tetap menjadi ide." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1621,7 +1629,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1632,7 +1640,7 @@ msgstr "" "umpan balik, dan akumulasi pengetahuan apa yang memungkinkan agen " "mengerjakan ini dengan andal?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1644,12 +1652,12 @@ msgstr "" "mendekati pendekatan berikutnya. Saya ingin terus mengeksplorasi seberapa " "jauh hal itu dapat membawa kita." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Tonggak dan sumber proyek" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1684,7 +1692,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1718,7 +1726,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1736,7 +1744,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1760,7 +1768,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1782,7 +1790,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1798,7 +1806,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1820,7 +1828,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1834,7 +1842,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1855,27 +1863,27 @@ msgstr "" "agen AI, dan bagaimana pengetahuan menyatu di seluruh TH08, TH095, dan PC-98" " TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Pengalaman yang dibawa antar proyek" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Esai rekonstruksi Touhou" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -1884,18 +1892,18 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Rumah{ph1}{ph2}/{ph3}Lab kecepatan dinosaurus" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Periksa →" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Bangun kembali aturan kecepatan dinosaurus." @@ -1904,7 +1912,7 @@ msgstr "Bangun kembali aturan kecepatan dinosaurus." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1917,15 +1925,15 @@ msgstr "" "berjalan;{ph1} kami menggunakan aturannya untuk membuat mini-game ini dengan" " {ph2}kecepatan yang dapat disesuaikan.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Di halaman ini" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1933,7 +1941,7 @@ msgstr "{ph0}Mainkan dan ubah kecepatannya{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1941,7 +1949,7 @@ msgstr "{ph0}Baca aturan yang dipulihkan{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1949,18 +1957,18 @@ msgstr "{ph0}Periksa rekonstruksi{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Coba analisisnya{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Mainkan dan ubah kecepatannya" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1972,49 +1980,49 @@ msgstr "" "tetap. Pilih aturan yang dipulihkan untuk memulai dari 6 dan percepat lagi " "secara bertahap." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Mainkan hasil rekonstruksi" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Main" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Lompat ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Mulai ulang" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Kecepatan" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Gunakan aturan akselerasi yang dipulihkan" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Aturan awal: mulai dari 6, lalu tingkatkan menjadi 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Gerakkan penggeser untuk mengatur kecepatan Anda sendiri. Ruang atau " "Lompatan membersihkan kaktus." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2023,7 +2031,7 @@ msgstr "" "Aktifkan JavaScript untuk memainkan rekonstruksi. Kode dan penjelasan di " "atas tetap dapat dibaca." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Baca script REA kembali" @@ -2031,7 +2039,7 @@ msgstr "Baca script REA kembali" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2046,7 +2054,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2056,18 +2064,18 @@ msgstr "" "Pengaturannya adalah {ph0}, {ph1} dan {ph2}. Gim ini menjalankan cabang ini " "pada pembaruan tanpa tabrakan." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Gunakan aturan yang sama di game baru" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Salin" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2084,18 +2092,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}Unduh aturan kecepatan{ph1} · {ph2}Baca kode permainannya{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Periksa rekonstruksi" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2106,27 +2114,27 @@ msgstr "" "otomatis dinonaktifkan. Bandingkan kecepatan yang direkam tersebut dengan " "pemutaran ulang aturan yang dipulihkan." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Pembaruan" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Game asli" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Aturan yang direkonstruksi" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Jalankan pemeriksaan kecepatan" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2135,14 +2143,14 @@ msgstr "" "Nilai dibulatkan menjadi tiga desimal. Cabang memeriksa sebelum menambahkan," " sehingga kenaikan terakhir dapat mengambil kecepatan tepat di atas 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Coba analisisnya sendiri" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2151,7 +2159,7 @@ msgstr "{ph0}Siapkan REA {ph1} dengan agen pengodean Anda." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2160,7 +2168,7 @@ msgstr "" "Ikuti {ph0}langkah-langkah koneksi browser{ph1}, menggunakan {ph2} sebagai " "URL halaman." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2177,7 +2185,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2189,7 +2197,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2203,7 +2211,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2218,7 +2226,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2244,12 +2252,12 @@ msgstr "" "Baca aturan kecepatan permainan dinosaurus dengan REA, bangun kembali, lalu " "ubah kecepatan dan mainkan." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Rekonstruksi kecepatan dinosaurus" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2258,52 +2266,52 @@ msgstr "" "Mini-game dinosaurus. Gunakan tombol Lompat atau tekan Spasi saat permainan " "difokuskan." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Salin aturan kecepatan yang direkonstruksi" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Salin prompt analisis dinosaurus" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Lewati ke konten" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Rumah{ph1} / FAQ" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "FAQ REA." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Penyiapan, pembaruan, analisis, dan pemecahan masalah." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Topik" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2311,7 +2319,7 @@ msgstr "{ph0}Penyiapan dan pembaruan{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2319,7 +2327,7 @@ msgstr "{ph0}Analisis{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2327,31 +2335,31 @@ msgstr "{ph0}Pemecahan masalah{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Data dan berbagi{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Penyiapan dan pembaruan" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Bagaimana cara memasang REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * penyiapan agen" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Salin" @@ -2359,7 +2367,7 @@ msgstr "Salin" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2373,12 +2381,12 @@ msgstr "" "pertanyaan. {ph0}Panduan penyiapan{ph1} menjelaskan kebutuhan awal dan " "langkah analisis pertama." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Agen pengkodean mana yang dapat menggunakan REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2393,18 +2401,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Hubungkan agen pengkodean Anda{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Bagaimana cara memperbarui REA ?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2413,13 +2421,13 @@ msgstr "" "REA sering dirilis, termasuk perbaikan bug. Jika Anda menginstal CLI dengan " "npm :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * terpasang CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2429,14 +2437,14 @@ msgstr "" "Ikuti perintah penyegaran penyiapan yang dicetak oleh pembaruan. Jika Anda " "mengatur agen Anda melalui {ph0}, lari:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * pengaturan agen penyegaran" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2448,14 +2456,14 @@ msgstr "" "tertentu, jadi jalankan penyiapan lagi agar agen memakai versi baru. Untuk " "satu kali perintah CLI, tambahkan perintah setelah {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Apakah memasang keterampilan dari skills.sh cukup?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2468,24 +2476,24 @@ msgstr "" "keterampilan yang cocok, mulai ulang agen Anda sehingga dapat memanggil " "alat." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Analisis" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Apa yang dapat saya analisis dengan REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Mulailah dengan jenis perangkat lunak yang Anda miliki:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2497,7 +2505,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2509,7 +2517,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2517,7 +2525,7 @@ msgstr "{ph0}Halaman browser{ph1}: skrip, permintaan, dan pengamatan runtime." #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2529,12 +2537,12 @@ msgstr "" " dan sumber daya yang dikemas. {ph0}Lihat studi kasus{ph1} untuk investigasi" " yang berhasil." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Apakah saya memerlukan Hopper, Ghidra atau IDA ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2546,7 +2554,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2559,12 +2567,12 @@ msgstr "" "penyedia mana yang dapat digunakan. {ph0}Menyiapkan analisis program kode " "mesin{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Dapatkah saya menggunakan REA tanpa agen pengkodean?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2573,14 +2581,14 @@ msgstr "" "Ya. CLI menggunakan alur kerja analisis yang sama. Untuk aplikasi JavaScript" " atau Electron lokal:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * analisis aplikasi statis" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2591,13 +2599,13 @@ msgstr "" "{ph0}Gunakan CLI {ph1} untuk opsi instalasi." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Kode apa yang dikembalikan REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2612,7 +2620,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2624,12 +2632,12 @@ msgstr "" " menguji implementasi. The {ph0} Perhitungan DX-Ball{ph1} dan {ph2}Pemeriksa" " bendera KKP{ph3} tunjukkan bagaimana proses itu bekerja." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Apa yang sebaiknya saya tanyakan kepada agen?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2646,7 +2654,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2654,7 +2662,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2664,18 +2672,18 @@ msgstr "" "Ganti jalur dengan target Anda. The {ph0}panduan{ph1} berikan petunjuk untuk" " contoh asli, Electron, dan browser." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Pemecahan masalah" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Mengapa agen saya tidak dapat melihat alat REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2685,7 +2693,7 @@ msgstr "" "Mulai ulang atau sambungkan kembali agen Anda setelah penyiapan. Periksa " "pendaftaran REA-nya dengan {ph0}; untuk Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * periksa satu klien" @@ -2693,7 +2701,7 @@ msgstr "Terminal * periksa satu klien" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2704,14 +2712,14 @@ msgstr "" "menunjukkan pendaftaran yang hilang atau kedaluwarsa, jalankan penyiapan " "untuk klien tersebut:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * perbaiki pengaturan satu klien" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2723,14 +2731,14 @@ msgstr "" "tetap tidak ada, periksa kesalahan koneksi MCP klien. {ph0}Lebih banyak " "diagnostik pengaturan{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Apakah saya harus memulai Hopper terlebih dahulu?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2742,14 +2750,14 @@ msgstr "" "pilihan mode demo atau aktivasi lisensi yang dijalankan pertama kali sebelum" " analisis tanpa pengawasan. {ph0}Lihat penyiapan penyedia asli{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Apa yang harus saya lakukan jika menemukan bug?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2761,7 +2769,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2774,17 +2782,17 @@ msgstr "" "kesalahan. Sertakan nama penyedia saat masalah melibatkan analisis program " "kode mesin." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Data dan berbagi" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "Apakah REA mengunggah aplikasi saya?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2793,7 +2801,7 @@ msgstr "" "REA menganalisis target pada mesin Anda. Agen Anda menerima hasilnya, dan " "kebijakan data penyedia modelnya berlaku untuk hasil tersebut." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Bagaimana saya bisa membagikan contoh atau berkontribusi?" @@ -2802,7 +2810,7 @@ msgstr "Bagaimana saya bisa membagikan contoh atau berkontribusi?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2818,7 +2826,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2843,77 +2851,77 @@ msgstr "" "Jawaban atas pertanyaan umum REA: instalasi, pembaruan, alat analisis, agen " "pengkodean, pemecahan masalah, dan contoh berbagi." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Pertanyaan yang sering diajukan tentang REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Salin perintah pengaturan REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Salin perintah pembaruan REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Perintah penyegaran penyiapan agen salin" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Salin perintah analisis REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Salin contoh analisis prompt" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Salin perintah diagnosis klien" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Salin perintah pengaturan cakupan" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Lewati ke konten" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Rumah{ph1} / Investigasi pertama Anda" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Cari tahu di mana{ph0}catatan yang diekspor pergi." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2922,14 +2930,14 @@ msgstr "" "Gunakan REA untuk memeriksa aplikasi kecil, ikuti tombol catatan Ekspornya, " "dan periksa sendiri satu detailnya." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "Dalam latihan ini" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2937,7 +2945,7 @@ msgstr "{ph0}1. Siapkan{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2945,7 +2953,7 @@ msgstr "{ph0}2. Tanyakan tentang ekspor{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2953,7 +2961,7 @@ msgstr "{ph0}3. Ikuti jawabannya{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2961,13 +2969,13 @@ msgstr "{ph0}4. Periksa prediksi{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Ajukan pertanyaan lain{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Hubungkan agen Anda ke REA" @@ -2980,29 +2988,29 @@ msgstr "1. Hubungkan agen Anda ke REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Salin" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Atau jalankan perintah ini di terminal Anda:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3011,14 +3019,14 @@ msgstr "" "Tinjau paket, setujui penyiapan, lalu mulai ulang agen Anda. Sudah " "terhubung? Lanjutkan di bawah ini." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Tanyakan di mana CSV ditulis" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3030,7 +3038,7 @@ msgstr "" " tombol. Agen Anda dapat memeriksa kodenya tanpa menginstal atau meluncurkan" " Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3042,14 +3050,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Unduh contoh ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3059,12 +3067,12 @@ msgstr "" "Jika agen Anda tidak dapat mengunduh file, buka zip arsip ini sendiri. " "Berikan jalan ke {ph0} folder dan pertanyaan ekspor yang sama." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Ikuti jawabannya kembali ke kode" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Cari penjelasan singkat dengan referensi file dan baris:" @@ -3073,7 +3081,7 @@ msgstr "Cari penjelasan singkat dengan referensi file dan baris:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3085,12 +3093,12 @@ msgstr "" "sebagai CSV dan menulis {ph1} di folder Unduhan pengguna. Kolomnya adalah " "{ph2} dan {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Dari tombol ke penulis file" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3099,7 +3107,7 @@ msgstr "" "Analisis statis REA memasangkan pesan dengan penangannya. Tujuan dibaca dari" " kode." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3110,18 +3118,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}Lihat jejak kode lengkap dan hasil REA yang direkam{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Periksa prediksi" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3130,19 +3138,19 @@ msgstr "" "Koma memisahkan kolom CSV. Apa yang terjadi jika judul catatan itu sendiri " "berisi koma atau tanda petik?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Jalankan cek sendiri" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Buka terminal di bagian yang belum dibongkar {ph0} folder:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3152,17 +3160,17 @@ msgstr "" "atau Zsh. Agen Anda dapat menjalankan JavaScript yang sama di shell platform" " Anda." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Ajukan pertanyaan lain" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Coba tindak lanjut dalam percakapan yang sama:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3171,7 +3179,7 @@ msgstr "" "Apa yang terjadi jika file tidak dapat ditulis? Ikuti kesalahan kembali ke " "halaman." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3184,7 +3192,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3198,7 +3206,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3212,7 +3220,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3237,65 +3245,65 @@ msgstr "" "perginya catatan yang diekspor, dan periksa formatter CSV dengan judul " "sampel." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Investigasi REA pertama Anda" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Salin prompt instalasi REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Salin perintah pengaturan" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Salin Catatan penyelidikan prompt" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Salin prompt pemeriksaan CSV" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Salin perintah pemeriksaan formatter" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Lewati ke konten" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Rumah{ph1} / Memulai" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Siapkan REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3303,49 +3311,49 @@ msgstr "" "Hubungkan REA ke agen pengkodean Anda, atau periksa aplikasi lokal dari " "terminal Anda." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Buka terminal dan periksa:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminal" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Salin" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3358,7 +3366,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3369,17 +3377,17 @@ msgstr "" "pada sistem ini\"{ph1} saat Anda berlari {ph2}, jalankan ini sekali dan coba" " lagi:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Jika Anda menggunakan Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Kalau tidak,:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Tutup Terminal, buka lagi, lalu:" @@ -3387,7 +3395,7 @@ msgstr "Tutup Terminal, buka lagi, lalu:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3399,7 +3407,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3411,7 +3419,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3420,14 +3428,14 @@ msgid "" msgstr "" "Lebih suka penginstal biasa? Unduh versi LTS dari {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Opsi pengaturan" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3435,7 +3443,7 @@ msgstr "{ph0}Hubungkan agen pengkodean Anda{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3443,7 +3451,7 @@ msgstr "{ph0}Gunakan CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3451,18 +3459,18 @@ msgstr "{ph0}Menyiapkan analisis program kode mesin{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Mendapatkan bantuan{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Hubungkan agen pengkodean Anda" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3474,12 +3482,12 @@ msgstr "" "Build, dan klien MCP lain yang didukung. Konektor Grok Bot ditambahkan dari " "obrolannya." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Baru mengenal agen pengkodean?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3490,7 +3498,7 @@ msgstr "" "tab browser. Itu dapat membaca file dan menjalankan perintah, dan bertanya " "sebelum membuat perubahan. REA memberikan alat rekayasa balik." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3502,7 +3510,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3515,7 +3523,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3527,7 +3535,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3537,7 +3545,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}, sumber terbuka. Hubungkan penyedia model " "pilihan Anda." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3555,18 +3563,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Atau jalankan pengaturan sendiri" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Bagaimana cara membuka terminal?" @@ -3575,7 +3583,7 @@ msgstr "Bagaimana cara membuka terminal?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3591,7 +3599,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3605,7 +3613,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3618,7 +3626,7 @@ msgstr "{ph0} Linux :{ph1} pers {ph2} {ph3} {ph4} di sebagian besar desktop." #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3628,7 +3636,7 @@ msgstr "" "Tempel perintah dengan {ph0} {ph1} (macOS : {ph2} {ph3}; Terminal Linux: " "{ph4} {ph5} {ph6}), lalu tekan Enter." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3639,12 +3647,12 @@ msgstr "" "dan keterampilan investigasi pencocokan, menyimpan cadangan konfigurasi yang" " ada. Itu bertanya sebelum menerapkan perubahan." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Mulai ulang klien Anda saat penyiapan selesai." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Bagaimana cara memulai ulang klien saya?" @@ -3653,7 +3661,7 @@ msgstr "Bagaimana cara memulai ulang klien saya?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3669,7 +3677,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3679,7 +3687,7 @@ msgstr "" "{ph0}Agen terminal{ph1} ( Claude Code, Codex, Gemini CLI): keluar dari sesi " "dan mulai lagi." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3689,7 +3697,7 @@ msgstr "" "JavaScript atau Electron, Anda dapat memulai dengan:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3700,12 +3708,12 @@ msgstr "" "panggilan, dan dependensi yang terlibat, dengan lokasi sumber untuk temuan " "Anda." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Ganti jalur dengan target lokal Anda." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Bagaimana cara mendapatkan jalur lengkap folder?" @@ -3714,7 +3722,7 @@ msgstr "Bagaimana cara mendapatkan jalur lengkap folder?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3729,7 +3737,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3741,7 +3749,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3751,17 +3759,17 @@ msgstr "" "{ph0}Sistem apa pun:{ph1} seret folder ke jendela terminal dan jalurnya " "muncul." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "Di terminal, beri tanda kutip di sekitar jalur yang berisi spasi." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Gunakan CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3770,14 +3778,14 @@ msgstr "" "Analisis folder aplikasi JavaScript atau Electron atau arsip ASAR tanpa " "menjalankan aplikasi:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Analisis aplikasi statis" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3787,13 +3795,13 @@ msgstr "" "Ganti jalur dengan direktori aplikasi yang Anda ekstrak atau {ph0} berkas. " "Pada Windows, jalur seperti {ph1} bekerja di sini." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Di mana saya menemukan aplikasi .berkas asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3804,7 +3812,7 @@ msgstr "Aplikasi Electron biasanya menyimpannya dalam {ph0} folder:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3816,7 +3824,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3829,21 +3837,21 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} sering {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "" "Beberapa aplikasi dipasang di tempat lain. Cari folder aplikasi untuk {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3855,31 +3863,31 @@ msgstr "" "ditandai dalam hasil." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Jika Anda ingin permanen {ph0} perintah di shell Anda:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Instal CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Lanjutkan dengan panduan aplikasi JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Menyiapkan analisis program kode mesin" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3888,12 +3896,12 @@ msgstr "" "Program kode mesin memerlukan alat analisis lokal. Pilih dan konfigurasikan " "salah satu di bawah ini, lalu berikan REA executable atau pustaka Anda." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Pilih alat: Ghidra, Hopper atau IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3905,17 +3913,17 @@ msgstr "" "memerlukan dekompiler asli untuk arsitektur host Anda. Setel jalur sebelum " "menjalankan penyiapan:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Hubungkan instalasi Ghidra Anda" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Koneksi Ghidra · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3927,12 +3935,12 @@ msgstr "" " Pada Linux arm64, Anda mungkin perlu membuat dekompiler asli Ghidra secara " "terpisah." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Hubungkan Ghidra di Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3943,19 +3951,19 @@ msgstr "" " dan x64 asli dan DLL pada drive NTFS lokal tetap. Gunakan Ghidra 12.1 yang " "ada.instalasi x dan JDK 64-bit 21 atau yang lebih baru:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Koneksi Ghidra · PowerShell Windows" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "" "Ganti kedua jalur dengan penginstalan Anda, lalu tinjau paket penyiapan." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3965,7 +3973,7 @@ msgstr "" " itu mendeteksi instalasi yang ada atau menawarkan rencana instalasi untuk " "persetujuan Anda." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3974,7 +3982,7 @@ msgstr "" "Pada macOS, selesaikan pilihan mode demo atau aktivasi lisensi Hopper yang " "dijalankan pertama kali sebelum analisis tanpa pengawasan." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3985,7 +3993,7 @@ msgstr "" "yang ada untuk GUI terlampir atau basis data tanpa kepala. Analisis tanpa " "kepala Linux dan macOS tetap belum diverifikasi." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Hubungkan pendaftaran IDA MCP yang ada" @@ -3995,7 +4003,7 @@ msgstr "Hubungkan pendaftaran IDA MCP yang ada" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4007,13 +4015,13 @@ msgstr "" "dalam file JSON. Yang sudah ada {ph3} objek dengan sebuah {ph4} entri juga " "diterima. Arahkan REA ke file itu sebelum pengaturan:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Koneksi IDA · PowerShell Windows" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4031,7 +4039,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4043,29 +4051,29 @@ msgstr "" "Untuk agen, sertakan {ph1} di lingkungan pendaftaran REA dan pilih IDA saat " "membuka biner." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Untuk pengaturan Ghidra yang ada, periksa fungsi dengan:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Analisis fungsi" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "Ganti {ph0} dengan nama fungsi atau alamat yang ingin Anda periksa." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Bagaimana analisis sesi program kode mesin bekerja" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4078,7 +4086,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4088,18 +4096,18 @@ msgstr "" "{ph0}Ikuti contoh analisis program kode mesin{ph1} untuk melihat bagaimana " "hasil fungsi mengarah ke perhitungan yang dipulihkan." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Mendapatkan bantuan" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Jika agen Anda tidak melihat REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4109,27 +4117,27 @@ msgstr "" "Mulai ulang atau sambungkan kembali klien setelah pengaturan. Periksa " "koneksi REA-nya dengan {ph0}; untuk Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Periksa satu klien" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Jika penyedia membutuhkan perhatian" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Periksa penyedia yang Anda gunakan. Untuk Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Periksa satu penyedia" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4140,7 +4148,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4153,7 +4161,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4167,7 +4175,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4181,7 +4189,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4206,112 +4214,112 @@ msgstr "" "Electron lokal dari terminal. Penyiapan, pertanyaan pertama, dan panduan " "penyedia asli." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Salin pemeriksaan versi Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Salin perintah instalasi Node.js untuk Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Salin perintah kebijakan eksekusi PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Salin perintah instalasi Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Salin perintah instalasi fnm untuk macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Salin perintah Node.js 24 untuk macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Salin perintah instalasi fnm untuk Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Salin perintah Node.js 24 untuk Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "Panduan memulai REA" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Salin prompt instalasi REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Salin perintah penyiapan agen" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Salin perintah analisis JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Salin perintah instalasi CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Salin perintah koneksi Ghidra untuk macOS dan Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Salin koneksi Ghidra untuk PowerShell Windows" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Salin koneksi IDA untuk PowerShell Windows" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Salin perintah analisis fungsi asli" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Salin perintah diagnosis klien" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Salin perintah diagnosis penyedia" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -4320,20 +4328,20 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Rumah{ph1} / {ph2}Panduan{ph3} / Pengamatan browser" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Lihat apa yang terjadi{ph0}saat Anda mengklik." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4342,14 +4350,14 @@ msgstr "" "Gunakan aplikasi browser kecil untuk menghubungkan tindakan, permintaan " "jaringannya, dan JavaScript yang membuat unduhan." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "Dalam panduan ini" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4357,7 +4365,7 @@ msgstr "{ph0}Contohnya{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4365,7 +4373,7 @@ msgstr "{ph0}Buka browser{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4373,7 +4381,7 @@ msgstr "{ph0}Tanyakan pada agen Anda{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4381,13 +4389,13 @@ msgstr "{ph0}Tangkap dari CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Baca permintaan dan skrip{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Apa yang terjadi saat Anda mengklik Ekspor?" @@ -4397,7 +4405,7 @@ msgstr "Apa yang terjadi saat Anda mengklik Ekspor?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4409,7 +4417,7 @@ msgstr "" "tombol. Mengkliknya akan memuat {ph4}, memformat dua catatan sebagai CSV, " "dan memulai pengunduhan." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Dari klik ke unduhan CSV" @@ -4420,7 +4428,7 @@ msgstr "Dari klik ke unduhan CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4436,7 +4444,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4454,7 +4462,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4464,17 +4472,17 @@ msgstr "" "{ph0}03 * Agen Anda{ph1}{ph2}Baca kode ekspor{ph3}{ph4}Hubungkan permintaan " "yang diamati ke {ph5} dalam {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Mulai pengambilan sebelum mengklik Ekspor catatan." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Buka Chrome dengan debugging jarak jauh" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4483,21 +4491,21 @@ msgstr "" "Buka contoh Catatan yang dihosting dengan profil browser terpisah dan port " "debugging lokal. Di Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Mulai browser contoh" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Salin" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4506,7 +4514,7 @@ msgstr "" "Gunakan jalur eksekusi browser yang Anda instal di macOS atau Windows . Anda" " dapat mengganti URL halaman dengan halaman lain yang ingin Anda periksa." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4515,7 +4523,7 @@ msgstr "" "REA terhubung ke browser yang ada ini. Anda tetap mengontrol halaman, " "melakukan tindakan, dan menutup browser setelah selesai." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Minta agen Anda untuk menonton satu aksi" @@ -4528,7 +4536,7 @@ msgstr "Minta agen Anda untuk menonton satu aksi" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4540,7 +4548,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4552,7 +4560,7 @@ msgstr "" "dibuat?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4562,7 +4570,7 @@ msgstr "" "Contoh prompt. Berikan agen Anda titik akhir debugging, {ph0}, dan URL " "halaman. Biarkan mulai menangkap sebelum Anda mengklik." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4572,23 +4580,23 @@ msgstr "" "Agen Anda menemukan target halaman, memulai jendela observasi, dan membaca " "bukti yang dihasilkan. Itu kemudian dapat memeriksa skrip di balik ekspor." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Atau tangkap dari terminal" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Temukan ID target halaman:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Temukan halamannya" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4598,14 +4606,14 @@ msgstr "" "Pilih target dengan URL contoh Catatan. Ganti {ph0} di bawah ini dengan ID -" " nya, lalu jalankan:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Abadikan sepuluh detik berikutnya" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4616,7 +4624,7 @@ msgstr "" "catatan{ph1} pada browser tersebut. Hasilnya tiba setelah jendela observasi " "berakhir." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4627,49 +4635,49 @@ msgstr "" "jendela tersebut, dan bentuk respons JSON. Permintaan sebelumnya berada di " "luar tangkapan ini." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Baca skrip permintaan dan ekspor" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Direkam dengan REA 4.1.0 pada contoh Catatan lokal" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Fakta yang ditangkap" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Nilai" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Permintaan" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Tanggapan" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Inisiator permintaan" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * naskah" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Struktur respons" @@ -4677,19 +4685,19 @@ msgstr "Struktur respons" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} dengan {ph1} dan {ph2} bidang" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Baca skrip yang dimuat" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4701,7 +4709,7 @@ msgstr "" "digunakan:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4714,7 +4722,7 @@ msgstr "" "{ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4726,7 +4734,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4750,65 +4758,65 @@ msgstr "" "Amati ekspor Catatan dengan REA: pilih halaman browser, tangkap klik, " "periksa permintaan, dan ikuti skrip ekspor." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Pengamatan browser" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Salin mulai browser contoh" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Salin contoh prompt" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Salin temukan halaman" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Salin tangkap sepuluh detik berikutnya" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Salin baca skrip yang dimuat" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Lewati ke konten" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Rumah{ph1} / Panduan" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Panduan REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4817,37 +4825,37 @@ msgstr "" "Analisis fungsi asli, ekspor Electron, atau permintaan browser. Setiap " "panduan menyertakan prompt, kode, dan hasil." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Investigasi pertama" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Siapkan REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Hubungkan agen pengkodean Anda atau gunakan REA dari terminal." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Mulai dengan REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Program kode mesin" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Pulihkan perhitungan posisi suara kiri / kanan" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4856,22 +4864,22 @@ msgstr "" "Mulailah dengan game Windows yang dapat dieksekusi. Periksa instruksi, ikuti" " fungsi pemanggil, baca konstanta numerik, dan periksa C yang dipulihkan." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Analisis panduan program kode mesin" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Ikuti ekspor CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4881,14 +4889,14 @@ msgstr "" "proses utama. Gunakan REA untuk menghubungkan API, saluran IPC, dan penulis " "file." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Panduan JavaScript & Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4896,17 +4904,17 @@ msgstr "" "Untuk aplikasi paket yang lebih besar, ikuti {ph0} Jembatan papan klip " "Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Perilaku peramban" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Amati satu klik" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4915,7 +4923,7 @@ msgstr "" "Buka contoh Catatan kerja, tangkap permintaan ekspor, dan temukan kode yang " "mengubah responsnya menjadi unduhan." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Panduan pengamatan browser" @@ -4934,12 +4942,12 @@ msgstr "" "Pelajari REA melalui contoh singkat yang berhasil: perhitungan asli, ekspor " "Electron CSV, dan permintaan browser." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -4948,20 +4956,20 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Rumah{ph1} / {ph2}Panduan{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Lacak sebuah Electron {ph0} Ekspor CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4970,14 +4978,14 @@ msgstr "" "Ikuti satu klik tombol dari page API, melalui Electron IPC, ke CSV file " "writer." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "Dalam panduan ini" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4985,7 +4993,7 @@ msgstr "{ph0}Contohnya{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4993,7 +5001,7 @@ msgstr "{ph0}Tanyakan pada agen Anda{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5001,7 +5009,7 @@ msgstr "{ph0}Lacak kode ekspor{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5009,20 +5017,20 @@ msgstr "{ph0}Coba contohnya{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Periksa penulis CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Ke mana perginya \"Catatan ekspor\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5034,7 +5042,7 @@ msgstr "" "catatan{ph1} memanggil API di halaman, masuk ke proses utama, dan menulis " "CSV . Perilaku tersebut tersebar di beberapa file." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "Ekspor CSV di seluruh proses Electron" @@ -5048,7 +5056,7 @@ msgstr "Ekspor CSV di seluruh proses Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5065,7 +5073,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5082,7 +5090,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5095,13 +5103,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} memformat catatan → {ph1} menulis {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5112,14 +5120,14 @@ msgstr "" "API yang terbuka. Jalur disimpulkan dari kode; tangkapan waktu proses dapat " "memeriksa apa yang dijalankan." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Tanyakan tentang ekspor CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5137,14 +5145,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Salin" @@ -5155,7 +5163,7 @@ msgstr "Salin" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5166,7 +5174,7 @@ msgstr "" "mengekspor catatan di aplikasi ini. Di mana CSV dibuat?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5174,7 +5182,7 @@ msgid "" "{ph0}." msgstr "Contoh prompt. Sertakan jalur absolut ke folder aplikasi atau {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5185,17 +5193,17 @@ msgstr "" "proses. Agen Anda menggunakan peta tersebut untuk mempersempit penyelidikan " "ke fitur ekspor." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Lacak kode ekspor" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Halaman tersebut memanggil API kecil" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5206,7 +5214,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5218,7 +5226,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5228,7 +5236,7 @@ msgstr "" "Membaca handler menjawab pertanyaan awal: {ph0} memformat catatan, dan " "proses utama menulis {ph1} ke dalam folder Unduhan pengguna." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5237,7 +5245,7 @@ msgstr "" "Direkam oleh REA 4.1.0 pada contoh yang dapat diunduh di bawah ini. Lokasi " "sumber menyertai temuan API, saluran, dan penangan." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Analisis sendiri contohnya" @@ -5245,25 +5253,25 @@ msgstr "Analisis sendiri contohnya" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Unduh contoh ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Jelajahi enam file sumber" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Analisis aplikasi statis" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5274,7 +5282,7 @@ msgstr "" " satu saluran IPC dan satu pengendali yang cocok di {ph0}. Lokasi sumber ada" " di {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5285,13 +5293,13 @@ msgstr "" "atau jalur ASAR. Agen dapat mengikuti string literal, nama API, atau saluran" " IPC dengan alat penelusuran fitur REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Periksa penulis CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5301,7 +5309,7 @@ msgstr "" "Ikuti {ph0} untuk pawangnya. Input mana yang mencapai penulis CSV, dan apa " "yang terjadi jika penulisan file gagal?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5316,7 +5324,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5330,7 +5338,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5344,7 +5352,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5370,32 +5378,32 @@ msgstr "" "dengan REA . Termasuk file contoh yang dapat diunduh dan hasil analisis yang" " diverifikasi." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Salin contoh prompt" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Salin analisis aplikasi statis" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -5404,20 +5412,20 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}Rumah{ph1} / {ph2}Panduan{ph3} / Analisis program kode mesin" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "Recover DX-Ball{ph0}perhitungan posisi suara kiri/kanan." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5426,14 +5434,14 @@ msgstr "" "Periksa instruksi asli, identifikasi input dan konstanta, lalu periksa C " "yang dipulihkan." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "Dalam panduan ini" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5441,7 +5449,7 @@ msgstr "{ph0}Contohnya{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5449,7 +5457,7 @@ msgstr "{ph0}Tanyakan pada agen Anda{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5457,7 +5465,7 @@ msgstr "{ph0}Baca hasil REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5465,18 +5473,18 @@ msgstr "{ph0}Pulihkan dan periksa{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Gunakan biner Anda sendiri{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Hitung posisi suara stereo kiri / kanan" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5487,7 +5495,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5499,7 +5507,7 @@ msgstr "" "REA juga mengembalikan instruksi dan fungsi pemanggilnya, yang memberi agen " "cara untuk menyelidiki aritmatika yang hilang." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Baru mengenal istilah ini?" @@ -5508,7 +5516,7 @@ msgstr "Baru mengenal istilah ini?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5520,7 +5528,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5533,7 +5541,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5546,7 +5554,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5558,7 +5566,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5568,7 +5576,7 @@ msgstr "" "{ph0}Konstanta:{ph1} nomor tetap yang disimpan dalam program, dibaca sebagai" " byte mentah dan diterjemahkan." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Tiga bukti, satu perhitungan" @@ -5579,7 +5587,7 @@ msgstr "Tiga bukti, satu perhitungan" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5596,7 +5604,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5614,7 +5622,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5624,7 +5632,7 @@ msgstr "" "{ph0}03 * Byte data{ph1}{ph2}Konstanta numerik{ph3}{ph4}Byte yang " "direferensikan didekode ke {ph5}, {ph6} dan nilai skala.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5633,7 +5641,7 @@ msgstr "" "REA menyediakan instruksi, hubungan panggilan fungsi, dan byte. Agen " "menafsirkannya bersama-sama." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Tanyakan tentang perilakunya" @@ -5642,7 +5650,7 @@ msgstr "Tanyakan tentang perilakunya" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5652,19 +5660,19 @@ msgstr "" "Setelah {ph0}menghubungkan REA ke agen Anda{ph1} dan {ph2}menyiapkan alat " "analisis program kode mesin{ph3}, berikan executable lokal dan pertanyaan:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Alat analisis mana yang harus saya gunakan?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA membutuhkan salah satunya untuk membaca program asli:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5678,7 +5686,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5691,7 +5699,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5702,7 +5710,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5718,14 +5726,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Salin" @@ -5736,7 +5744,7 @@ msgstr "Salin" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5747,7 +5755,7 @@ msgstr "" "pemosisian suara stereo. Jelaskan perhitungannya dan tunjukkan " "kodenya.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5759,7 +5767,7 @@ msgstr "" "sendiri, atau ajukan pertanyaan yang sama tentang program Windows kecil " "lainnya yang Anda miliki." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Bagaimana cara mendapatkan path lengkap file?" @@ -5768,7 +5776,7 @@ msgstr "Bagaimana cara mendapatkan path lengkap file?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5783,7 +5791,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5795,7 +5803,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5805,17 +5813,17 @@ msgstr "" "{ph0}Sistem apa pun:{ph1} seret file ke jendela terminal dan jalurnya " "muncul." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Baca hasil REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Baca inputnya" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5825,13 +5833,13 @@ msgstr "" "floating-point. Ini adalah input yang tidak ada dari tampilan pseudocode " "pertama." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Ikuti fungsi pemanggil" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5842,12 +5850,12 @@ msgstr "" "sebelumnya mengalikan koordinat ubin dengan 30; menambahkan {ph0} (20) " "memberikan posisi layar bata." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Baca konstanta yang dirujuk" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5856,12 +5864,12 @@ msgstr "" "Aritmatika mereferensikan alamat-alamat ini. Membaca byte memberikan nilai " "aktual; urutan instruksi memberi tahu agen bagaimana mereka digunakan." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Tulis dan periksa fungsi yang dipulihkan" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5872,7 +5880,7 @@ msgstr "" " sebelum konversi bilangan bulat. Perhitungan menempatkan bagian tengah " "layar di tengah bidang stereo." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5885,20 +5893,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Lihat investigasi lengkap dan perbandingan assembly-to-C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Cobalah dengan biner Anda sendiri" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5912,7 +5920,7 @@ msgstr "" "awal yang berguna termasuk \"Bagaimana file ini diuraikan?\"atau\" Fungsi " "mana yang menangani tindakan menu ini?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5921,13 +5929,13 @@ msgstr "" "Jika Anda sudah mengetahui nama atau alamat fungsi, Anda dapat menanyakannya" " dari terminal. Untuk instalasi Ghidra yang dikonfigurasi:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Analisis fungsi" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5941,7 +5949,7 @@ msgstr "" "sesinya. Kueri MCP agen Anda menggunakan kembali biner yang diimpor saat " "sesi tersebut dibuka." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5965,50 +5973,50 @@ msgstr "" "Pulihkan perhitungan asli dengan REA : periksa instruksi, ikuti fungsi " "pemanggil, baca konstanta, dan periksa C yang direkonstruksi." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Analisis program kode mesin" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Salin contoh prompt" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Salin analisis fungsi" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Lewati ke konten" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Siapkan REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6016,7 +6024,7 @@ msgstr "{ph0}Siapkan REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6024,7 +6032,7 @@ msgstr "{ph0}Apa itu RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6032,7 +6040,7 @@ msgstr "{ph0}Bagaimana REA membantu{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6040,7 +6048,7 @@ msgstr "{ph0}Permainan dinosaurus{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6048,7 +6056,7 @@ msgstr "{ph0}Kalkulator{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6056,7 +6064,7 @@ msgstr "{ph0}Coba REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6064,7 +6072,7 @@ msgstr "{ph0}Pelajari lebih lanjut{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6072,25 +6080,25 @@ msgstr "{ph0}Bantuan & umpan balik{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Komunitas{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Rekayasa balik, dengan agen pengkodean Anda" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Cari tahu bagaimana{ph0}perangkat lunak bekerja." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6101,7 +6109,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6109,13 +6117,13 @@ msgstr "Sudah tahu RE? {ph0}Lewati ke panduan analisis →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Ingin lebih dalam? {ph0}Baca Blognya →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Tempel prompt ini ke agen pemrograman Anda:" @@ -6128,38 +6136,38 @@ msgstr "Tempel prompt ini ke agen pemrograman Anda:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Salin" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Atau jalankan perintah ini di terminal:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Periksa dan setujui rencana perubahan, lalu mulai ulang agen Anda." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Apa itu rekayasa balik?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6174,7 +6182,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6186,7 +6194,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6194,7 +6202,7 @@ msgstr "Sebelum REA · Anda menyelidikinya {ph0}sendiri{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6202,7 +6210,7 @@ msgstr "{ph0}01{ph1} Dekode cabang" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6210,7 +6218,7 @@ msgstr "{ph0}02{ph1} Melacak panggilan" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6220,20 +6228,20 @@ msgstr "{ph0}03{ph1} Pulihkan aturan" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}x64 asli * instruksi yang dipilih{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * Cabang mana?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6242,29 +6250,29 @@ msgid "" msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Dua lompatan ke tempat yang sama. Operator mana ini?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Cari ID perintah, lalu beri label pada cabang." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Membagi ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Kalikan ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Apa yang dilakukan fungsi yang dipanggil?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6274,24 +6282,24 @@ msgstr "" "\"100 sudah jelas. Panggilan itu hanya alamat. {ph0}Yang mana yang membelah?" " Nilai mana yang masuk?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Periksa fungsi pembantu dan lacak nilai yang disimpan." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Membagi" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 · Apa aturannya?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6301,19 +6309,19 @@ msgstr "" "\"Jalur ini dikalikan dengan masukan lainnya. Jadi {ph0}10% berarti 10% dari" " 200{ph1} setelah +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Beri nama operan dan periksa kedua jalur operator." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Penalaran ahli ilustratif" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6325,20 +6333,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Dengan REA · Anda bertanya kepada {ph0}agen Anda{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Cukup satu prompt." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6352,20 +6360,20 @@ msgstr "Tanyakan kepada agen Anda {ph0}dengan bahasa sehari-hari.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Contoh prompt * Kalkulator" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Contoh jawaban * berdasarkan temuan" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6373,22 +6381,22 @@ msgid "" msgstr "" "Setelah +, tombol % mengambil {ph0}persentase dari angka pertama.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA menyediakan" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Instruksi pawang, kode yang didekompilasi, dan panggilan." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Agen Anda menjelaskan" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "" @@ -6397,7 +6405,7 @@ msgstr "" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6410,7 +6418,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6420,38 +6428,38 @@ msgstr "" "{ph0}Mari kita coba dua contoh.{ph1} Ubah kecepatan permainan, lalu kembali " "ke Kalkulator dan buat kembali tombol % - nya." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Contoh 01 * Game dinosaurus Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Mengapa dinosaurus semakin cepat?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Tujuan" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "" "Bangun kembali game dengan {ph0}kecepatan yang dapat disesuaikan.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Mengapa merekayasa baliknya?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6462,49 +6470,49 @@ msgstr "" "permainan lari{ph1}: seberapa cepat dimulai, seberapa banyak meningkat dan " "kapan berhenti." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Mainkan hasil rekonstruksi" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Main" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Lompat ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Mulai ulang" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Kecepatan" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Gunakan aturan akselerasi yang dipulihkan" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Aturan awal: mulai dari 6, lalu tingkatkan menjadi 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Gerakkan penggeser untuk mengatur kecepatan Anda sendiri. Ruang atau " "Lompatan membersihkan kaktus." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6513,14 +6521,14 @@ msgstr "" "Aktifkan JavaScript untuk memainkan rekonstruksi. Kode dan penjelasan di " "atas tetap dapat dibaca." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA mengembalikan" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6539,7 +6547,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6552,7 +6560,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6566,7 +6574,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6579,7 +6587,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6589,12 +6597,12 @@ msgstr "" "{ph0}Mulai dari 6.{ph1} Tambahkan {ph2}0.001{ph3} setiap pembaruan tanpa " "tabrakan, sementara kecepatan di bawah {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Buka lab kecepatan →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Apa yang dilakukan setiap bagian" @@ -6605,7 +6613,7 @@ msgstr "Apa yang dilakukan setiap bagian" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6622,7 +6630,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6639,7 +6647,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6649,13 +6657,13 @@ msgstr "" "{ph0}03 * Kamu{ph1}{ph2}Mengubah kecepatan dan bermain{ph3}{ph4}Coba " "akselerasi asli, lalu pilih kecepatan Anda sendiri.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Lihat skrip, cek, dan cara mencoba analisisnya" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6665,7 +6673,7 @@ msgstr "" "REA memeriksa edisi browser HTTP melalui koneksi debugging lokal dan " "mengembalikan yang dimuat {ph0}, termasuk sumber dan intisarinya." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6679,7 +6687,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6696,7 +6704,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6714,7 +6722,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6723,19 +6731,19 @@ msgstr "" "{ph0}Kode kecepatan yang diperiksa{ph1} · {ph2} Penulis Chromium * Lisensi " "BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Contoh 02 * Kalkulator Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Buat ulang tombol % Kalkulator." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6744,7 +6752,7 @@ msgstr "Buat kalkulator kecil yang menangani {ph0}keduanya + dan × {ph1}" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6755,29 +6763,29 @@ msgstr "" "memeriksa aplikasi yang diinstal untuk menemukan angka persentase yang " "diterapkan." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Coba perhitungannya" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Reset" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% dari 200 = 20. Kemudian 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Ilustrasi interaktif dari aturan persentase yang diinspeksi." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6789,7 +6797,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6803,7 +6811,7 @@ msgstr "Untuk contoh ini, {ph0} dan {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6819,7 +6827,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6830,7 +6838,7 @@ msgstr "" "{ph0}›{ph1}{ph2}Gunakan REA untuk memeriksa tombol % Kalkulator Windows. " "Pulihkan aturan setelah + dan × {ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Dengan +" @@ -6838,13 +6846,13 @@ msgstr "Dengan +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Ambil 10% dari angka pertama.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Dengan ×" @@ -6852,13 +6860,13 @@ msgstr "Dengan ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Ubah 10% menjadi 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Dari aplikasi yang diinstal ke tombol % yang berfungsi" @@ -6870,7 +6878,7 @@ msgstr "Dari aplikasi yang diinstal ke tombol % yang berfungsi" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6888,7 +6896,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6900,12 +6908,12 @@ msgstr "" "aturan{ph3}{ph4}Periksa silang cabang dengan sumber Microsoft, lalu coba + " "dan × {ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Lihat kode sebenarnya dan bagaimana jawabannya diperiksa" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6926,7 +6934,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6936,17 +6944,17 @@ msgstr "" "{ph0}Implementasi persentase{ph1} · {ph2}Kasus uji Microsoft{ph3} · " "{ph4}Panduan penyiapan asli{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Investigasi pertamamu" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Coba REA di aplikasi kecil." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6955,12 +6963,12 @@ msgstr "" "Unduh contoh Catatan kami, lacak ekspor CSV - nya, dan periksa satu input " "yang diubah." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Coba contoh terpandu" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Ingin mempelajari lebih lanjut?" @@ -6969,7 +6977,7 @@ msgstr "Ingin mempelajari lebih lanjut?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6989,13 +6997,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Contoh prompt * Situs web" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Ya, yang ini." @@ -7008,7 +7016,7 @@ msgstr "Ya, yang ini." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7022,7 +7030,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7036,23 +7044,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Lihat studi kasus DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Untuk langkah penyiapan dan analisis, pilih target Anda:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Program kode mesin" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7061,17 +7069,17 @@ msgstr "" "Periksa fungsi, string, referensi, dan hubungan pemanggilan fungsi di " "executable dan pustaka." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Analisis panduan program kode mesin" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7080,17 +7088,17 @@ msgstr "" "Modul peta, rute, IPC, dan dependensi asli dari folder aplikasi atau arsip " "ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Alur kerja aplikasi" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Aktivitas browser & waktu proses" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7099,12 +7107,12 @@ msgstr "" "Tangkap browser atau aktivitas proses yang dipilih, lalu bandingkan hasilnya" " di seluruh proses." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Panduan pengamatan browser" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Ada pertanyaan?" @@ -7115,7 +7123,7 @@ msgstr "Ada pertanyaan?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7125,12 +7133,12 @@ msgstr "" "{ph0}Baca FAQ{ph1}, {ph2}ngobrol dengan kami di Discord {ph3}, atau " "{ph4}buka masalah GitHub{ph5} untuk bug dan permintaan fitur." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Gabung komunitas" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7154,27 +7162,27 @@ msgstr "" "pengkodean Anda. Ikuti panduan yang jelas dan coba contoh interaktif dengan " "REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Salin prompt instalasi REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Salin perintah pengaturan" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Ikuti analisis Kalkulator manual" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Salin pertanyaan persentase Kalkulator" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7183,37 +7191,37 @@ msgstr "" "Mini-game dinosaurus. Gunakan tombol Lompat atau tekan Spasi saat permainan " "difokuskan." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Salin prompt analisis dinosaurus" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Pilih perhitungan" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Salin prompt analisis Kalkulator" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Salin prompt proyek situs web" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Salin prompt rekonstruksi game" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -7222,25 +7230,25 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Rumah{ph1} / {ph2}Menampilkan{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Studi kasus * Pengautentikasi Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Bagaimana cara kerja autentikator{ph0}buat kode masuk?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7250,17 +7258,17 @@ msgstr "" "perhitungan di Android APK, lalu bangun kembali dengan jam yang dapat Anda " "kendalikan." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * Rilis resmi APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Lihat Aegis di GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Dari APK ke kode yang dapat Anda reproduksi" @@ -7271,7 +7279,7 @@ msgstr "Dari APK ke kode yang dapat Anda reproduksi" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7289,7 +7297,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7307,7 +7315,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7319,14 +7327,14 @@ msgstr "" "kodenya.{ph3}{ph4}Demo browser baru mereproduksi aturan dan memeriksanya " "terhadap kasus referensi publik.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "Dalam studi kasus ini" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7334,7 +7342,7 @@ msgstr "{ph0}Tanyakan pada agen Anda{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7342,7 +7350,7 @@ msgstr "{ph0}Coba pembuat kode{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7350,7 +7358,7 @@ msgstr "{ph0}Temukan kodenya dengan REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7358,7 +7366,7 @@ msgstr "{ph0}Baca perhitungannya{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7366,20 +7374,20 @@ msgstr "{ph0}Periksa rekonstruksi{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Periksa sendiri APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Tanyakan pada agen Anda" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7397,21 +7405,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Salin" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7421,14 +7429,14 @@ msgstr "" "Contoh prompt untuk APK yang diunduh, dengan analisis Android REA " "dikonfigurasi. {ph0}Dapatkan APK dan pengaturan analisis ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Coba pembuat kode" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7440,33 +7448,33 @@ msgstr "" "menggabungkan nomor blok dengan kunci akun untuk menghasilkan kode. Kunci " "dan blok yang sama menghasilkan kode yang sama." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Pindahkan jam melintasi 60 detik" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Waktu" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "detik" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Jam contoh kami yang dapat disesuaikan" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "blok 30 detik" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Blok" @@ -7475,35 +7483,35 @@ msgstr "Blok" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 detik{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Kode yang dihasilkan" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Kunci akun + blok →" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Contoh waktu, dalam detik" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 detik" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 detik" @@ -7512,7 +7520,7 @@ msgstr "60 detik" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7524,7 +7532,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7534,7 +7542,7 @@ msgstr "" "Kuncinya adalah tetap, publik {ph0}RFC 6238 datasheet{ph1}. Demo " "mengimplementasikan perhitungan yang dipulihkan dari APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7543,18 +7551,18 @@ msgstr "" "Diagram menunjukkan hasilnya pada 59 detik. Aktifkan JavaScript untuk " "mengubah jam." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Temukan kodenya dengan REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Persempit APK menjadi tiga kelas" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7564,14 +7572,14 @@ msgstr "" "{ph0} adalah kandidat perhitungan; dua lainnya menyangkut bilah kemajuan dan" " akun yang diimpor. TOTP berarti kata sandi satu kali berbasis waktu." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Hubungkan generator ke tampilan aplikasi" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7582,7 +7590,7 @@ msgstr "" "metode dasar. Memeriksa {ph0} kemudian menampilkan panggilan tampilan {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7592,14 +7600,14 @@ msgstr "" "Permintaan menunjukkan jalur input yang dipersingkat. Hasil nama kelas " "menghilangkan yang umum {ph0} awalan." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Baca perhitungannya" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7613,7 +7621,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7621,7 +7629,7 @@ msgstr "{ph0}01{ph1} Blok waktu" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7629,7 +7637,7 @@ msgstr "{ph0}02{ph1} Kunci + blok" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7637,7 +7645,7 @@ msgstr "{ph0}03{ph1} Enam digit" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7649,7 +7657,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7663,7 +7671,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7678,7 +7686,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7689,7 +7697,7 @@ msgstr "" "untuk tampilan. Panel kanan adalah ringkasan penjelasan. {ph0} Kode Aegis " "adalah GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Di dalam generator" @@ -7698,7 +7706,7 @@ msgstr "Di dalam generator" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7709,7 +7717,7 @@ msgstr "" "dari {ph2} dan mengembalikan badan ini; sumber aslinya memanggil helper " "{ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7726,20 +7734,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Bandingkan dengan sumber rilis yang cocok{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Periksa rekonstruksi" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7752,29 +7760,29 @@ msgstr "" "pada {ph0}133 kasus uji{ph1}, termasuk batas blok waktu dan kode yang " "dimulai dengan nol." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Contoh waktu" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Kode enam digit" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 detik" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1.111.111.109 detik" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7784,17 +7792,17 @@ msgstr "" "Generator juga cocok dengan enam kasus referensi SHA-1 yang diterbitkan di " "{ph0}RFC 6238{ph1}. Periksa implementasi browser terhadap mereka:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Jalankan pemeriksaan referensi" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Baca perhitungan demo" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7803,7 +7811,7 @@ msgstr "" "Kasus referensi menggunakan delapan digit. Cek tersebut juga memverifikasi " "hasil enam digit mereka." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7812,14 +7820,14 @@ msgstr "" "Verifikasi menjalankan metode Java yang diekstraksi dan demo baru. Android " "APK diperiksa secara statis." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Periksa sendiri APK" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7831,7 +7839,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7841,18 +7849,18 @@ msgstr "" "Analisis Android membutuhkan JDK 17 lengkap atau lebih baru. Pilih dengan " "{ph0} atau {ph1}. Kasus ini menggunakan JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Arahkan REA ke file penyedia dan periksa APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7864,7 +7872,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7874,7 +7882,7 @@ msgstr "" "Pertanyaan selanjutnya: {ph0}apa yang terjadi jika akun menggunakan delapan " "digit atau interval waktu yang berbeda?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Sumber" @@ -7890,7 +7898,7 @@ msgstr "Sumber" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7904,13 +7912,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}Kasus referensi RFC 6238{ph1} · {ph2}Data uji demo{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7935,37 +7943,37 @@ msgstr "" "Periksa Aegis Android APK dengan REA, pulihkan perhitungan kode masuk enam " "digitnya, dan coba rekonstruksi dengan jam yang dapat disesuaikan." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Studi kasus Aegis APK" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Salin prompt contoh Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Ikuti perhitungan kode masuk" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Salin perintah inspeksi APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -7974,26 +7982,26 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Rumah{ph1} / {ph2}Menampilkan{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Studi kasus * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Temukan bendera di{ph0}biner KKP." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8004,17 +8012,17 @@ msgstr "" "menjadi persamaan, dan menemukan masukan yang membuat program asli dicetak " "{ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "pemeriksa bendera kotak bertopeng * Mudah * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Lihat tantangan aslinya" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Dari biner ke jawaban yang dicentang" @@ -8025,7 +8033,7 @@ msgstr "Dari biner ke jawaban yang dicentang" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8042,7 +8050,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8060,7 +8068,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8072,7 +8080,7 @@ msgstr "" "{ph3}{ph4}Skrip Python memecahkan persamaan. REA menangkap program asli " "yang menerima hasilnya.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." @@ -8080,14 +8088,14 @@ msgstr "" "Tantangannya adalah oleh joseph, diterbitkan di repositori resmi " "DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "Dalam studi kasus ini" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8095,7 +8103,7 @@ msgstr "{ph0}Temukan kode pemeriksaan{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8103,7 +8111,7 @@ msgstr "{ph0}Baca satu topeng{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8111,7 +8119,7 @@ msgstr "{ph0}Perakitan ke kode yang dapat dibaca{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8119,7 +8127,7 @@ msgstr "{ph0}Selesaikan persamaannya{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8127,20 +8135,20 @@ msgstr "{ph0}Periksa jawabannya{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Cobalah sendiri{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Temukan kode pemeriksaan" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8158,17 +8166,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Salin" @@ -8179,7 +8187,7 @@ msgstr "Salin" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8191,7 +8199,7 @@ msgstr "" " benderanya. Jelaskan cara kerja pemeriksaan, lalu verifikasi jawabannya " "dengan program aslinya.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8200,12 +8208,12 @@ msgstr "" "Contoh prompt, dengan tantangan yang diunduh tersedia secara lokal dan " "analisis penyedia program kode mesin terhubung." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Ikuti prompt input ke fungsinya" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8214,14 +8222,14 @@ msgstr "" "Referensi memberi agen tempat untuk menyelidiki, meskipun nama fungsi asli " "yang dapat dieksekusi telah dihapus." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Baca pemeriksa dan dua pembantunya" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8234,7 +8242,7 @@ msgstr "" "nomor yang disimpan. Nya {ph0}- langkah byte melintasi {ph1} byte memberikan" " 26 topeng." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8243,12 +8251,12 @@ msgstr "" "Ini adalah hasil yang dipilih dari analisis REA baru. Jalur target lokal " "dipersingkat untuk ditampilkan; alamat mengacu pada gambar yang diimpor REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Satu cek mengungkapkan satu karakter" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8261,14 +8269,14 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "" "Pemeriksaan ketujuh hanya memilih satu posisi. {ph0}Sosok terbuka{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Baca topeng dan targetnya dari biner" @@ -8277,7 +8285,7 @@ msgstr "Baca topeng dan targetnya dari biner" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8290,12 +8298,12 @@ msgstr "" "endian. Bersama-sama, byte ini memberi tahu agen bahwa {ph2}, jadi karakter " "itu adalah {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Dari instruksi hingga pemeriksaan yang dapat dibaca" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8306,7 +8314,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8314,7 +8322,7 @@ msgstr "{ph0}01{ph1} Mulai" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8322,7 +8330,7 @@ msgstr "{ph0}02{ph1} Pilih" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8330,7 +8338,7 @@ msgstr "{ph0}03{ph1} Tambahkan" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8338,18 +8346,18 @@ msgstr "{ph0}04{ph1} Maju" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Bandingkan" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * instruksi asli yang dipilih" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Ringkasan satu cek C * yang dapat dibaca" @@ -8357,7 +8365,7 @@ msgstr "Ringkasan satu cek C * yang dapat dibaca" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8366,7 +8374,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8378,7 +8386,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8390,7 +8398,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8404,7 +8412,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8414,7 +8422,7 @@ msgstr "" "{ph0}05 * Bandingkan dengan target yang disimpan.{ph1} Fungsi pemanggil " "menerima jumlah dalam {ph2}. Ketidakcocokan melompat ke {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8423,12 +8431,12 @@ msgstr "" "Instruksi datang dari pembantu penjumlahan dan fungsi pemanggilnya. C adalah" " ringkasan penjelasan dengan nama deskriptif dan loop 36 sel yang diratakan." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Selesaikan 26 persamaan tersebut" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8440,13 +8448,13 @@ msgstr "" "tumpang tindih memberikan persamaan yang dapat diselesaikan bersama oleh " "skrip Python kecil." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * kutipan pemecah" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8460,19 +8468,19 @@ msgstr "" " bendera dengan huruf, angka,garis bawah, dan tanda kurung. Unduhan lengkap " "mencakup semua 26 topeng dan target." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Unduh pemecah lengkap" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Periksa jawabannya dengan program aslinya" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8484,47 +8492,47 @@ msgstr "" "diselesaikan. Mengubah satu karakter yang dipilih dari {ph0} untuk {ph1} " "membuat jumlah pertama 1440, bukan 1441, dan program menolaknya." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Masukan" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Keluaran yang diamati" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Kode keluar" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Bendera pemecah" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Satu karakter berubah" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Tampilkan bendera yang dipulihkan dan keluaran yang diambil" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * keluaran program asli" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Salin bendera" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8533,12 +8541,12 @@ msgstr "" "Nilai yang dipulihkan juga cocok dengan tanda dalam metadata tantangan yang " "diterbitkan penyelenggara, dicentang setelah menyelesaikan biner." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Sumber, identitas target, dan detail analisis" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8549,7 +8557,7 @@ msgstr "" "4.1.0 dengan Ghidra 12.1.4 pada Linux x64. Binernya adalah ELF x86-64 yang " "dilucuti, 15.248 byte." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8572,7 +8580,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8582,12 +8590,12 @@ msgstr "" "{ph0}Bandingkan dengan sumber penyelenggara{ph1} · {ph2}Tantang metadata dan" " bendera{ph3} · {ph4} Catatan bukti REA{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Cobalah sendiri" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8597,13 +8605,13 @@ msgstr "" "atas untuk menyelidiki dengan agen Anda, atau jalankan skrip yang " "disertakan." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * selesaikan dan jalankan" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8615,7 +8623,7 @@ msgstr "" "kebutuhan Python dan {ph0}. Menjalankan executable asli membutuhkan Linux " "x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Siapkan REA dengan agen pengkodean Anda" @@ -8636,28 +8644,28 @@ msgstr "" "DownUnderCTF. Temukan fungsi pemeriksaan, ekstrak mask, dan bandingkan flag " "yang dipulihkan dengan program asli." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Studi kasus pemeriksa bendera KKP" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Salin permintaan contoh KKP" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "" "Persamaan topeng KKP; gulir secara horizontal pada layar yang lebih kecil" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8668,42 +8676,42 @@ msgstr "" " sel itu yang berkontribusi pada jumlah tersebut. Kode karakter yang " "diperlukan adalah 55, yang berarti karakternya adalah 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Ikuti pemeriksaan KKP" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Salin perakitan KKP" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Salin cek KKP yang dapat dibaca" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Salin kutipan pemecah KKP" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Salin bendera yang dipulihkan" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Salin perintah pemecah KKP" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -8712,25 +8720,25 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Rumah{ph1} / {ph2}Menampilkan{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Studi kasus * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Membangun kembali DX-Ball {ph0}dari executable-nya." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8739,14 +8747,14 @@ msgstr "" "Tujuannya adalah versi C yang dapat dipertahankan dari game Windows tahun " "1996. REA membantu agen memeriksa yang asli, satu fungsi pada satu waktu." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8758,14 +8766,14 @@ msgstr "" "instruksi, fungsi pemanggil, dan pembacaan data; proyek rekonstruksi " "mengimplementasikan dan menguji hasilnya. {ph0}Sosok terbuka{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "Dalam studi kasus ini" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8773,7 +8781,7 @@ msgstr "{ph0}Proyek ini{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8781,7 +8789,7 @@ msgstr "{ph0}Panci suara{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8789,23 +8797,23 @@ msgstr "{ph0}Memeriksa hasilnya{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Lanjutkan pekerjaan{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "fungsi C yang dipertahankan" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "perbandingan dengan kode asli" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "fungsi dengan byte terkompilasi yang cocok" @@ -8816,7 +8824,7 @@ msgstr "fungsi dengan byte terkompilasi yang cocok" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8826,12 +8834,12 @@ msgstr "" "Pos pemeriksaan proyek: 7 Oktober 2026. {ph0}Buku besar kemajuan{ph1} · " "{ph2}Cakupan pengujian{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Proyek sejauh ini" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8846,12 +8854,12 @@ msgstr "" " berlanjut dengan fisika bola dan dayung, penanganan power-up, dan integrasi" " Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Menemukan perhitungan posisi suara kiri/kanan" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8870,17 +8878,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Salin" @@ -8891,7 +8899,7 @@ msgstr "Salin" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8902,7 +8910,7 @@ msgstr "" "pemosisian suara stereo. Jelaskan perhitungannya dan tunjukkan " "kodenya.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8913,7 +8921,7 @@ msgstr "" "Investigasi di bawah ini menunjukkan pertanyaan REA dan bukti di balik " "jawabannya." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8927,7 +8935,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8941,12 +8949,12 @@ msgstr "" "operasi floating-point. Ketidaksesuaian itu memberi agen alasan konkret " "untuk terus menyelidiki." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "Tampilan dekompiler pertama" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8955,18 +8963,18 @@ msgstr "" "Outputnya menunjukkan panggilan konversi. Membaca petunjuk di bawah ini " "mengungkapkan masukan dan perhitungan yang memanggil panggilan itu." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Tiga pertanyaan dijawab melalui REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Pulihkan input yang hilang" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8977,14 +8985,14 @@ msgstr "" "Di sini, {ph0} memperlihatkan input integer yang hilang dari tampilan " "decompiler." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Ikuti fungsi pemanggil untuk memahami masukannya" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8995,12 +9003,12 @@ msgstr "" "instruksi sebelumnya {ph0} sebesar 30; menambahkan 20 memberikan koordinat " "layar bata, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Baca nilai di balik alamat memori" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9009,12 +9017,12 @@ msgstr "" "Byte yang dikembalikan menetapkan dua konstanta aritmatika dan skala pan " "awal. Agen sekarang memiliki nilai yang diperlukan untuk ekspresi C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Dari temuan REA hingga C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9025,7 +9033,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9033,7 +9041,7 @@ msgstr "{ph0}01{ph1} Masukan" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9041,7 +9049,7 @@ msgstr "{ph0}02{ph1} Lipat gandakan" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9049,7 +9057,7 @@ msgstr "{ph0}03{ph1} Kurangi" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9057,18 +9065,18 @@ msgstr "{ph0}04{ph1} Skala" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Kembali" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "x86 asli · kutipan" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Direkonstruksi C" @@ -9078,7 +9086,7 @@ msgstr "Direkonstruksi C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9098,7 +9106,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9115,7 +9123,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9133,7 +9141,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9150,7 +9158,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9162,7 +9170,7 @@ msgstr "" "{ph3}, diidentifikasi dalam hasil callee REA. C memberikan hasil ke {ph4}; " "perbandingan original-x86 periksa nilai yang dikembalikan." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9173,23 +9181,23 @@ msgstr "" "Daftar lengkap di bawah ini juga mencakup penyimpanan intervensi dan " "penyiapan serta pembersihan fungsi." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Perakitan lengkap dan bukti pendukung" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "Hasil REA · 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Apa yang disediakan fungsi pemanggil" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9199,54 +9207,54 @@ msgstr "" "Fungsi pukulan bata di {ph0} menskalakan koordinat ubinnya sebesar 30, " "menambahkan 20, lalu mendorongnya sebelum panggilan:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Apa yang dibaca data menetapkan" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "Pembacaan byte REA, diterjemahkan sebagai ganda little-endian" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Alamat" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Nilai" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Digunakan untuk" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Perkalian pertama" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Pengurangan" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} awalnya" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Skala panci tersimpan" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9262,7 +9270,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9272,12 +9280,12 @@ msgstr "" "{ph0}Sumber yang dipelihara{ph1} · {ph2}Catatan investigasi dan referensi " "bukti{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Memeriksa fungsi yang dipulihkan" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9287,12 +9295,12 @@ msgstr "" " dengan aslinya, dan byte yang dikompilasi cocok dengan yang dapat " "dieksekusi." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 kasus perilaku" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9303,12 +9311,12 @@ msgstr "" "pengembaliannya dengan C. Pengujian mencakup setiap posisi bilangan bulat " "dari 0 hingga 640 pada lima skala panci: 0, 0,5, 1, 20, dan -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 byte yang cocok" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9319,7 +9327,7 @@ msgstr "" "kompilator cocok dengan fungsi lengkap setelah menerapkan relokasi yang " "ditinjau dan memeriksa konstanta yang direferensikan." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9334,18 +9342,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Baca detail pemutaran ulang kompiler{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Lanjutkan penyelidikan" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9356,7 +9364,7 @@ msgstr "" "dan pembuatan bonus: periksa fungsi yang relevan, pulihkan status dan " "dependensinya, lalu bandingkan implementasinya dengan aslinya." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9365,7 +9373,7 @@ msgstr "" "Untuk memeriksa sendiri fungsi sound-pan, ikuti petunjuk penyiapan proyek " "DX-Ball dan berikan target aslinya yang sesuai. Lalu lari:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "Dalam checkout DX-Ball" @@ -9374,7 +9382,7 @@ msgstr "Dalam checkout DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9388,7 +9396,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9404,7 +9412,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9429,7 +9437,7 @@ msgstr "" "original-x86 yang dipertahankan, dan pencocokan byte fungsi yang " "dikompilasi." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9437,7 +9445,7 @@ msgstr "" "DX-Ball sound-pan investigation; gulir secara horizontal pada layar yang " "lebih kecil" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9453,70 +9461,70 @@ msgstr "" "x86 asli dalam 3.205 kasus dan oleh replay kompiler VC4. 0 yang cocok dengan" " 63 byte." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Studi kasus rekonstruksi DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Salin contoh prompt" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Ikuti perhitungan posisi suara kiri / kanan" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Salin kutipan perakitan asli" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Salin fungsi panci suara" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Salin rakitan panci suara lengkap" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Salin perintah analisis DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Lewati ke konten" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Rumah{ph1} / Menampilkan" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "Studi kasus REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9525,17 +9533,17 @@ msgstr "" "Android, game, Electron, dan tantangan KKP, dengan kode, angka, dan hasil " "yang dicentang." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * Analisis APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Cara autentikator membuat kode masuk" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9546,22 +9554,22 @@ msgstr "" "metode pembuatan dengan REA, lalu pindahkan jam demo untuk melihat mengapa " "kode berubah setiap 30 detik." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Baca studi kasus Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "KKP * Analisis program kode mesin" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Selesaikan pemeriksa bendera KKP" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9572,22 +9580,22 @@ msgstr "" "pemeriksaannya, ubah mask dan jumlah menjadi persamaan, lalu verifikasi flag" " yang diselesaikan dengan program aslinya." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Baca studi kasus KKP" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Asli * Rekonstruksi" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "Perhitungan posisi suara kiri/kanan DX-Ball" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9599,22 +9607,22 @@ msgstr "" " C kecil, diperiksa terhadap perilaku asli dan semua 63 byte yang " "dikompilasi." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Baca studi kasus DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Penelusuran fitur" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Bagaimana Notion menyalin teks dan HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9625,22 +9633,22 @@ msgstr "" " Ikuti pembungkus IPC-nya ke papan klip sistem, lalu lihat bagaimana penanda" " HTML kecil menyimpan data blok kaya yang terhubung ke salinan." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Baca studi kasus Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * Rekonstruksi" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Bagaimana TH04 mengarahkan cincin peluru" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9651,17 +9659,17 @@ msgstr "" "pembagian, dan koordinatnya dengan C++ yang dapat dibaca, lalu lihat " "bagaimana mereka menghasilkan cincin yang ditujukan untuk pemain." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Baca studi kasus TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Panduan langkah demi langkah" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9670,7 +9678,7 @@ msgstr "" "Panduan berjalan melalui perhitungan asli, ekspor Electron, dan permintaan " "browser. Masing-masing dimulai dengan target yang cepat dan konkret." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Baca panduannya" @@ -9689,12 +9697,12 @@ msgstr "" "Ikuti investigasi REA melalui kode, angka, dan demo: autentikator Android, " "DX-Ball , Notion, TH04, dan pemeriksa bendera DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -9703,25 +9711,25 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Rumah{ph1} / {ph2}Menampilkan{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Studi kasus * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Bagaimana salinan Notion{ph0}teks dan HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9730,12 +9738,12 @@ msgstr "" "Lacak panggilan papan klip dari API halaman Notion, melalui proses pramuat " "dan utama, ke penulis papan klip Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Desktop 7.6.1 * JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Jembatan di dalam paket desktop Notion" @@ -9747,7 +9755,7 @@ msgstr "Jembatan di dalam paket desktop Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9764,7 +9772,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9781,7 +9789,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9798,7 +9806,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9809,13 +9817,13 @@ msgstr "" " dan HTML yang disediakan.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Satu saluran bergabung dengan kedua sisi: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9825,14 +9833,14 @@ msgstr "" "proses utama. Menyelesaikan pembungkus mengungkapkan panggilan Electron di " "balik nama-nama itu." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "Dalam studi kasus ini" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9840,7 +9848,7 @@ msgstr "{ph0}Ikuti jembatan papan klip{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9848,19 +9856,19 @@ msgstr "{ph0}Menjaga struktur blok{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Lebih banyak contoh dan sumber{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Ke mana perginya operasi penyalinan?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9880,17 +9888,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Salin" @@ -9901,7 +9909,7 @@ msgstr "Salin" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9912,7 +9920,7 @@ msgstr "" " HTML ke papan klip sistem. Tunjukkan kode pada setiap " "langkah.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9921,12 +9929,12 @@ msgstr "" "Contoh prompt dengan paket aplikasi lokal Notion tersedia untuk agen " "pengkodean Anda." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA menemukan tempat untuk mulai membaca" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9937,13 +9945,13 @@ msgstr "" " dan panggilan yang mengirimkan permintaan IPC. Kedua temuan datang dengan " "rentang sumber dalam bundel yang diperkecil:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "Temuan REA →" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9957,7 +9965,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9971,12 +9979,12 @@ msgstr "" "sesuatu yang tepat untuk dicari di bundel utama. Empat kutipan di bawah ini " "menunjukkan rute yang menghubungkannya." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Empat potongan kode pendek" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9985,13 +9993,13 @@ msgstr "" "Disederhanakan dari JavaScript yang dikemas, dengan nama variabel yang dapat" " dibaca. Anggota yang tidak terkait dihilangkan." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Mulai dari API yang diekspos ke halaman" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10001,13 +10009,13 @@ msgstr "" "Anggota ini menyediakan nama saluran. Implementasi dari {ph0} memberitahu " "kita bagaimana permintaan meninggalkan proses halaman." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Selesaikan pembungkus pramuat" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10017,14 +10025,14 @@ msgstr "" "Fungsi yang dikembalikan meneruskan argumen melalui IPC request-and-respons " "Electron. Sekarang kita bisa mencari {ph0} di sisi proses utama." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Periksa bagaimana penerima didaftarkan" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10034,12 +10042,12 @@ msgstr "" "Proses utama menggunakan pembungkus lain. Nya {ph0} metode mendaftarkan " "sebuah {ph1} penerima untuk saluran tersebut." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Temukan tulisan dan cek pengirimnya" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10050,13 +10058,13 @@ msgstr "" "yang disediakan ke API papan klip Electron. Saluran dan dua pembungkus yang " "diselesaikan menghubungkan metode yang diekspos ke panggilan ini." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Bagaimana blok yang disalin mempertahankan strukturnya?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10067,27 +10075,27 @@ msgstr "" "data blok secara lokal dan menempatkan ID di HTML yang disalin untuk " "menghubungkannya." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Tautan HTML ke data blok yang disimpan" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Baca ID HTML-nya" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Temukan ID lokal yang sama" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Pulihkan data blok Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10096,7 +10104,7 @@ msgstr "" "Teks ilustrasi dan ID. Pengujian modul yang direkam mengembalikan data blok " "saat ID cocok; entri basi hanya mengembalikan teks dan HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10105,23 +10113,23 @@ msgstr "" "Saat menempel, Notion mencari ID HTML dan memeriksanya terhadap salinan yang" " disimpan. ID yang cocok mengembalikan data blok." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Format papan klip direkam dari aset web yang di-cache pada 13 Juli 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Lebih banyak contoh dan sumber" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Contoh lain: Tabel penurunan harga" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10130,12 +10138,12 @@ msgstr "" "Notion mem-parsing Penurunan harga menjadi data blok. Contoh ini menunjukkan" " bagaimana tabel menjadi header dan baris data." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Tabel melalui parser penurunan harga Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10144,13 +10152,13 @@ msgstr "" "Output yang direkam dari parser Penurunan harga yang diekstraksi. Tabel " "menjadi baris dan sel." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Jalur lain: koneksi SQLite offline" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10164,7 +10172,7 @@ msgstr "" "utilitas SQLite. Kumpulan pernyataan dan hasil selanjutnya melewati port " "tersebut." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10174,7 +10182,7 @@ msgstr "" " mengapa hanya melacak permintaan IPC awal yang melewatkan percakapan " "selanjutnya." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Sumber dan cara membaca kutipannya" @@ -10182,7 +10190,7 @@ msgstr "Sumber dan cara membaca kutipannya" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10200,7 +10208,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10216,7 +10224,7 @@ msgstr "" "modul yang diekstraksi dan harness kecil; keluarannya menggambarkan probe " "tersebut daripada sesi UI desktop yang diambil." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10230,7 +10238,7 @@ msgstr "" "cocok dihubungkan dengan membaca implementasi pembungkusnya dalam paket." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10248,7 +10256,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10262,7 +10270,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10288,52 +10296,52 @@ msgstr "" "proses utama, dengan kutipan kode pendek dan tampilan format papan klip yang" " kaya." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Studi kasus Notion Electron" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Salin prompt analisis Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Salin kutipan pramuat Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Salin kutipan pembungkus pemanggilan Notion" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Salin kutipan pembungkus penangan Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Salin kutipan penerima papan klip Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Memulihkan data papan klip yang kaya saat ditempel" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Kembali ke atas" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Lewati ke konten" @@ -10342,25 +10350,25 @@ msgstr "Lewati ke konten" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Rumah{ph1} / {ph2}Menampilkan{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Studi kasus * Touhou 4: Kisah Tanah Teratai" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Merekonstruksi TH04{ph0}pola peluru." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10370,17 +10378,17 @@ msgstr "" "memeriksa fungsi DOS asli, lalu ikuti instruksinya ke dalam C++yang dapat " "dibaca." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * DOS 16-bit * C++ dan perakitan" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Lihat rekonstruksi TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Dari instruksi asli hingga sumber yang dicentang" @@ -10391,7 +10399,7 @@ msgstr "Dari instruksi asli hingga sumber yang dicentang" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10407,7 +10415,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10425,7 +10433,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10441,7 +10449,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10453,7 +10461,7 @@ msgstr "" "cocok{ph3}{ph4}Pemeriksaan kompilator yang direkam mencakup kode pembuatan " "peluru yang berisi pembantu ini.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10462,14 +10470,14 @@ msgstr "" "REA mengembalikan kode asli dan bukti analisisnya. Proyek TH04 menyediakan " "pemeriksaan sumber dan kompiler yang dipelihara." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "Dalam studi kasus ini" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10477,7 +10485,7 @@ msgstr "{ph0}Cincin peluru{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10485,7 +10493,7 @@ msgstr "{ph0}Apa yang dikembalikan REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10493,7 +10501,7 @@ msgstr "{ph0}Perakitan ke C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10501,18 +10509,18 @@ msgstr "{ph0}Memeriksa sumbernya{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Proyek lengkap{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Bagaimana sebuah cincin mengincar pemain" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10531,16 +10539,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agen pengkodean Anda" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Salin" @@ -10551,7 +10559,7 @@ msgstr "Salin" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10562,7 +10570,7 @@ msgstr "" "peluru dan mengarahkannya ke pemain. Jelaskan perhitungannya dan tunjukkan " "kodenya.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10572,7 +10580,7 @@ msgstr "" "secara lokal." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10586,7 +10594,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10596,12 +10604,12 @@ msgstr "" "Ilustrasi matematika sudut yang dipulihkan untuk hitungan 16, arah pemain " "40, dan rotasi templat 0. {ph0}Sosok terbuka{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Templat penembakan di sumber yang dipulihkan" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Serangan cincin Elly * kutipan sumber" @@ -10610,7 +10618,7 @@ msgstr "Serangan cincin Elly * kutipan sumber" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10620,13 +10628,13 @@ msgstr "" "Garis-garis ini memilih pola sebelum tingkat kesulitan dan penyetelan " "kinerja. {ph0}Baca sumber serangan itu{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Apa yang dikembalikan REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10638,12 +10646,12 @@ msgstr "" "peluru. REA mengembalikan instruksi, pseudocode, dan referensinya. Tiga " "bagian dari hasil itu menjelaskan polanya." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Periksa gambar DOS sebelum membaca kodenya" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10652,7 +10660,7 @@ msgstr "" "Pemeriksaan mengikat kode yang dimuat dan catatan relokasi ke executable " "yang disediakan. Jalur di atas dipersingkat untuk tampilan." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Baca perkalian dan pembagian cincin" @@ -10660,7 +10668,7 @@ msgstr "Baca perkalian dan pembagian cincin" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10672,12 +10680,12 @@ msgstr "" "pembagian menggunakan hitungan yang dibaca dari {ph1}. Nama sumber yang " "dipertahankan bidang itu {ph2}. Urutan lengkapnya muncul di bawah ini." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Temukan di mana polanya mengarah ke pemain" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10690,12 +10698,12 @@ msgstr "" "alamat tersebut dapat dibaca; REA memungkinkan agen memeriksa operasi asli " "di belakangnya." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Dari perakitan ke C++yang dapat dibaca" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10708,7 +10716,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10716,7 +10724,7 @@ msgstr "{ph0}01{ph1} Indeks" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10724,7 +10732,7 @@ msgstr "{ph0}02{ph1} Ruang" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10732,7 +10740,7 @@ msgstr "{ph0}03{ph1} Tujuan" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10740,18 +10748,18 @@ msgstr "{ph0}04{ph1} Putar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Toko" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * instruksi 16-bit asli" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "C++ yang dapat dibaca * ringkasan aimed-ring" @@ -10759,7 +10767,7 @@ msgstr "C++ yang dapat dibaca * ringkasan aimed-ring" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10773,7 +10781,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10789,7 +10797,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10804,7 +10812,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10819,7 +10827,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10833,7 +10841,7 @@ msgstr "" "oleh pemeran unsigned-byte. Sumber di sekitarnya juga mengubah sudut dan " "kecepatan ini menjadi kecepatan." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10844,7 +10852,7 @@ msgstr "" "C++ di atas adalah ringkasan yang dapat dibaca. Pemeriksaan kompiler di " "bawah ini berlaku untuk sumber yang dipelihara dalam proyek tertaut." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Baca sumber ring dan aim yang dipelihara" @@ -10861,7 +10869,7 @@ msgstr "Baca sumber ring dan aim yang dipelihara" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10871,12 +10879,12 @@ msgstr "" "{ph0}Ring makro{ph1} · {ph2}Tujuan dan sumber kecepatan{ph3} · " "{ph4}Representasi sudut{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Memeriksa sumber yang dipelihara" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10885,12 +10893,12 @@ msgstr "" "Pemeriksaan terekam proyek TH04 mengkompilasi kode pembuatan peluru, " "termasuk pembantu ini, dengan rantai alat Turbo C++ 4.0 J yang disematkan." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2.139 byte yang cocok" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10899,12 +10907,12 @@ msgstr "" "Kode pembuatan peluru yang dikompilasi cocok dengan bagian 2.139 byte dari " "executable asli." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Dua bangunan bersih" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10917,65 +10925,65 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "Direkam pada 3 Oktober 2026. {ph0}Baca pemeriksaan kompilator{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Identitas target dan ruang lingkup analisis" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Target asli" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156.258 byte, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Entri pembantu" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} dalam gambar yang dimuat REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Offset berkas asli" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, dikembalikan oleh {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Pemeriksaan kode yang direkam" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 Oktober 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10986,7 +10994,7 @@ msgstr "" " tumpang tindih." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11001,7 +11009,7 @@ msgstr "" "terletak pada rentang yang dilaporkan tersebut." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11017,7 +11025,7 @@ msgstr "" "yang sama. Identitas game yang disediakan disematkan oleh manifes " "repositorinya, dengan asal pristine-dump independen masih terbuka." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11028,12 +11036,12 @@ msgstr "" "lengkap, pengaturan waktu, dan perilaku perangkat keras PC-98 memiliki " "pemeriksaan runtime terpisah dalam proyek rekonstruksi." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "Rekonstruksi lengkap TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11046,7 +11054,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11058,7 +11066,7 @@ msgstr "{ph0}Jelajahi repositori TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11074,7 +11082,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11090,7 +11098,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11116,22 +11124,22 @@ msgstr "" "C++ untuk melihat bagaimana cincin peluru ditempatkan dan diarahkan ke " "pemain." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Di halaman ini" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "Studi kasus pola peluru TH04" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Salin prompt contoh TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11139,7 +11147,7 @@ msgstr "" "TH04 memperbaiki dan mengarahkan cincin peluru; gulir secara horizontal pada" " layar yang lebih kecil" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11152,27 +11160,27 @@ msgstr "" "sama; poin-poin pertama yang disorot mengarah ke pemain. Keduanya menjaga " "jarak 16 unit sudut, atau 22,5 derajat." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Salin templat penembakan TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Ikuti perhitungan cincin bertujuan TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Salin kutipan perakitan TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Salin perhitungan aimed-ring yang dapat dibaca" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Kembali ke atas" @@ -11280,7 +11288,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Kecepatan tetap: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11289,7 +11297,7 @@ msgstr "" "Memutar ulang aturan yang dipulihkan. Keempat nilai cocok dengan pemeriksaan" " game asli yang dikontrol saat dibulatkan menjadi tiga desimal." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11653,591 +11661,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Jarak yang sama: 256 ÷ 16 = 16 satuan sudut = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Studi kasus" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Mulai" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Panduan" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Kode sumber" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Lisensi MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Gabung komunitas" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Ikuti di X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * sumber skrip yang dipilih" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Kode sumber" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Keluaran formatter yang diharapkan" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Instruksi" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Fungsi pemanggil" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Konstanta" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Fungsi C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Tombol" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "Preload API" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Berkas CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Klik Anda" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Permintaan yang ditangkap" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Skrip ekspor" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "Hasil REA * ringkasan.kutipan ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "Kutipan instruksi REA · 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "Kutipan fungsi pemanggil REA · 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "Hasil byte REA * ditafsirkan sebagai ganda little-endian" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Kutipan C · yang dipulihkan" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Lihat cara kerja REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Menampilkan →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Pengaturan yang dipilih dari skrip yang diinspeksi" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Ringkasan yang dapat dibaca dari % handler" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * instruksi asli yang dipilih" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "ID Operator * Sumber Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Ikuti @ reatools di X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA →" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → agen * metode dan fungsi pemanggil" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * Java yang didekompilasi yang dipilih" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Ringkasan yang dapat dibaca * interpretasi agen" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, isi lengkap" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Unduh Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Unduh penyedia analisis Android" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA →" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → agen * instruksi yang dipilih" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agen → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA →" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Eksekusi asli * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Unduh tantangan asli" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Unduh pemecah" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "Hasil REA * kutipan pseudocode" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA excerpt agen · kutipan instruksi" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA excerpt agen · kutipan fungsi pemanggil" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agen → REA * dua {ph0} permintaan" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Hasil byte REA * diterjemahkan sebagai ganda" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Mulailah dengan target Anda sendiri" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Menghasilkan kode" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Aturan yang dipulihkan" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Jam yang dapat disesuaikan" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Biner" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Memeriksa kode" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Persamaan" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Benar!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Dapat dieksekusi" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Temuan REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Dipulihkan C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Validasi" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Aplikasi yang dikemas" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Exposed API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "IPC wrappers" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Papan klip" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Kode DOS asli" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Instruksi REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Perhitungan sudut" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Cincin peluru" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Exposed page API" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Panggilan IPC perender" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Dikirim ke papan klip sistem" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Disimpan secara lokal oleh Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Masukan penurunan harga" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Keluaran parser terstruktur · kutipan" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analisis aplikasi Anda sendiri" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA →" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA excerpt agen · kutipan instruksi" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Hasil fungsi yang sama * kutipan tujuan" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "C++yang dipertahankan sesuai" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Makro cincin * cabang TH04, kutipan" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Sudut dan kecepatan * kutipan sumber" @@ -12271,7 +12287,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12289,7 +12305,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12310,7 +12326,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12331,7 +12347,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12350,7 +12366,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12369,7 +12385,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12380,14 +12396,14 @@ msgstr "" " untuk saya.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Rekonstruksi · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12398,7 +12414,7 @@ msgstr "" "Anda, dan tinjau perubahan yang diusulkan." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12407,7 +12423,7 @@ msgstr "Contoh yang disediakan · {ph0} dan npm · Agen pengkodean Anda" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12426,7 +12442,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12441,7 +12457,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12460,7 +12476,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12471,7 +12487,7 @@ msgstr "" " {ph7} dan menulis file tersebut.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12486,7 +12502,7 @@ msgstr "{ph0} * baris 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12499,7 +12515,7 @@ msgstr "" "Tampilkan prediksi dan keluaran aktual.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12510,7 +12526,7 @@ msgstr "" "Ini memeriksa pemformat secara langsung dengan {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12518,7 +12534,7 @@ msgstr "{ph0} · CSV formatter" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12528,7 +12544,7 @@ msgstr "" "dengan {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12536,7 +12552,7 @@ msgstr "Tidak memiliki {ph0}, atau tidak yakin?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12549,7 +12565,7 @@ msgstr "" "ditemukan\", instal {ph1} 24 PT:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12563,7 +12579,7 @@ msgstr "{ph0} · contoh kutipan sumber" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12573,9 +12589,9 @@ msgstr "" "{ph0}Buka contohnya{ph1} · {ph2}Unduh {ph3}{ph4} · {ph5}Unduh {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12583,7 +12599,7 @@ msgstr "{ph0} * contoh sumber" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12597,7 +12613,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12610,7 +12626,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12623,7 +12639,7 @@ msgstr "Contohnya: {ph0}mengapa Kalkulator menghasilkan 220 untuk {ph1}?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12634,7 +12650,7 @@ msgstr "" "{ph3} menghasilkan 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12643,7 +12659,7 @@ msgstr "REA * dimuat {ph0} * baris yang dipilih" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12661,7 +12677,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12680,7 +12696,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12693,28 +12709,28 @@ msgstr "" "memungkinkan saya mengubah waktu.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * Anggota API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * Pembantu IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "utama/{ph0} * pembantu penangan" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12724,12 +12740,1425 @@ msgstr "utama/{ph0} * penerima papan klip" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Mulai {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Beralih ke mode terang" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Beralih ke mode gelap" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Untuk memeriksa isi permintaan dan respons HTTP, gunakan {ph0}Fiddler " +"Everywhere: rekaman SAZ, MCP, dan skill publik{ph1}. Ekspor SAZ atau HAR 1.2" +" untuk menghasilkan Evidence rekaman di REA secara luring, atau hubungkan " +"server MCP Everywhere untuk memeriksa lalu lintas yang direkam bersama agen " +"Anda." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Model khusus{ph0}Esai" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Apakah rekayasa balik membutuhkan model yang lebih besar?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Pelajaran dari rekonstruksi Touhou tentang model umum, model khusus, dan " +"pembelajaran dari umpan balik kompiler." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Oleh N0zoM1z0 · 13 Oktober 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Lewati ke konten" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Beranda{ph1} / {ph2}Blog{ph3} / Model dan rekayasa balik" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Esai" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Apakah rekayasa balik memerlukan model yang lebih besar?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Oleh N0zoM1z0 · 13 Oktober 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Poin utama" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Kemampuan model memengaruhi hipotesis mana yang dapat diajukan oleh " +"agen AI.{ph1} Sesi berikutnya memecahkan masalah yang belum terselesaikan " +"oleh pekerjaan sebelumnya." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Kompiler yang familiar menawarkan pola konkret untuk dipelajari model " +"khusus.{ph1} Beberapa kecocokan kode mesin yang tepat bergantung pada pola " +"kode sumber spesifik yang dapat digunakan kembali." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Sertakan pengetahuan repositori dalam perbandingan yang adil.{ph1} " +"Model yang lebih kecil dengan pengambilan pengetahuan yang baik mungkin " +"sudah memiliki informasi yang cukup untuk membuat kemajuan." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Latih model untuk memilih eksperimen berguna berikutnya, dan uji " +"pemeriksanya.{ph1} Masukan hanya berguna jika pemeriksa memverifikasi hal " +"yang benar." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Evaluasi hasil rekonstruksi terverifikasi beserta waktu dan biaya.{ph1}" +" Itulah yang ingin saya ukur untuk alur kerja agen AI yang lengkap." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "Dalam artikel ini" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Apa yang berubah dengan model yang lebih kuat?{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Mengapa mengambil spesialisasi?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Di mana pengalaman ini harus disimpan?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Pelajari eksperimen bermanfaat berikutnya{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Pembelajaran rekayasa balik dan penguatan{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Ketika pemeriksa salah{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Sebuah perbandingan yang layak untuk dijalankan{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Agen AI macam apa yang disarankan di sini?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Apa yang berubah dengan model yang lebih kuat?" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Sejak Agustus 2026, saya telah mengeksplorasi seberapa banyak rekayasa balik" +" yang dapat dilakukan agen dengan akses ke suatu program dan cara untuk " +"memeriksa kerjanya. Sebagian besar pengalaman saya berasal dari " +"merekonstruksi game, terutama Touhou. Karena saya telah mengubah model, " +"repositori menyimpan catatan tentang apa yang berhasil dipulihkan oleh " +"setiap sesi." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Sebagian besar pekerjaan tersebut bertujuan untuk rekonstruksi yang tepat: " +"kami mengkompilasi sumber yang dikelola di bawah rantai alat historis dengan" +" versi tetap dan memeriksa apakah sumber tersebut mereproduksi fungsi " +"target. Ketika model selanjutnya berhasil ketika pekerjaan sebelumnya " +"terhenti, perubahan sumber menunjukkan apa yang memungkinkan kemajuan " +"tersebut." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Variabel sementara membutuhkan masa hidup yang tumpang tindih" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Sebagian besar logika fungsi serangan TH09 telah direkonstruksi, namun " +"kompiler masih menyimpan hasil sementara yang berbeda dari aslinya. Masalah " +"yang tersisa adalah berapa lama hasil tersebut perlu bertahan dan kapan " +"penyimpanannya dapat digunakan kembali." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Catatan sesi {ph0}GPT-6-Sol{ph1} melaporkan ketidakcocokan ini setelah " +"menguji beberapa pengaturan kode sumber biasa. Ketika {ph2}GPT-6.1-Sol " +"memeriksa masalahnya lagi{ph3}, ia mengajukan hipotesis yang berguna tentang" +" masa hidup variabel-variabel sementara ini." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"Fungsi tersebut memberikan hasil sementara dan menyalinnya ke posisi " +"animasi. Di C++, hasil sementara tetap aktif hingga ekspresi yang " +"menggunakannya selesai. Mengelompokkan operasi nyata ke dalam satu ekspresi " +"membuat hasil tersebut tetap hidup, sehingga kompiler tidak dapat lagi " +"menggunakan penyimpanan yang sama untuk semuanya." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Salah satu hasil masih berbagi penyimpanan dengan nilai yang nantinya " +"digunakan untuk pemeriksaan tabrakan. Memberikan nilai tersebut seumur " +"hidupnya akan menyelesaikan sisa tumpang tindih. Setelah beberapa eksperimen" +" yang ditargetkan, {ph0}kompilasi ulang yang bersih dari sumber " +"mengonfirmasi bahwa seluruh fungsi cocok{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Saya tertarik pada bagaimana penemuan dan pengujian saling mendukung. " +"Hipotesis tentang masa hidup objek yang bersifat sementara memberikan arah " +"baru bagi agen AI. Umpan balik dari kompiler membantunya menyempurnakan " +"hipotesis tersebut menjadi susunan kode sumber yang cocok." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Grafik aliran kontrol yang berbeda" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Fungsi TH09 kedua menunjukkan mengapa arah baru itu penting. Di sini " +"kendalanya adalah bagaimana beberapa cabang membagikan karya akhirnya. " +"{ph0}Pekerjaan sebelumnya GPT-6.1-Sol{ph1} memiliki bagian-bagian fungsi " +"yang cocok, namun cabang-cabangnya masih digabungkan secara berbeda dari " +"aslinya." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra mengubah grafik aliran kontrol di sekitarnya{ph1}. Jalur " +"utama sekarang mengarah ke pembaruan akhir bersama dan kembalinya. Dalam " +"struktur sumber tersebut, kompiler menggabungkan cabang-cabang dengan cara " +"yang sama seperti aslinya. Fungsi keseluruhannya cocok, dan {ph2}pemeriksaan" +" pembangunan kembali secara terpisah mengonfirmasi hal tersebut{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Mengubah representasi membuka ruang pencarian yang lebih " +"produktif.{ph1} Kedua kasus tersebut memberi saya alasan untuk menganggap " +"serius kemampuan model umum: agen dapat terus mencoba variasi lokal untuk " +"waktu yang lama sebelum menemukan cara yang lebih baik untuk mengekspresikan" +" pekerjaan di sekitarnya." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Pada saat yang sama, sesi selanjutnya dimulai dengan sumber sebelumnya dan " +"mencatat kegagalan. Akumulasi pekerjaan itu adalah bagian dari keuntungan " +"mereka. Sejarah memungkinkan kita memeriksa penemuan-penemuan dan " +"pemeriksaannya; perbandingan terkontrol akan membantu memisahkan pengaruh " +"model dari pengalaman yang diwarisinya." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Inilah yang membuat pertanyaan ini menarik bagi saya. Beberapa kemajuan " +"datang dari penemuan representasi baru. Sebagian besar pekerjaan yang " +"tersisa melibatkan pengujian pengaturan kode sumber yang berbeda terhadap " +"kompiler yang sudah dikenal. Seberapa banyak hal ini memerlukan kemampuan " +"penalaran yang luas? Berapa banyak yang dapat dipelajari suatu model dengan " +"bekerja berulang kali menggunakan compiler dan kode tersebut?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Mengapa model AI khusus dapat berfungsi dengan baik?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou memberi kita alasan konkret untuk mengharapkan pengalaman itu " +"membantu. Sebagian besar kode permainan berasal dari penulis yang sama, ZUN," +" jadi kebiasaan berulang adalah asumsi awal yang masuk akal. Repositori " +"mendukung hal tersebut dengan contoh-contoh yang berguna: loop terkait dan " +"pengaturan pembantu telah memberikan hipotesis di seluruh game." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Pola sumber tersebut menjadi lebih spesifik ketika kita menyertakan " +"kompiler. Dalam versi dan rangkaian opsi tertentu, perubahan kecil pada " +"sumber dapat menghasilkan perbedaan berulang dalam kode mesin. Beberapa dari" +" perbedaan tersebut ternyata tidak jelas." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Di TH095, misalnya, {ph0}bahkan nama variabel lokal dapat memengaruhi tempat" +" VC7.1 menyimpannya{ph1}. Memindahkan deklarasinya tidak menyelesaikan tata " +"letak penyimpanan. Namun, fungsi latar belakang sebelumnya telah " +"mengungkapkan pola penamaan yang mempengaruhi pilihan kompiler. Hal ini " +"menunjukkan hipotesis yang lebih menjanjikan untuk {ph2}merekonstruksi " +"{ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Menggunakan kembali pola tersebut untuk variabel ukuran file menghasilkan " +"tata letak yang diperlukan tanpa menambahkan penyimpanan. Fungsi penuh " +"kemudian dicocokkan." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Ini adalah detail yang sangat spesifik yang mungkin tidak diketahui oleh " +"model AI tujuan umum saat pertama kali mengalami masalah. Model yang " +"dikhususkan untuk kompiler ini dapat melihat banyak kasus seperti itu dan " +"mempelajari variasi kode sumber mana yang layak untuk diuji terlebih dahulu." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Peluangnya sangat jelas dalam masalah pencocokan akhir dimana kita sudah " +"memahami perilakunya. Kami kemudian menanyakan pengaturan kode sumber biasa " +"mana yang diubah oleh kompiler ini menjadi instruksi yang diamati. " +"Spesialisasi dapat membantu model mengusulkan bentuk-bentuk tersebut dengan " +"lebih efisien, sementara target tetap menentukan hipotesis mana yang " +"bertahan." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Pola yang berguna harus mempertahankan konteksnya. TH08 menggunakan versi " +"Visual C++ yang lebih lama dari TH095 dan TH09. TH04 menggunakan compiler " +"yang berbeda dari era DOS. {ph0}rekonstruksi kode pemain{ph1} memerlukan " +"hipotesis berbeda tentang pola kode sumber dan bagaimana kode yang " +"dikompilasi dihubungkan ke dalam file yang dapat dieksekusi. Memiliki " +"penulis yang sama memberi kita ekspektasi awal, namun setiap target memberi " +"tahu kita apakah target tersebut berlaku. Model khusus perlu membedakan " +"konteks-konteks ini." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Di mana pengalaman ini harus disimpan?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Sebelum memutuskan untuk mengajarkan pola-pola tersebut melalui pelatihan " +"model, saya akan melihat pengetahuan yang sudah kita simpan di gudang. Dalam" +" {ph0}esai sebelumnya{ph1}, saya menulis tentang hal ini yang menjadi memori" +" kerja proyek. Memori tersebut mencakup pelajaran kompiler, beserta " +"sumbernya dan eksperimen gagal yang menjadikannya berguna." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Dengan mengambil catatan tersebut, agen dapat memulai dengan hasil yang " +"diketahui dan memeriksa bagaimana kami mencapainya. Hal ini juga dapat " +"menghindari alternatif-alternatif yang telah gagal dalam konteks yang sama. " +"Titik awal ditingkatkan tanpa mengubah parameter model yang dilatih." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Saat merekonstruksi fungsi TH09 untuk menciptakan musuh, {ph0}sesi " +"GPT-6-Luna-max{ph1} mengambil hipotesis dari kode sumber TH08 terkait. Kode " +"sebelumnya menyarankan cara mengatur loop dan menangani kegagalan di " +"dalamnya. Bukti TH09 sendiri memberikan detail khusus game tersebut. " +"Pembangunan kembali dari sumber mengonfirmasi bahwa fungsi lengkapnya cocok." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"Model tidak mengetahui kekhasan kompiler\" dan \"model tidak dapat " +"menggunakannya\" adalah masalah yang berbeda.{ph1} Pengambilan mungkin " +"memecahkan masalah pertama, namun mengubah fakta tersebut menjadi kandidat " +"yang berguna masih membutuhkan usaha. Dan jika kandidat kode sumber gagal, " +"model harus memutuskan apa arti hasil tersebut untuk percobaan berikutnya. " +"Mengetahui pola yang relevan hanyalah awal dari proses itu." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Oleh karena itu, saya akan menyertakan model AI serba guna yang lebih kecil " +"dengan pengambilan yang baik dalam perbandingan apa pun. Memberikan " +"perpustakaan pengalaman yang sama akan membantu kami mengidentifikasi apa " +"saja yang ditambahkan oleh pelatihan: perolehan kandidat yang lebih baik, " +"keputusan yang lebih baik setelah adanya masukan, atau keduanya." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Pelajari eksperimen bermanfaat berikutnya" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Keputusan-keputusan setelah mendapat masukan adalah hal yang paling ingin " +"saya pelajari. Dalam rekonstruksi agenik, model mengajukan penjelasan dan " +"mengujinya terhadap program. Bahkan ketika kode sumber kandidat gagal, " +"hasilnya dapat mempersempit kemungkinan yang tersisa dan menyarankan " +"percobaan berikutnya yang lebih berguna." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Perhatikan kembali contoh hasil sementara. Sumber akhirnya menunjukkan " +"pengaturan yang berhasil, namun rute ke sumber tersebut berisi lebih banyak " +"informasi. Setiap eksperimen berikut membantu mengidentifikasi apa yang " +"masih perlu diubah." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Eksperimen" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Apa yang diajarkan hasilnya kepada kita" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Coba cara lain untuk menyalin hasilnya" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Kode copynya berubah, tapi fungsinya tetap berbeda." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Gunakan nilai yang dikembalikan secara langsung" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"Penyalinan mengikuti pola aslinya, namun penyimpanan sementara tetap " +"berbeda." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Jaga agar semua variabel sementara tetap valid pada waktu yang sama" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Mereka mendapatkan penyimpanan terpisah, namun masih tumpang tindih dengan " +"nilai yang digunakan nanti untuk pemeriksaan tabrakan." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Pisahkan nilai pemeriksaan tabrakan" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Kompilasi ulang yang bersih dari sumber mengonfirmasi kecocokan yang " +"lengkap." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Eksperimen yang dipilih dari rekonstruksi fungsi serangan di atas, " +"dikelompokkan berdasarkan apa yang diajarkannya kepada kita." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Catatan pelatihan yang menjaga urutan ini dapat mengajarkan lebih dari " +"sekedar sumber akhir saja. Ini menghubungkan setiap perubahan yang diusulkan" +" dengan hasil yang diamati dan keputusan berikutnya. Mempertahankan variasi " +"yang tidak efektif juga penting: variasi tersebut akan memberi tahu agen " +"selanjutnya hipotesis mana yang telah diuji dalam konteks tersebut." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Saya ingin model mempelajari cara menggunakan masukan.{ph1} Hasil yang " +"netral adalah alasan untuk mempertimbangkan kembali variasi; ketidakcocokan " +"yang berubah mungkin menunjukkan penyebab lain. Ketika suntingan lokal tidak" +" lagi bersifat informatif, agen harus dapat mengunjungi kembali representasi" +" sumber atau memeriksa bukti lagi." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Belajar membuat pilihan tersebut membutuhkan otonomi. Terkadang langkah " +"berikutnya yang berguna adalah memeriksa pemanggil lain daripada " +"mengkompilasi hasil edit lainnya. Urutan penulisan ulang yang diperlukan " +"akan menghilangkan pilihan tersebut, bersama dengan bagian dari perilaku " +"yang kita ingin model pelajari." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "Mengapa rekayasa balik menarik untuk pembelajaran penguatan" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Rekonstruksi dengan lingkup yang jelas memberi lingkungan praktis untuk " +"mempelajari pilihan ini. Setelah versi target dan kompiler ditetapkan, " +"banyak eksperimen kode sumber memberi umpan balik yang cepat dan dapat " +"diulang. Agen bisa mengompilasi kandidat, memeriksa perbedaan, lalu memilih " +"langkah berikutnya." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Pembelajaran penguatan dapat melatih proses pengambilan keputusan melalui " +"umpan balik yang diterimanya. Kandidat yang diterima melalui pemeriksaan " +"tertentu memberi kita hasil yang konkrit, sementara rangkaian upaya " +"memungkinkan kita mengamati berapa banyak usaha yang diperlukan untuk " +"mencapainya." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Sudah ada penelitian yang mendukung arah ini. {ph0}LLM4Decompile{ph1} " +"mempelajari model yang dikhususkan untuk dekompilasi. " +"{ph2}AutoDecompiler{ph3} melatih penyempurnaan multi-putaran menggunakan " +"compiler dan masukan eksekusi. Studi mereka fokus pada pemulihan fungsional." +" Untuk pekerjaan ini, saya akan menggunakannya sebagai titik awal untuk " +"tugas terkait menemukan sumber yang cocok dengan keluaran kompiler historis." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Namun, untuk mencapai tugas yang terdefinisi dengan baik, pertama-tama kita " +"perlu menetapkan sumber daya yang dimiliki suatu fungsi atau merancang cara " +"baru untuk mengamati perilaku program saat berjalan. Di TH08, misalnya, " +"{ph0}perbedaan tabrakan mengarah kembali ke cara program asli menangani " +"penghitungan floating-point{ph1}. Sebelum agen dapat menguji koreksi yang " +"berguna, agen harus menentukan apa yang diukur." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Hal ini menunjukkan adanya peran lain dari model yang berkemampuan luas: " +"membantu membuat masalah dapat diperiksa. Setelah pemeriksaan tersebut " +"dilakukan, kami dapat menyelidiki sejauh mana kebijakan penelusuran yang " +"dipelajari dapat diterapkan." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Ketika pemeriksa salah" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Saat suatu pemeriksaan dipakai untuk pelatihan, cakupannya menjadi bagian " +"dari lingkungan belajar. Saya menyebut acuan atau alat pemeriksa itu oracle." +" Bahkan jawaban yang dapat diulang harus dipahami berdasarkan apa yang " +"benar-benar diperiksanya." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 menunjukkan seberapa banyak yang bisa disembunyikan di luar cakupan " +"itu. Beberapa fungsi yang direkonstruksi memberikan perbandingan yang tepat " +"dengan konstanta floating-point yang salah. Pembanding menyesuaikan alamat " +"yang direlokasi sebelum memeriksa instruksi, namun pembanding memeriksa " +"nilai di balik alamat tersebut hanya jika nilai tersebut telah dicatat " +"secara eksplisit untuk verifikasi. Referensi literal lainnya bisa lolos " +"tanpa diperiksa nilainya." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Untuk mengatasi kesenjangan ini, {ph0}audit yang lebih luas{ph1} menemukan " +"konstanta yang salah pada fungsi yang telah lolos verifikasi. Dalam satu " +"perhitungan, kode sumber yang direkonstruksi menambahkan {ph2}, sedangkan " +"kode sumber asli menambahkan {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Model yang diberi imbalan melalui pemeriksaan verifikasi lama dapat " +"belajar menghasilkan rekonstruksi yang salah.{ph1} Kami tidak melatih model " +"RL menggunakan pemeriksa tersebut. Kegagalan yang kami amati ada pada " +"pemeriksaan itu sendiri. Namun jika kita menggunakannya sebagai hadiah, " +"titik buta yang sama akan menjadi bagian dari lingkungan belajar." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Tes fungsional dapat memiliki titik buta serupa. {ph0}Penelitian yang " +"menggunakan fuzzing diferensial pada dekompiler LLM{ph1} menemukan perbedaan" +" perilaku di luar pengujian yang disediakan. Oleh karena itu, kita perlu " +"memahami tes kelulusan dalam kaitannya dengan kasus-kasus yang dilakukannya." +" Demikian pula, kecocokan instruksi harus dipahami dalam kaitannya dengan " +"byte dan data yang diverifikasi." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Sebelum menggunakan salah satu jenis cek verifikasi sebagai hadiah, saya " +"akan mengujinya dengan hasil yang sengaja salah. Saya juga akan memisahkan " +"penerimaan akhir dari kode sumber yang dapat diedit oleh agen AI. Model " +"harus lolos verifikasi dengan merekonstruksi program dengan benar. Jika " +"tidak, hanya dengan menyalin array byte dari target dapat menipu sistem " +"penilaian yang naif tanpa memulihkan kode sumber yang berguna." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Memperbaiki model yang belajar dan memperbaiki pemeriksanya merupakan " +"bagian dari masalah penelitian yang sama.{ph1} Semakin baik model " +"mengoptimalkan umpan balik yang kita berikan, semakin penting memahami umpan" +" balik itu sendiri." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Sebuah perbandingan yang layak untuk dijalankan" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Dengan pemeriksaan tersebut, saya akan memulai perbandingan pada rangkaian " +"tugas VC7.1 yang tetap. Pertama, saya akan menetapkan dasar untuk model AI " +"tujuan umum yang kuat dan model yang lebih kecil. Menambahkan pengetahuan " +"repositori ke model yang lebih kecil akan menunjukkan perubahan pengambilan " +"apa. Dari sana, spesialisasi yang diawasi dan versi terlatih RL akan " +"memungkinkan kita memeriksa apa saja yang ditambahkan dalam pelatihan." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Agar perbandingan tersebut informatif, setiap model akan menerima bukti dan " +"alat target yang sama. Untuk perbandingan khusus pelatihan, saya juga akan " +"mempertahankan model dasar dan pengetahuan yang tersedia. Uji coba berulang " +"akan membantu membedakan strategi pencarian yang andal dari kandidat solusi " +"yang berhasil secara kebetulan." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Saya kemudian akan memisahkan dua kondisi awal: merekonstruksi suatu fungsi " +"dari instruksinya, dan menutup beberapa perbedaan terakhir dalam sumber yang" +" dipertahankan. Model AI khusus mungkin sangat baik dalam tugas kedua, " +"sementara model AI tujuan umum melakukan banyak pekerjaan yang diperlukan " +"untuk mencapainya. Mengukurnya secara terpisah akan mengungkapkan pembagian " +"kerja tersebut." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Kedua tugas memerlukan contoh uji yang tidak ada dalam data pelatihan maupun" +" bahan retrieval. Game Touhou yang terkait berbagi kode engine. " +"Mengecualikan satu game saja masih bisa menyisakan fungsi yang hampir " +"identik dalam data pelatihan. Saya akan menyisihkan seluruh kelompok kode " +"yang terkait, dan memastikan jawaban terverifikasinya tidak masuk ke data " +"pelatihan ataupun pustaka retrieval." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Untuk contoh-contoh ini, hasilnya akan berupa kecocokan yang lengkap dan " +"terverifikasi secara independen. Anggaran yang sama untuk proposal kandidat " +"atau upaya kompilasi akan membantu membandingkan kualitas pencarian. " +"Mengukur total waktu dan biaya, termasuk kompilasi, akan menunjukkan apakah " +"kualitas tersebut menghasilkan alur kerja yang efisien. Biaya pelatihan " +"harus diukur secara terpisah." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Kedua pengukuran itu penting. Proposal yang murah dapat menyebabkan alur " +"kerja yang mahal jika menyebabkan lebih banyak kompilasi yang tidak " +"memberikan informasi berguna. Sebaliknya, model yang lebih lambat mungkin " +"lebih ekonomis jika model tersebut menemukan eksperimen yang berguna lebih " +"cepat. Perbandingannya harus mencakup biaya-biaya ini." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Menghitung hasil yang diterima juga menjaga kemajuan sementara tetap dalam " +"perspektif. Salah satu TH09 {ph0}kandidat penyimpanan ulang{ph1} tampak " +"menjanjikan karena fungsi yang dikompilasi memiliki ukuran yang diharapkan, " +"namun perbandingan penuh masih menemukan perbedaan besar. Perubahan dalam " +"cara compiler menyusun instruksi juga dapat membuat kandidat tampak lebih " +"dekat dengan target tanpa menyelesaikan masalah mendasarnya. Diagnostik " +"semacam itu dapat memandu eksperimen berikutnya, namun saya akan memvalidasi" +" imbalan apa pun karena \"mendekati\" dengan pemeriksaan penerimaan penuh." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Saya tertarik dengan pola hasil ini. Jika model AI khusus dapat berfungsi " +"dengan baik dalam rangkaian kompiler yang sudah dikenal, apakah keunggulan " +"tersebut dapat bertahan jika terjadi perubahan rantai alat? Dan ketika kedua" +" model AI memiliki pengambilan yang baik, berapa banyak lagi yang bisa " +"ditambahkan oleh pelatihan? Jawabannya akan membantu kita memutuskan model " +"mana yang paling berguna." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Agen AI macam apa yang disarankan di sini?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Jika model-model tersebut terbukti membantu pada tahap-tahap yang berbeda, " +"pengaturan yang berguna mungkin adalah agen luas yang memiliki akses ke " +"model AI khusus. Setelah tugas menjadi pencarian kompiler yang familier, " +"tugas tersebut dapat menanyakan kandidat pada model AI khusus. Jika hasilnya" +" tidak masuk akal, agen yang lebih luas dapat kembali ke bukti target atau " +"menyelidiki pengukuran itu sendiri." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"Dalam pengaturan tersebut, spesialisasi menjadi alat yang dapat dipilih agen" +" seiring berkembangnya penyelidikan. Agen mempunyai kebebasan untuk mengubah" +" arah yang memungkinkan terobosan sebelumnya." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Hal ini tentu saja mengikuti pergeseran industri yang saya jelaskan di esai " +"sebelumnya. Mampu menjalankan lebih banyak eksperimen mengubah cara kami " +"mengatur pekerjaan. Hal ini juga memberi kita alasan untuk mempertanyakan " +"keputusan mana yang memerlukan pertimbangan luas dan mana yang ditingkatkan " +"melalui pengalaman berulang-ulang dengan bidang tertentu." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Untuk saat ini, model umum terkuat mendapat tempat dalam alur kerja saya " +"karena menyelesaikan masalah yang sebelumnya belum terpecahkan. Keberhasilan" +" itu membuat saya ingin mempelajari prosesnya: seberapa banyak bergantung " +"pada keluasan kemampuan model, dan seberapa banyak bisa dikerjakan oleh " +"model yang dilatih khusus untuk jenis rekonstruksi ini?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Repositori memberi kita cara untuk menguji pertanyaan tersebut.{ph1} " +"Saya ingin menggunakan data tersebut untuk membuat perbandingan dan melihat " +"apa yang kita pelajari." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Bukti dan atribusi model" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Contoh-contoh ini menjelaskan perbandingan tingkat fungsi historis yang " +"dicatat dalam penerapan tertaut. Pemeriksaan waktu proses keseluruhan " +"permainan adalah pencapaian yang terpisah. Sumber dan catatan pencocokan " +"ditinjau pada 13 Oktober 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"Label TH09 {ph0} berarti GPT-6-Astra. Model yang terkait dengan {ph1} " +"berubah seiring waktu, sehingga label saja tidak dapat mengidentifikasi " +"model yang digunakan dalam proses tertentu. Nama model eksplisit dalam " +"commit lain yang dikutip memberikan atribusi yang tercatat. Riwayat ini " +"tidak mencakup pengukuran biaya atau upaya yang konsisten untuk setiap " +"proses." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 masa hidup objek sementara:{ph1} {ph2}tinjauan konteks " +"sebelumnya{ph3} dan {ph4}rekonstruksi lengkap yang diverifikasi melalui " +"kompilasi ulang yang bersih dari sumber{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front callback:{ph1} {ph2}wilayah diagnostik yang tidak " +"cocok{ph3}, {ph4}Astra grafik aliran kontrol baru{ph5} dan {ph6}pemeriksaan " +"kompilasi ulang yang diterima{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Pengetahuan compiler:{ph1} {ph2}TH095 penggunaan kembali perilaku " +"identifier-bucket{ph3}, {ph4}TH04 kode sumber pemain dan urutan linker{ph5} " +"dan {ph6}Luna rekonstruksi lengkap fungsi penciptaan musuh TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Pemeriksaan dan diagnostik:{ph1} {ph2}TH08 audit konstan floating-" +"point{ph3}, {ph4}TH08 investigasi numerik{ph5} dan {ph6}TH09 rekonstruksi " +"penyimpanan ulangan{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Perbandingan yang diusulkan antara model khusus dan pelatihan RL adalah " +"eksperimen di masa depan. Sejarah proyek memotivasi mereka. Tidak ada model " +"khusus terlatih yang dievaluasi untuk esai ini." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Apakah rekayasa balik memerlukan model yang lebih besar? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Apa yang saya pelajari dari rekonstruksi Touhou tentang model umum, model " +"khusus, dan cara belajar mengajukan hipotesis yang lebih baik melalui umpan " +"balik kompiler." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Di halaman ini" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Model dan esai rekayasa balik" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Eksperimen rekonstruksi yang dipilih" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Kembali ke atas" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}Catatan bukti terperinci{ph1} memuat perbandingan yang dicatat dan " +"konteks eksperimen." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Oleh N0zoM1z0 · 13 Oktober 2026 · Draf untuk ditinjau" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Panduan pemasangan" diff --git a/website/locales/it/messages.po b/website/locales/it/messages.po index d47a67355..516e09283 100644 --- a/website/locales/it/messages.po +++ b/website/locales/it/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Vai al contenuto" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Casa{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Riflessioni sul reverse engineering." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Gioco ricostruzione{ph0}Saggio" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "La rivoluzione industriale nel reverse engineering" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "Che manuale RE e ricostruire TH08, TH095 e TH04 mi ha insegnato circa gli " "agenti, la verifica e la conoscenza che composti attraverso i progetti." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Leggi l'articolo" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Di N0zoM1z0 * 10 ottobre 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "e agenti AI." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -135,112 +138,117 @@ msgstr "" "REA-Scopri come funziona il software. Reverse engineering con il tuo agente " "di codifica." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Home di REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Navigazione principale" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA su GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Unisciti a REA su Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Segui REA su X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -249,35 +257,35 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Casa{ph1} / {ph2}Blog{ph3} / Touhou ricostruzione" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Saggio * Touhou ricostruzione" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "La rivoluzione industriale nel reverse engineering." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Di N0zoM1z0 * 10 ottobre 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Punti chiave" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -290,7 +298,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -304,7 +312,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -317,7 +325,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -330,7 +338,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -340,65 +348,65 @@ msgstr "" "{ph0}Siamo agli inizi della rivoluzione industriale di RE.{ph1} I metodi " "stanno ancora prendendo forma. C'è ancora molto da esplorare." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Come composti esperienza" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Direzione umana{ph1} * Obiettivi e criteri di accettazione" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Autonomia" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agente" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Scegli un esperimento.{ph0}Proponi un'ipotesi." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Verifica" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Riferimento di verifica" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Test contro a{ph0}riferimento concreto." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Repository" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Memoria di lavoro" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -407,7 +415,7 @@ msgstr "Codice, prove,{ph0}controlli e lezioni." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -416,26 +424,26 @@ msgstr "Disadattamento{ph0}{ph1}Rivedere l'ipotesi{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Wells{ph0}{ph1}punto di partenza{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Riutilizzo" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Passare{ph1} * Mantenere il risultato e le sue prove" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -444,14 +452,14 @@ msgstr "" "Ogni progetto lascia il successivo con un punto di partenza migliore. Ciò " "include fissare i controlli quando scopriamo una lacuna." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "In questo articolo" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -459,7 +467,7 @@ msgstr "{ph0}Agosto 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -467,7 +475,7 @@ msgstr "{ph0} TH08: la continuazione{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -475,7 +483,7 @@ msgstr "{ph0}Due approcci{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -483,7 +491,7 @@ msgstr "{ph0} TH095: compounding{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -491,7 +499,7 @@ msgstr "{ph0} TH04: tra architetture{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -499,7 +507,7 @@ msgstr "{ph0}Da esatto a leggibile{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -507,18 +515,18 @@ msgstr "{ph0}Il cambiamento industriale{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Cosa diventa possibile{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Cosa è cambiato nell'agosto 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -534,7 +542,7 @@ msgstr "" "successiva. Significava anche mantenere un quadro sempre più grande nella " "mia testa." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -548,7 +556,7 @@ msgstr "" "metodo può essere utile altrove, ma ogni campo deve stabilire cosa può " "verificare con un riferimento affidabile." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -561,7 +569,7 @@ msgstr "" "l'accesso al programma e agli strumenti di sviluppo ordinari. Touhou " "ricostruzione mi ha dato un progetto sostanziale in cui scoprire." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -579,7 +587,7 @@ msgstr "" "attenzione alla direzione del progetto e se i suoi controlli fossero " "affidabili." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -590,7 +598,7 @@ msgstr "" "chiedermi cosa sarebbe sopravvissuto oltre il progetto attuale. Il prossimo " "gioco trarrà beneficio da tutto ciò che abbiamo appena imparato?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: costruire sul lavoro umano" @@ -599,7 +607,7 @@ msgstr "TH08: costruire sul lavoro umano" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -613,7 +621,7 @@ msgstr "" "dato un fondamento sostanziale. È venuto con la conoscenza della costruzione" " e una storia di contributi che ho conservato nella continuazione." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -625,7 +633,7 @@ msgstr "" "libro mastro ha registrato la fonte per tutte le 1.107 funzioni di gioco " "identificate." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -636,7 +644,7 @@ msgstr "" "circa undici giorni dopo l'inizio della continuazione. Ne è seguita " "un'edizione Web. La versione nativa Linux a 64 bit è arrivata il 30 agosto." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -652,7 +660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -670,12 +678,12 @@ msgstr "" "previsto. L'agente propone una spiegazione e la mette alla prova; una " "mancata corrispondenza gli dà qualcosa di specifico da indagare." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Una corrispondenza esatta con la costante sbagliata" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -687,7 +695,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -700,7 +708,7 @@ msgstr "" " la potenza del giocatore contro {ph0}. L'originale usato {ph1}, la soglia " "di potenza massima." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -716,13 +724,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}Eppure la funzione aveva già superato il confronto esatto.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -738,7 +746,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -754,7 +762,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -768,7 +776,7 @@ msgstr "" " ampio{ph3} poi ha esaminato 1.548 riferimenti costanti in virgola mobile. " "Ha trovato altri dodici riferimenti errati su cinque funzioni accettate." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -782,7 +790,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -792,7 +800,7 @@ msgstr "" "{ph0}Anche il riferimento di verifica (oracle) doveva essere " "ricostruito.{ph1} Ripararlo faceva parte della riparazione del gioco." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -810,7 +818,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -827,7 +835,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -837,7 +845,7 @@ msgstr "" "{ph0}Un batch di successo ci ha dato sia il codice recuperato che un " "ambiente migliore per il batch successivo.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Due diverse idee di ricostruzione" @@ -846,7 +854,7 @@ msgstr "Due diverse idee di ricostruzione" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -858,7 +866,7 @@ msgstr "" " con questo tipo di lavoro. L'avviso annuncia che ulteriori sviluppi " "avverranno privatamente fino al completamento. Un passaggio recita:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -868,7 +876,7 @@ msgstr "" "prende dal nostro lavoro dipinge una cattiva immagine per i futuri sforzi di" " decompilazione…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -886,7 +894,7 @@ msgstr "" "dovrebbe procedere la ricostruzione e come dovrebbe essere giudicato un " "contributo." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -900,7 +908,7 @@ msgstr "" "contributore contava perché gran parte del ragionamento accadeva mentre " "lavoravano." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -911,7 +919,7 @@ msgstr "" "costruiscono strumenti. Ciò che è cambiato per me è che un agente potrebbe " "usare quella conoscenza per perseguire la prossima indagine da solo." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -926,7 +934,7 @@ msgstr "" " persona sia in grado di esaminare il motivo per cui abbiamo scelto " "un'implementazione, anche se un agente ha fatto la maggior parte del lavoro." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -939,7 +947,7 @@ msgstr "" "Ciò solleva domande reali sul credito. Cambia anche ciò che i manutentori " "devono sapere prima di accettare un contributo." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -955,7 +963,7 @@ msgstr "" "Diverse comunità possono scegliere quanto di quel cambiamento vogliono " "assumere." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -980,7 +988,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -993,14 +1001,14 @@ msgstr "" "abbreviato. Di TH08 {ph4}crediti e provenienza{ph5} registra il limite di " "continuazione." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: l'esperienza inizia a comporre" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1015,7 +1023,7 @@ msgstr "" "ancora imparare il gioco. Ma sapevamo già molto di più su come iniziare una " "ricostruzione e come mantenerla in movimento." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1029,7 +1037,7 @@ msgstr "" "Windows i386 è stata contrassegnata come giocabile il 10 settembre, circa " "dodici giorni dopo l'inizializzazione." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1041,7 +1049,7 @@ msgstr "" "L'esperienza era già presente negli strumenti e nel modo in cui il progetto " "è stato organizzato." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1057,7 +1065,7 @@ msgstr "" " a modellare il modo in cui ci siamo avvicinati alla compilazione " "dell'intero programma di TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1070,7 +1078,7 @@ msgstr "" "aiutare dopo che sono andato avanti. L'agente successivo può utilizzare il " "risultato senza ripetere l'indagine che lo ha portato." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1085,7 +1093,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1097,7 +1105,7 @@ msgstr "" "partita.{ph1} Possiamo spendere di più dello sforzo del prossimo progetto su" " ciò che è effettivamente nuovo sul suo obiettivo." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1110,7 +1118,7 @@ msgstr "" "continuare il lavoro. Non devono ricostruire la storia dell'intero progetto " "per scoprire perché la fonte sembra il modo in cui lo fa." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: il flusso di lavoro sopravvive a un'architettura diversa" @@ -1119,7 +1127,7 @@ msgstr "TH04: il flusso di lavoro sopravvive a un'architettura diversa" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1135,7 +1143,7 @@ msgstr "" "diverse dai giochi Windows. Esistente {ph2}ReC98 lavoro{ph3} ci ha dato " "preziose conoscenze e materiale sorgente anche qui." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1148,7 +1156,7 @@ msgstr "" "salvataggi. Il lavoro corrente è una porta nativa a 64 bit. Stabilire una " "versione DOS funzionante prima dà a quella porta un riferimento." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1161,7 +1169,7 @@ msgstr "" "il nostro lavoro. Ma l'agente potrebbe ancora seguire una domanda fino a un " "risultato e lasciare che quel risultato guidi il prossimo esperimento." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1176,7 +1184,7 @@ msgstr "" "prove e i controlli sono disponibili, un agente può elaborare la domanda " "come ha fatto su un titolo Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1188,7 +1196,7 @@ msgstr "" "con un nuovo modo di lavorare. L'architettura ha definito il problema; il " "flusso di lavoro ci ha comunque dato un modo per risolverlo." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1205,7 +1213,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1216,12 +1224,12 @@ msgstr "" "manuale{ph1} · {ph2}porta a 64 bit{ph3}. Il porto è ancora in fase di " "sviluppo." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Dal codice esatto al codice leggibile" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1230,7 +1238,7 @@ msgstr "" "Una volta che una ricostruzione funziona, voglio che qualcun altro sia in " "grado di capirlo." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1245,7 +1253,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1262,7 +1270,7 @@ msgstr "" "Manteniamo il ragionamento con la fonte in modo che la prossima persona " "possa vedere da dove proviene quell'interpretazione." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1278,14 +1286,14 @@ msgstr "" "sicuro, abbiamo bisogno di recuperare la relazione dietro il vecchio accesso" " alla memoria." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "L'ordine che ora uso è:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1301,7 +1309,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1318,7 +1326,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1334,7 +1342,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1349,7 +1357,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1366,7 +1374,7 @@ msgstr "" "ricostruito costruisca e si comporti correttamente lungo i percorsi che " "esercitiamo." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1380,7 +1388,7 @@ msgstr "" "disponibili dà all'agente un fallimento concreto per indagare prima di " "portare un refactor ulteriormente." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1397,7 +1405,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1416,7 +1424,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1427,12 +1435,12 @@ msgstr "" "semantica rende fruibile la conoscenza recuperata.{ph1} Una porta può quindi" " costruire su entrambi." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Cosa rende questo un cambiamento industriale" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1446,7 +1454,7 @@ msgstr "" "Uno strumento migliore potrebbe aiutare con ogni funzione successiva che ne " "aveva bisogno." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1460,7 +1468,7 @@ msgstr "" "io prescriva ogni passo, gran parte del lavoro rimane legato alla mia " "attenzione." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1473,7 +1481,7 @@ msgstr "" "aiutare a capire l'errore abbastanza bene da riprovare. Devo ancora decidere" " se le prove accumulate supportano una pietra miliare del progetto." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1488,7 +1496,7 @@ msgstr "" "controlli di riferimento. L'agente può usarli per testare la fonte che " "propone e vedere dove regge la sua spiegazione." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1506,7 +1514,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1527,7 +1535,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1545,7 +1553,7 @@ msgstr "" "rivedere i risultati che ha influenzato. Il prossimo progetto può quindi " "ereditare uno strumento più forte." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1561,7 +1569,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1573,7 +1581,7 @@ msgstr "" " progetti un modo condiviso per portare avanti i loro controlli e lezioni. " "Lavorare su un gioco può migliorare le condizioni di partenza per un altro." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1585,12 +1593,12 @@ msgstr "" "utilizzare. Migliorare questi strumenti cambia quanto la prossima persona—o " "il prossimo agente-può fare." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "I progetti che possiamo ora considerare" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1602,7 +1610,7 @@ msgstr "" "attenzione di quanto potrei realisticamente dargli. Molti progetti " "rimarrebbero idee." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1620,7 +1628,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1631,7 +1639,7 @@ msgstr "" " conoscenza accumulata permetterebbero a un agente di lavorare su questo in " "modo affidabile?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1642,12 +1650,12 @@ msgstr "" "avrei lasciato da solo. Ognuno può migliorare il modo in cui ci avviciniamo " "al prossimo. Voglio continuare a esplorare fino a che punto ci può portare." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Pietre miliari e fonti del progetto" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1682,7 +1690,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1716,7 +1724,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1734,7 +1742,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1758,7 +1766,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1780,7 +1788,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1797,7 +1805,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1819,7 +1827,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1833,7 +1841,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1854,27 +1862,27 @@ msgstr "" "Touhou con agenti AI e su come la conoscenza si compensa in TH08 , TH095 e " "PC-98 TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Esperienza tra i progetti" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Touhou ricostruzione saggio" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -1883,18 +1891,18 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Casa{ph1}{ph2}/{ph3}Dinosaur speed lab" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Ispezionare → ricostruire → modificare" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Ricostruisci la regola della velocità del dinosauro." @@ -1903,7 +1911,7 @@ msgstr "Ricostruisci la regola della velocità del dinosauro." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1916,15 +1924,15 @@ msgstr "" "abbiamo usato la sua regola per costruire questo mini-gioco con " "{ph2}velocità regolabile.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "In questa pagina" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1932,7 +1940,7 @@ msgstr "{ph0}Gioca e cambia la velocità{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1940,7 +1948,7 @@ msgstr "{ph0}Leggi la regola recuperata{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1948,18 +1956,18 @@ msgstr "{ph0}Controlla la ricostruzione{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Prova l'analisi{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Gioca e cambia la velocità" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1971,49 +1979,49 @@ msgstr "" "Selezionare la regola recuperato per iniziare a 6 e gradualmente accelerare " "di nuovo." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Gioca alla ricostruzione" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Gioca" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Salta ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Ricomincia" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Velocità" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Utilizzare la regola di accelerazione recuperata" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Regola originale: inizia da 6, quindi aumenta verso 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Spostare il cursore per impostare la propria velocità. Spazio o salto " "cancella un cactus." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2022,7 +2030,7 @@ msgstr "" "Abilita JavaScript per riprodurre la ricostruzione. Il codice e la " "spiegazione di cui sopra rimangono leggibili." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Leggere lo script REA restituito" @@ -2030,7 +2038,7 @@ msgstr "Leggere lo script REA restituito" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2045,7 +2053,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2055,18 +2063,18 @@ msgstr "" "Le impostazioni sono {ph0}, {ph1} e {ph2}. Il gioco esegue questo ramo su un" " aggiornamento senza una collisione." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Usa la stessa regola nel nuovo gioco" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Copia" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2083,7 +2091,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" @@ -2091,12 +2099,12 @@ msgstr "" "{ph0}Scarica la regola della velocità{ph1} · {ph2}Leggi il codice del " "gioco{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Controlla la ricostruzione" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2107,27 +2115,27 @@ msgstr "" "ostacoli e programmazione automatica disabilitata. Confronta quelle velocità" " registrate con un replay della regola recuperata." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Aggiornare" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Gioco originale" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Regola ricostruita" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Eseguire il controllo della velocità" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2136,14 +2144,14 @@ msgstr "" "Valori arrotondati a tre decimali. Il ramo controlla prima di aggiungere, " "quindi l'incremento finale può prendere velocità appena sopra 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Prova tu stesso l'analisi" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2152,7 +2160,7 @@ msgstr "{ph0}Impostare REA {ph1} con il tuo agente di codifica." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2161,7 +2169,7 @@ msgstr "" "Segui il {ph0}passaggi di connessione del browser{ph1}, servendosi {ph2} " "come l'URL della pagina." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2178,7 +2186,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2190,7 +2198,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2204,7 +2212,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2219,7 +2227,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2245,12 +2253,12 @@ msgstr "" "Leggi la regola di velocità del gioco dei dinosauri con REA, ricostruiscilo," " quindi cambia la velocità e gioca." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Dinosauro velocità ricostruzione" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2259,52 +2267,52 @@ msgstr "" "Dinosauro mini-gioco. Utilizzare il pulsante di salto o premere Spazio " "mentre il gioco è focalizzato." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Copia regola di velocità ricostruita" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copia dinosaur analysis prompt" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Vai al contenuto" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Casa{ph1} / FAQ" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "Domande FREQUENTI SU REA." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Configurazione, aggiornamenti, analisi e risoluzione dei problemi." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Argomento" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2312,7 +2320,7 @@ msgstr "{ph0}Configurazione e aggiornamenti{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2320,7 +2328,7 @@ msgstr "{ph0}Analisi{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2328,31 +2336,31 @@ msgstr "{ph0}Risoluzione dei problemi{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Dati e condivisione{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Configurazione e aggiornamenti" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Come installo REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminale * configurazione agente" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Copia" @@ -2360,7 +2368,7 @@ msgstr "Copia" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2374,12 +2382,12 @@ msgstr "" "percorso del file e una domanda. La {ph0}guida alla configurazione{ph1} " "spiega i prerequisiti e la prima analisi." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Quali agenti di codifica possono utilizzare REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2395,18 +2403,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Connetti il tuo agente di codifica{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Come aggiorno REA?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2415,13 +2423,13 @@ msgstr "" "REA rilascia frequentemente, comprese le correzioni di bug. Se è stato " "installato il CLI con npm :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminale * installato CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2431,14 +2439,14 @@ msgstr "" "Seguire il comando setup refresh stampato dall'aggiornamento. Se si imposta " "il vostro agente attraverso {ph0}, eseguire:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminale * aggiorna la configurazione dell'agente" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2451,14 +2459,14 @@ msgstr "" "usare la nuova versione. Per un singolo comando CLI, aggiungi il comando " "dopo {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Sta installando l'abilità da skills.sh abbastanza?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2470,24 +2478,24 @@ msgstr "" " REA{ph1} per collegare il server MCP e installare l'abilità corrispondente," " quindi riavviare l'agente in modo che possa chiamare gli strumenti." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Analisi" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Cosa posso analizzare con REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Inizia con il tipo di software che hai:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2499,7 +2507,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2511,7 +2519,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2520,7 +2528,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2532,12 +2540,12 @@ msgstr "" "risorse pacchettizzate. {ph0}Vedi i casi di studio{ph1} per le indagini " "lavorate." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Ho bisogno di Hopper, Ghidra o IDA ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2549,7 +2557,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2562,12 +2570,12 @@ msgstr "" "quale provider può essere utilizzato. {ph0}Impostare l'analisi dei programmi" " di codice macchina{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Posso usare REA senza un agente di codifica?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2576,14 +2584,14 @@ msgstr "" "Sì. CLI utilizza gli stessi flussi di lavoro di analisi. Per un locale " "JavaScript o Electron app:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminale * analisi statica dell'applicazione" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2594,13 +2602,13 @@ msgstr "" " ASAR. {ph0}Utilizzare il CLI {ph1} per le opzioni di installazione." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Quale codice restituisce REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2615,7 +2623,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2627,12 +2635,12 @@ msgstr "" "e testare un'implementazione. Il {ph0} Calcolo DX-Ball{ph1} e {ph2}CTF flag " "checker{ph3} mostra come funziona questo processo." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Che cosa chiedo al mio agente?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2649,7 +2657,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2657,7 +2665,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2667,18 +2675,18 @@ msgstr "" "Sostituisci il percorso con il tuo obiettivo. Il {ph0}guida{ph1} fornire " "prompt per esempi nativi, Electron e browser." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Risoluzione dei problemi" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Perché il mio agente non può vedere gli strumenti REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2688,7 +2696,7 @@ msgstr "" "Riavviare o ricollegare l'agente dopo l'installazione. Controlla la sua " "registrazione REA con {ph0}; per Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminale * controllare un client" @@ -2696,7 +2704,7 @@ msgstr "Terminale * controllare un client" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2707,14 +2715,14 @@ msgstr "" "report mostra una registrazione mancante o obsoleta, eseguire setup per quel" " client:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminale * riparare la configurazione di un cliente" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2726,14 +2734,14 @@ msgstr "" "gli strumenti rimangono assenti, controllare l'errore di connessione MCP del" " client. {ph0}Più diagnostica di configurazione{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Devo iniziare prima Hopper?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2746,14 +2754,14 @@ msgstr "" "licenza prima dell'analisi automatica. {ph0}Vedere configurazione provider " "nativo{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Che cosa faccio se trovo un bug?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2765,7 +2773,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2778,17 +2786,17 @@ msgstr "" "degli errori. Includere il nome del provider quando il problema comporta " "l'analisi dei programmi di codice macchina." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Dati e condivisione" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "REA carica la mia app?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2797,7 +2805,7 @@ msgstr "" "REA analizza gli obiettivi sulla tua macchina. L'agente riceve i risultati e" " la politica dei dati del fornitore del modello si applica a tali risultati." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Come posso condividere un esempio o contribuire?" @@ -2806,7 +2814,7 @@ msgstr "Come posso condividere un esempio o contribuire?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2822,7 +2830,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2848,77 +2856,77 @@ msgstr "" " di analisi, agenti di codifica, risoluzione dei problemi e esempi di " "condivisione." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Domande frequenti su REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Copia il comando di installazione REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Copia il comando di aggiornamento REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Copy agent setup refresh command" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Copia il comando di analisi REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Copia esempio prompt di analisi" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Copia comando diagnosi client" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Copy scoped setup comando" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Vai al contenuto" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Casa{ph1} La tua prima indagine" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Scopri dove{ph0}le note esportate vanno." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2927,14 +2935,14 @@ msgstr "" "Usa REA per ispezionare una piccola app, segui il pulsante Esporta note e " "controlla tu stesso un dettaglio." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "In questo esercizio" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2942,7 +2950,7 @@ msgstr "{ph0}1. Istituire{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2950,7 +2958,7 @@ msgstr "{ph0}2. Chiedi informazioni sull'esportazione{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2958,7 +2966,7 @@ msgstr "{ph0}3. Segui la risposta{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2966,13 +2974,13 @@ msgstr "{ph0}4. Controllare una previsione{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Fai un'altra domanda{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Connetti il tuo agente a REA" @@ -2985,29 +2993,29 @@ msgstr "1. Connetti il tuo agente a REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Copia" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Oppure esegui questo comando nel tuo terminale:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3016,14 +3024,14 @@ msgstr "" "Rivedere il piano, approvare la configurazione, quindi riavviare l'agente. " "Sei già connesso? Continua sotto." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Chiedi dove è scritto CSV" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3035,7 +3043,7 @@ msgstr "" " pulsante. L'agente può ispezionare il codice senza installare o avviare " "Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3047,14 +3055,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Scarica esempio ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3065,12 +3073,12 @@ msgstr "" "archivio. Dare il percorso per il {ph0} cartella e la stessa domanda di " "esportazione." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Segui la risposta al codice" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Cerca una breve spiegazione con riferimenti a file e righe:" @@ -3079,7 +3087,7 @@ msgstr "Cerca una breve spiegazione con riferimenti a file e righe:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3091,12 +3099,12 @@ msgstr "" "note come CSV e scrive {ph1} nella cartella Download dell'utente. Le colonne" " sono {ph2} e {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Dal pulsante al file writer" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3105,7 +3113,7 @@ msgstr "" "L'analisi statica di REA associa il messaggio al suo gestore. La " "destinazione viene letta dal codice." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3117,7 +3125,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." @@ -3125,12 +3133,12 @@ msgstr "" "{ph0}Vedere la traccia completa del codice e il risultato REA " "registrato{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Controllare una previsione" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3139,19 +3147,19 @@ msgstr "" "Una virgola separa le colonne CSV. Cosa succede quando il titolo di una nota" " contiene una virgola o virgolette?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Esegui il controllo da solo" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Aprire un terminale nel disimballato {ph0} cartella:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3161,17 +3169,17 @@ msgstr "" "Zsh. Il tuo agente può eseguire lo stesso JavaScript nella shell della tua " "piattaforma." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Fai un'altra domanda" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Prova un follow-up nella stessa conversazione:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3180,7 +3188,7 @@ msgstr "" "Cosa succede se il file non può essere scritto? Seguire l'errore torna alla " "pagina." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3193,7 +3201,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3207,7 +3215,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3221,7 +3229,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3245,65 +3253,65 @@ msgstr "" "Prova REA su una piccola app Note. Imposta il tuo agente, chiedi dove vanno " "le note esportate e controlla il formatter CSV con un titolo di esempio." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "La tua prima indagine REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Copia REA prompt di installazione" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Copia comando setup" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Copia note richiesta di indagine" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Copia CSV prompt di controllo" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Comando Copia formatter check" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Vai al contenuto" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Casa{ph1} / Inizia" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Impostare REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3311,49 +3319,49 @@ msgstr "" "Connetti REA al tuo agente di codifica o ispeziona un'app locale dal tuo " "terminale." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Aprire un terminale e controllare:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminale" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Copia" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3366,7 +3374,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3377,17 +3385,17 @@ msgstr "" "su questo sistema\"{ph1} quando corri {ph2}, esegua questo una volta e " "riprova:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Se si utilizza Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Altrimenti:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Chiudere il terminale, aprirlo di nuovo, quindi:" @@ -3395,7 +3403,7 @@ msgstr "Chiudere il terminale, aprirlo di nuovo, quindi:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3407,7 +3415,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3419,7 +3427,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3429,14 +3437,14 @@ msgstr "" "Preferisci un normale installatore? Scarica la versione LTS da " "{ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Opzioni di configurazione" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3444,7 +3452,7 @@ msgstr "{ph0}Connetti il tuo agente di codifica{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3452,7 +3460,7 @@ msgstr "{ph0}Utilizzare il CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3460,18 +3468,18 @@ msgstr "{ph0}Impostare l'analisi dei programmi di codice macchina{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Ottenere aiuto{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Connetti il tuo agente di codifica" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3483,12 +3491,12 @@ msgstr "" "Build e altri client MCP supportati. Il connettore di Grok Bot viene " "aggiunto dalla sua chat." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Nuovi agenti di codifica?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3500,7 +3508,7 @@ msgstr "" "prima di apportare modifiche. REA fornisce strumenti di reverse engineering" " it." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3512,7 +3520,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3525,7 +3533,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3537,7 +3545,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3547,7 +3555,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}, fonte aperta. Connetti il fornitore di " "modelli di tua scelta." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3564,18 +3572,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "O eseguire l'installazione da soli" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Come faccio ad aprire un terminale?" @@ -3584,7 +3592,7 @@ msgstr "Come faccio ad aprire un terminale?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3600,7 +3608,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3614,7 +3622,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3629,7 +3637,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3639,7 +3647,7 @@ msgstr "" "Incolla un comando con {ph0} {ph1} ( macOS : {ph2} {ph3}; Terminali Linux: " "{ph4} {ph5} {ph6}), quindi premere Invio." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3651,12 +3659,12 @@ msgstr "" "backup della configurazione esistente. Chiede prima di applicare le " "modifiche." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Riavvia il client al termine dell'installazione." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Come faccio a riavviare il mio cliente?" @@ -3665,7 +3673,7 @@ msgstr "Come faccio a riavviare il mio cliente?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3681,7 +3689,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3691,7 +3699,7 @@ msgstr "" "{ph0}Agenti terminali{ph1} (Claude Code , Codex , Gemini CLI ): uscire dalla" " sessione e riavviarla." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3701,7 +3709,7 @@ msgstr "" "un'app JavaScript o Electron, potresti iniziare con:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3712,12 +3720,12 @@ msgstr "" "chiamate e le dipendenze coinvolte, con le posizioni di origine per i " "risultati." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Sostituisci il percorso con il tuo target locale." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Come ottengo il percorso completo di una cartella?" @@ -3726,7 +3734,7 @@ msgstr "Come ottengo il percorso completo di una cartella?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3742,7 +3750,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3754,7 +3762,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3764,19 +3772,19 @@ msgstr "" "{ph0}Qualsiasi sistema:{ph1} trascinare la cartella in una finestra di " "terminale e il suo percorso appare." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "In un terminale, metti le virgolette attorno a un percorso che contiene " "spazi." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Utilizzare il CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3785,14 +3793,14 @@ msgstr "" "Analizzare una cartella dell'applicazione JavaScript o Electron o un " "archivio ASAR senza eseguire l'app:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Analisi statica delle applicazioni" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3802,13 +3810,13 @@ msgstr "" "Sostituire il percorso con la directory dell'app estratta o {ph0} file. Su " "Windows, un percorso come {ph1} funziona qui." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Dove trovo un'app .file asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3819,7 +3827,7 @@ msgstr "Electron apps di solito tenerlo in un {ph0} cartella:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3831,7 +3839,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3844,21 +3852,21 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} spesso {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "" "Alcune app si installano altrove. Cerca nella cartella dell'app per {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3870,31 +3878,31 @@ msgstr "" " contrassegnate nel risultato." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Se vuoi un permanente {ph0} comando nella tua shell:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Installare il CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Continuare con la guida all'applicazione JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Impostare l'analisi dei programmi di codice macchina" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3904,12 +3912,12 @@ msgstr "" "locale. Scegli e configura uno di seguito, quindi assegna a REA l'eseguibile" " o la libreria." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Scegli uno strumento: Ghidra, Hopper o IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3921,17 +3929,17 @@ msgstr "" "richiede un decompiler nativo per l'architettura host. Impostare i percorsi " "prima di eseguire setup:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Collegare l'installazione Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Collegamento di Ghidra · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3943,12 +3951,12 @@ msgstr "" "Linux arm64, potrebbe essere necessario compilare separatamente il " "decompilatore nativo di Ghidra." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Collegare Ghidra su Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3959,12 +3967,12 @@ msgstr "" "native x86 e x64 PE e DLL su unità NTFS locali fisse. Utilizzare un Ghidra " "12.1 esistente.x installazione e un JDK 21 a 64 bit o più recente:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Connessione Ghidra * PowerShell Windows" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3972,7 +3980,7 @@ msgstr "" "Sostituire i due percorsi con le installazioni, quindi rivedere il piano di " "installazione." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3982,7 +3990,7 @@ msgstr "" "un'installazione esistente o offre un piano di installazione per " "l'approvazione." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3991,7 +3999,7 @@ msgstr "" "Su macOS, completa la scelta di prima esecuzione di Hopper della modalità " "demo o dell'attivazione della licenza prima di un'analisi automatica." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -4002,7 +4010,7 @@ msgstr "" "MCP esistente per una GUI collegata o un database headless. L'analisi senza" " testa Linux e macOS rimane non verificata." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Collegare una registrazione IDA MCP esistente" @@ -4012,7 +4020,7 @@ msgstr "Collegare una registrazione IDA MCP esistente" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4024,13 +4032,13 @@ msgstr "" "{ph2} in un file JSON. Un esistente {ph3} oggetto con un {ph4} si accetta " "anche l'ingresso. Punta REA su quel file prima dell'installazione:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Connessione IDA * PowerShell Windows" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4048,7 +4056,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4060,19 +4068,19 @@ msgstr "" " un agente, includere {ph1} nell'ambiente di registrazione REA e selezionare" " IDA quando si apre il binario." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "" "Per una configurazione Ghidra esistente, ispezionare una funzione con:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Analisi delle funzioni" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." @@ -4080,13 +4088,13 @@ msgstr "" "Sostituire {ph0} con il nome della funzione o l'indirizzo che si desidera " "ispezionare." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "" "Come funzionano le sessioni di analisi dei programmi di codice macchina" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4099,7 +4107,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4109,18 +4117,18 @@ msgstr "" "{ph0}Seguire un esempio di analisi dei programmi di codice macchina{ph1} per" " vedere come il risultato della funzione porta a un calcolo recuperato." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Ottenere aiuto" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Se il tuo agente non vede REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4130,27 +4138,27 @@ msgstr "" "Riavviare o ricollegare il client dopo l'installazione. Controlla la sua " "connessione REA con {ph0}; per Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Controlla un cliente" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Se un fornitore ha bisogno di attenzione" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Controlla il provider che stai utilizzando. Per Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Controllare un provider" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4161,7 +4169,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4174,7 +4182,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4188,7 +4196,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4202,7 +4210,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4225,112 +4233,112 @@ msgstr "" "Electron locale dal terminale. Configurazione, prime domande e guide native " "provider." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Copia controllo versione Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Copia il comando di installazione Node.js per Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Copia il comando PowerShell execution policy" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Copia il comando di installazione Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Copia il comando di installazione fnm per macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Copia i comandi Node.js 24 per macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Copia il comando di installazione fnm per Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Copia i comandi Node.js 24 per Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA guida introduttiva" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Copia REA prompt di installazione" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Copy agent setup comando" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Copia il comando di analisi JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Copia il comando di installazione CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Copia il comando di connessione a Ghidra per macOS e Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Copia connessione Ghidra per PowerShell Windows" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Copia connessione IDA per PowerShell Windows" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Copia il comando di analisi delle funzioni native" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Copia comando diagnosi client" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Comando di diagnosi del provider di copia" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -4339,20 +4347,20 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Casa{ph1} / {ph2}Guida{ph3} / Osservazione del browser" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Vedi cosa succede{ph0}quando si fa clic." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4361,14 +4369,14 @@ msgstr "" "Utilizzare una piccola applicazione browser per collegare un'azione, la sua " "richiesta di rete e il JavaScript che costruisce un download." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "In questa guida" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4376,7 +4384,7 @@ msgstr "{ph0}Esempio{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4384,7 +4392,7 @@ msgstr "{ph0}Apri il browser{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4392,7 +4400,7 @@ msgstr "{ph0}Chiedi al tuo agente{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4400,13 +4408,13 @@ msgstr "{ph0}Cattura da CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Leggi la richiesta e lo script{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Cosa succede quando fai clic su Esporta?" @@ -4416,7 +4424,7 @@ msgstr "Cosa succede quando fai clic su Esporta?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4428,7 +4436,7 @@ msgstr "" "pulsante. Cliccando carica {ph4}, formatta le due note come CSV, e avvia un " "download." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Dal clic al CSV scarica" @@ -4439,7 +4447,7 @@ msgstr "Dal clic al CSV scarica" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4455,7 +4463,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4474,7 +4482,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4485,17 +4493,17 @@ msgstr "" "esportazione{ph3}{ph4}Collegare la richiesta osservata a {ph5} in " "{ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Avviare l'acquisizione prima di fare clic su Esporta note." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Aprire Chrome con debug remoto" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4504,21 +4512,21 @@ msgstr "" "Aprire l'esempio di Note ospitate con un profilo browser separato e una " "porta di debug locale. Su Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Avviare il browser di esempio" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Copia" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4528,7 +4536,7 @@ msgstr "" ". È possibile sostituire l'URL della pagina con un'altra pagina che si " "desidera ispezionare." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4537,7 +4545,7 @@ msgstr "" "REA si connette a questo browser esistente. Mantieni il controllo della " "pagina, esegui l'azione e chiudi il browser al termine." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Chiedi al tuo agente di guardare un'azione" @@ -4550,7 +4558,7 @@ msgstr "Chiedi al tuo agente di guardare un'azione" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4562,7 +4570,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4574,7 +4582,7 @@ msgstr "" "CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4584,7 +4592,7 @@ msgstr "" "Esempio prompt. Fornisci al tuo agente l'endpoint di debug, {ph0}, e l'URL " "della pagina. Lascia che inizi la cattura prima di fare clic." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4595,23 +4603,23 @@ msgstr "" "osservazione e legge le prove risultanti. Può quindi ispezionare lo script " "dietro l'esportazione." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "O cattura dal terminale" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Trova l'ID di destinazione della pagina:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Trova la pagina" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4621,14 +4629,14 @@ msgstr "" "Scegli la destinazione con l'URL di esempio Notes. Sostituire {ph0} sotto " "con il suo ID, quindi esegui:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Cattura i prossimi dieci secondi" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4639,7 +4647,7 @@ msgstr "" "{ph0}Note di esportazione{ph1} in quel browser. Il risultato arriva dopo la " "fine della finestra di osservazione." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4650,49 +4658,49 @@ msgstr "" "durante quella finestra e la forma della risposta JSON. Le richieste " "precedenti sono al di fuori di questa acquisizione." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Leggere lo script di richiesta ed esportazione" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Registrato con REA 4.1.0 nell'esempio local Notes" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Fatto catturato" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Valore" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Richiesta" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Risposta" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Iniziatore della richiesta" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} · script" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Struttura di risposta" @@ -4700,19 +4708,19 @@ msgstr "Struttura di risposta" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} con {ph1} e {ph2} campo" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Leggi gli script caricati" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4724,7 +4732,7 @@ msgstr "" " utilizzati i dati:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4737,7 +4745,7 @@ msgstr "" "stabilisce che questo clic richiesto {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4749,7 +4757,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4774,65 +4782,65 @@ msgstr "" "browser, catturare un clic, ispezionare la richiesta e seguire lo script di " "esportazione." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Osservazione del browser" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Copia avvia il browser di esempio" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Copia esempio prompt" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Copia trova la pagina" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Copia cattura i prossimi dieci secondi" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Copia leggi gli script caricati" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Vai al contenuto" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Casa{ph1} / Guida" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Guide REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4841,37 +4849,37 @@ msgstr "" "Analizzare una funzione nativa, un'esportazione Electron o una richiesta del" " browser. Ogni guida include un prompt, codice e risultati." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Prima indagine" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Impostare REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Collega il tuo agente di codifica o usa REA dal terminale." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Inizia con REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Programmi a codice macchina" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Recuperare un calcolo della posizione del suono sinistra/destra" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4881,22 +4889,22 @@ msgstr "" "seguire un chiamante, leggere costanti numeriche e controllare il C " "recuperato." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Guida all'analisi dei programmi di codice macchina" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Seguire un'esportazione CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4906,14 +4914,14 @@ msgstr "" "precarico e il processo principale. Utilizzare REA per collegare l'API, il " "canale IPC e il file writer." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Guida di JavaScript & Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4921,17 +4929,17 @@ msgstr "" "Per un'app pacchettizzata più grande, segui {ph0} Ponte appunti di " "Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Comportamento del browser" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Osservare un clic" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4940,7 +4948,7 @@ msgstr "" "Aprire un esempio di Note di lavoro, acquisire una richiesta di esportazione" " e trovare il codice che trasforma la sua risposta in un download." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Guida all'osservazione del browser" @@ -4959,12 +4967,12 @@ msgstr "" "Impara REA attraverso brevi esempi elaborati: un calcolo nativo, " "un'esportazione Electron CSV e una richiesta del browser." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -4973,20 +4981,20 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Casa{ph1} / {ph2}Guida{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Traccia un Electron {ph0} Esportazione CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4995,14 +5003,14 @@ msgstr "" "Segui un clic del pulsante dall'API della pagina, tramite Electron IPC, al " "file writer CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "In questa guida" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -5010,7 +5018,7 @@ msgstr "{ph0}Esempio{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5018,7 +5026,7 @@ msgstr "{ph0}Chiedi al tuo agente{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5026,7 +5034,7 @@ msgstr "{ph0}Traccia il codice di esportazione{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5034,20 +5042,20 @@ msgstr "{ph0}Prova l'esempio{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Ispezionare il writer CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Dove vanno le \"note di esportazione\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5059,7 +5067,7 @@ msgstr "" "esportazione{ph1} chiama un'API nella pagina, attraversa il processo " "principale e scrive un CSV . Il comportamento è distribuito su più file." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "L'esportazione di CSV attraverso i processi Electron" @@ -5073,7 +5081,7 @@ msgstr "L'esportazione di CSV attraverso i processi Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5090,7 +5098,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5107,7 +5115,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5120,13 +5128,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} formatta le note → {ph1} scrivere {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5137,14 +5145,14 @@ msgstr "" "l'API esposta. Il percorso è dedotto dal codice; un'acquisizione di runtime " "può controllare ciò che viene eseguito." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Chiedi informazioni sull'esportazione CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5162,14 +5170,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Copia" @@ -5180,7 +5188,7 @@ msgstr "Copia" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5191,7 +5199,7 @@ msgstr "" "questa app. Dove viene creato CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5201,7 +5209,7 @@ msgstr "" "Esempio prompt. Includere il percorso assoluto della cartella " "dell'applicazione o {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5212,17 +5220,17 @@ msgstr "" " confini di processo. L'agente utilizza tale mappa per restringere " "l'indagine alla funzione di esportazione." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Traccia il codice di esportazione" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "La pagina chiama una piccola API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5233,7 +5241,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5245,7 +5253,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5256,7 +5264,7 @@ msgstr "" "note e il processo principale scrive {ph1} nella cartella Download " "dell'utente." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5265,7 +5273,7 @@ msgstr "" "Registrato da REA 4.1.0 nell'esempio scaricabile qui sotto. Le posizioni di " "origine accompagnano i risultati dell'API, del canale e del gestore." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Analizza l'esempio da solo" @@ -5273,25 +5281,25 @@ msgstr "Analizza l'esempio da solo" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Scarica esempio ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Sfoglia i sei file sorgente" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Analisi statica delle applicazioni" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5302,7 +5310,7 @@ msgstr "" "canale IPC e un gestore corrispondente in {ph0}. Le posizioni di origine " "sono in {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5313,13 +5321,13 @@ msgstr "" "ASAR. Un agente può seguire una stringa letterale, un nome API o un canale " "IPC con gli strumenti di tracciamento delle funzionalità di REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Ispezionare il writer CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5329,7 +5337,7 @@ msgstr "" "Seguire {ph0} al suo gestore. Quali input raggiungono il writer CSV e cosa " "succede se la scrittura del file non riesce?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5344,7 +5352,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5358,7 +5366,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5372,7 +5380,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5398,32 +5406,32 @@ msgstr "" "precarico e un gestore IPC con REA . Include file di esempio scaricabili e " "un risultato di analisi verificato." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Copia esempio prompt" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Copia analisi applicazione statica" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -5432,7 +5440,7 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5440,14 +5448,14 @@ msgstr "" "{ph0}Casa{ph1} / {ph2}Guida{ph3} / Analisi di programmi a codice macchina" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "" "Recuperare di DX-Ball{ph0}calcolo della posizione sonora sinistra/destra." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5456,14 +5464,14 @@ msgstr "" "Ispezionare le istruzioni originali, identificare l'input e le costanti, " "quindi controllare il C recuperato." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "In questa guida" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5471,7 +5479,7 @@ msgstr "{ph0}Esempio{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5479,7 +5487,7 @@ msgstr "{ph0}Chiedi al tuo agente{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5487,7 +5495,7 @@ msgstr "{ph0}Leggi i risultati di REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5495,18 +5503,18 @@ msgstr "{ph0}Recuperare e controllare{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Usa il tuo binario{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Calcola il posizionamento del suono stereo sinistro / destro" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5518,7 +5526,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5530,7 +5538,7 @@ msgstr "" "chiamata a {ph1}. REA restituisce anche le sue istruzioni e i chiamanti, " "che danno all'agente un modo per indagare sull'aritmetica mancante." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Nuovo a questi termini?" @@ -5539,7 +5547,7 @@ msgstr "Nuovo a questi termini?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5551,7 +5559,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5564,7 +5572,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5577,7 +5585,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5589,7 +5597,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5599,7 +5607,7 @@ msgstr "" "{ph0}Costante:{ph1} numeri fissi memorizzati nel programma, letti come byte " "grezzi e decodificati." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Tre prove, un calcolo" @@ -5610,7 +5618,7 @@ msgstr "Tre prove, un calcolo" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5627,7 +5635,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5645,7 +5653,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5655,7 +5663,7 @@ msgstr "" "{ph0}03 * Byte di dati{ph1}{ph2}Le costanti numeriche{ph3}{ph4}I byte di " "riferimento decodificano a {ph5}, {ph6} e un valore di scala.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5664,7 +5672,7 @@ msgstr "" "REA fornisce le istruzioni, la relazione funzione-chiamata e i byte. " "L'agente li interpreta insieme." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Chiedi del comportamento" @@ -5673,7 +5681,7 @@ msgstr "Chiedi del comportamento" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5684,19 +5692,19 @@ msgstr "" "strumento di analisi dei programmi di codice macchina{ph3}, fornisca " "l'eseguibile locale e una domanda:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Quale strumento di analisi dovrei usare?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA ha bisogno di uno di questi per leggere i programmi nativi:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5710,7 +5718,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5723,7 +5731,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5734,7 +5742,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5750,14 +5758,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Copia" @@ -5768,7 +5776,7 @@ msgstr "Copia" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5779,7 +5787,7 @@ msgstr "" "posizionamento del suono stereo. Spiega il calcolo e mostra il " "codice.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5790,7 +5798,7 @@ msgstr "" "1.07 locale. REA non include DX-Ball, quindi usa la tua copia o fai lo " "stesso tipo di domanda su un altro piccolo programma Windows che hai." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Come ottengo il percorso completo di un file?" @@ -5799,7 +5807,7 @@ msgstr "Come ottengo il percorso completo di un file?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5814,7 +5822,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5826,7 +5834,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5836,17 +5844,17 @@ msgstr "" "{ph0}Qualsiasi sistema:{ph1} trascinare il file in una finestra di terminale" " e il suo percorso appare." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Leggi i risultati di REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Leggi l'input" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5855,13 +5863,13 @@ msgstr "" "Le istruzioni caricano un argomento intero e lo convertono per l'aritmetica " "in virgola mobile. Questo è l'input assente dalla prima vista pseudocodice." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Segui il chiamante" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5872,12 +5880,12 @@ msgstr "" "moltiplicano la coordinata tile per 30; aggiunta {ph0} (20) dà la posizione " "dello schermo del mattone." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Leggi le costanti di riferimento" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5887,12 +5895,12 @@ msgstr "" " i valori effettivi; l'ordine di istruzioni indica all'agente come vengono " "utilizzati." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Scrivi e controlla la funzione recuperata" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5903,7 +5911,7 @@ msgstr "" "-500, 0 e 500 prima della conversione intera. Il calcolo mette il centro " "dello schermo al centro del campo stereo." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5916,20 +5924,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Vedi l'indagine completa e il confronto assembly-to-C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Provalo con il tuo binario" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5944,7 +5952,7 @@ msgstr "" "Come viene analizzato questo file?\"o\" Quale funzione gestisce questa " "azione del menu?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5953,13 +5961,13 @@ msgstr "" "Se si conosce già il nome o l'indirizzo di una funzione, è possibile " "interrogarlo dal terminale. Per un'installazione Ghidra configurata:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Analisi delle funzioni" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5973,7 +5981,7 @@ msgstr "" "binario, quindi chiude la sua sessione. Le query MCP dell'agente " "riutilizzano il binario importato mentre la sessione è aperta." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5997,50 +6005,50 @@ msgstr "" "Recuperare un calcolo nativo con REA: ispezionare le istruzioni, seguire un " "chiamante, leggere le costanti e controllare ricostruito C." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Analisi di programmi a codice macchina" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Copia esempio prompt" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Analisi delle funzioni di copia" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Vai al contenuto" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Impostare REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6048,7 +6056,7 @@ msgstr "{ph0}Impostare REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6056,7 +6064,7 @@ msgstr "{ph0}Cos'è RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6064,7 +6072,7 @@ msgstr "{ph0}Come aiuta REA{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6072,7 +6080,7 @@ msgstr "{ph0}Dinosauro gioco{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6080,7 +6088,7 @@ msgstr "{ph0}Calcolatore{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6088,7 +6096,7 @@ msgstr "{ph0}Prova REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6096,7 +6104,7 @@ msgstr "{ph0}Approfondisci{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6104,25 +6112,25 @@ msgstr "{ph0}Aiuto e feedback{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Comunità{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Reverse engineering, con il tuo agente di codifica" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Scopri come{ph0}funziona il software." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6133,7 +6141,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6141,13 +6149,13 @@ msgstr "Sai già RE? {ph0}Vai alle guide di analisi →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Vuoi andare più a fondo? {ph0}Leggi il Blog →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Copia questo prompt nel tuo agente di programmazione:" @@ -6160,38 +6168,38 @@ msgstr "Copia questo prompt nel tuo agente di programmazione:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Copia" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Oppure esegui questo comando nel terminale:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Controlla e approva le modifiche previste, poi riavvia il tuo agente." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Che cos’è il reverse engineering?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6205,7 +6213,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6217,7 +6225,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6225,7 +6233,7 @@ msgstr "Prima di REA · Indaghi {ph0}da solo{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6233,7 +6241,7 @@ msgstr "{ph0}01{ph1} Decodifica rami" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6241,7 +6249,7 @@ msgstr "{ph0}02{ph1} Traccia chiamate" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6251,20 +6259,20 @@ msgstr "{ph0}03{ph1} Recuperare la regola" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Originale x64 * istruzioni selezionate{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * Quale ramo ·" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6274,29 +6282,29 @@ msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Due salti nello stesso posto. Quali operatori sono " "questi?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Cerca gli ID del comando, quindi etichetta il ramo." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Dividere ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Moltiplicare ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Che cosa fanno le funzioni chiamate?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6306,24 +6314,24 @@ msgstr "" "\"100 è chiaro. Le chiamate sono solo indirizzi. {ph0}Quale divide? Quale " "valore entra?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Ispezionare le funzioni di supporto e tracciare i valori memorizzati." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Dividere" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * Qual è la regola ·" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6333,20 +6341,20 @@ msgstr "" "\"Questo percorso si moltiplica per l'altro input. Cosi {ph0}10% significa " "10% di 200{ph1} dopo +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "" "Assegnare un nome agli operandi e controllare entrambi i percorsi operatore." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Ragionamento illustrativo esperto" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6358,20 +6366,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Con REA · Chiedi al {ph0}tuo agente{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Un solo prompt." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6385,49 +6393,49 @@ msgstr "Fai una domanda al tuo agente {ph0}con parole semplici.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Esempio prompt * Calcolatrice" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Esempio di risposta * in base ai risultati" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "Dopo +, il pulsante % prende {ph0}percentuale del primo numero.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA fornisce" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Istruzioni del gestore, codice decompilato e chiamate." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Il tuo agente spiega" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Quale ramo si applica, cosa calcola e come ricostruirlo." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6440,7 +6448,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6450,37 +6458,37 @@ msgstr "" "{ph0}Proviamo due esempi.{ph1} Modificare la velocità di un gioco, quindi " "tornare a Calcolatrice e ricostruire il suo pulsante%." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Esempio 01 * Gioco di dinosauri di Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Perché il dinosauro diventa più veloce?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Obiettivo" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Ricostruisci il gioco con {ph0}velocità regolabile.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Perché il reverse engineering?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6491,49 +6499,49 @@ msgstr "" "gioco in esecuzione{ph1}: quanto velocemente inizia, quanto aumenta e quando" " si ferma." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Gioca alla ricostruzione" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Gioca" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Salta ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Ricomincia" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Velocità" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Utilizzare la regola di accelerazione recuperata" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Regola originale: inizia da 6, quindi aumenta verso 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Spostare il cursore per impostare la propria velocità. Spazio o salto " "cancella un cactus." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6542,14 +6550,14 @@ msgstr "" "Abilita JavaScript per riprodurre la ricostruzione. Il codice e la " "spiegazione di cui sopra rimangono leggibili." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA ha restituito" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6568,7 +6576,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6581,7 +6589,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6595,7 +6603,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6609,7 +6617,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6619,12 +6627,12 @@ msgstr "" "{ph0}Inizia alle 6.{ph1} Aggiungere {ph2}0.001{ph3} ogni aggiornamento senza" " una collisione, mentre la velocità è inferiore {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Apri lo speed lab" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Cosa fa ogni parte" @@ -6635,7 +6643,7 @@ msgstr "Cosa fa ogni parte" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6652,7 +6660,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6669,7 +6677,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6679,13 +6687,13 @@ msgstr "" "{ph0}03 * Tu{ph1}{ph2}Cambiare la velocità e giocare{ph3}{ph4}Prova " "l'accelerazione originale, quindi scegli il tuo ritmo.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Vedi lo script, i controlli e come provare l'analisi" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6695,7 +6703,7 @@ msgstr "" "REA ispezionato l'edizione del browser HTTP tramite una connessione di debug" " locale e restituito il caricato {ph0}, compresa la sua fonte e digest." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6709,7 +6717,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6726,7 +6734,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6744,7 +6752,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6753,19 +6761,19 @@ msgstr "" "{ph0}Codice di velocità ispezionato{ph1} · {ph2} Autori Chromium * Licenza " "BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Esempio 02 * Calcolatrice Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Ricrea il pulsante % della calcolatrice." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6776,7 +6784,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6787,29 +6795,29 @@ msgstr "" "Controlliamo l'app installata per trovare a quale numero viene applicata la " "percentuale." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Prova il calcolo" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Reimposta" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% di 200 = 20. Quindi 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Illustrazione interattiva della regola percentuale ispezionata." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6821,7 +6829,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6835,7 +6843,7 @@ msgstr "Per questo esempio, {ph0} e {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6851,7 +6859,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6863,7 +6871,7 @@ msgstr "" "calcolatrice Windows. Recuperare le regole dopo + e×, quindi costruire una " "piccola calcolatrice che utilizza entrambi.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Con +" @@ -6871,13 +6879,13 @@ msgstr "Con +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Prendi il 10% del primo numero.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Con ×" @@ -6885,13 +6893,13 @@ msgstr "Con ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Trasforma il 10% in 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Dall'app installata a un pulsante % funzionante" @@ -6903,7 +6911,7 @@ msgstr "Dall'app installata a un pulsante % funzionante" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6921,7 +6929,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6933,12 +6941,12 @@ msgstr "" "regole{ph3}{ph4}Crosscheck il ramo con la fonte di Microsoft, quindi provare" " + e × sopra.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Vedi il codice reale e come è stata controllata la risposta" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6959,7 +6967,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6969,17 +6977,17 @@ msgstr "" "{ph0}Percentuale di attuazione{ph1} · {ph2}I test case di Microsoft{ph3} · " "{ph4}Guida all'installazione nativa{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "La tua prima indagine" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Prova REA su una piccola app." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6988,12 +6996,12 @@ msgstr "" "Scarica il nostro esempio di Note, traccia la sua esportazione CSV e " "controlla un input modificato." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Prova l'esempio guidato" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Vuoi approfondire?" @@ -7002,7 +7010,7 @@ msgstr "Vuoi approfondire?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7022,13 +7030,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Esempio prompt * Sito web" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Sì, questa." @@ -7041,7 +7049,7 @@ msgstr "Sì, questa." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7056,7 +7064,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7070,23 +7078,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Vedere il caso di studio DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Per le fasi di configurazione e analisi, scegli il tuo target:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Programmi a codice macchina" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7095,17 +7103,17 @@ msgstr "" "Ispezionare funzioni, stringhe, riferimenti e relazioni di chiamata di " "funzione in eseguibili e librerie." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Guida all'analisi dei programmi di codice macchina" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7114,17 +7122,17 @@ msgstr "" "Mappa moduli, percorsi, IPC e dipendenze native da una cartella " "dell'applicazione o da un archivio ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Flussi di lavoro delle applicazioni" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Attività del browser e runtime" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7133,12 +7141,12 @@ msgstr "" "Cattura l'attività del browser o del processo selezionata, quindi confronta " "i risultati tra le varie esecuzioni." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Guida all'osservazione del browser" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Hai domande?" @@ -7149,7 +7157,7 @@ msgstr "Hai domande?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7159,12 +7167,12 @@ msgstr "" "{ph0}Leggi le FAQ{ph1}, {ph2}chatta con noi su Discord {ph3}, o {ph4}aprire " "un problema GitHub{ph5} per bug e richieste di funzionalità." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Unisciti alla community" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7187,27 +7195,27 @@ msgstr "" "Decodificare app, binari e comportamento del browser con il tuo agente di " "codifica. Segui guide chiare e prova esempi interattivi con REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Copia REA prompt di installazione" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Copia comando setup" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Seguire l'analisi calcolatrice manuale" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Copia Calcolatrice percentuale domanda" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7216,37 +7224,37 @@ msgstr "" "Dinosauro mini-gioco. Utilizzare il pulsante di salto o premere Spazio " "mentre il gioco è focalizzato." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copia dinosaur analysis prompt" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Scegli il calcolo" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Copia Calcolatrice analisi prompt" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Copia il prompt del progetto del sito web" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Copia gioco ricostruzione prompt" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -7255,25 +7263,25 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Casa{ph1} / {ph2}Vetrina{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Caso di studio · Autenticatore Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Come funziona un autenticatore{ph0}generare un codice di accesso?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7283,17 +7291,17 @@ msgstr "" " in un APK Android, quindi ricostruiscilo con un orologio che puoi " "controllare." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * Versione ufficiale APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Vedi Aegis su GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Da un APK a un codice che puoi riprodurre" @@ -7304,7 +7312,7 @@ msgstr "Da un APK a un codice che puoi riprodurre" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7322,7 +7330,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7340,7 +7348,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7352,14 +7360,14 @@ msgstr "" "codice.{ph3}{ph4}Una nuova demo del browser riproduce la regola e la " "confronta con i casi di riferimento pubblico.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "In questo caso di studio" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7367,7 +7375,7 @@ msgstr "{ph0}Chiedi al tuo agente{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7375,7 +7383,7 @@ msgstr "{ph0}Prova il generatore di codice{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7383,7 +7391,7 @@ msgstr "{ph0}Trova il codice con REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7391,7 +7399,7 @@ msgstr "{ph0}Leggi il calcolo{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7399,20 +7407,20 @@ msgstr "{ph0}Controlla la ricostruzione{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Ispezionare il APK da soli{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Chiedi al tuo agente" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7430,21 +7438,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Copia" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7454,14 +7462,14 @@ msgstr "" "Un prompt di esempio per il APK scaricato, con l'analisi Android di REA " "configurata. {ph0}Ottenere il APK e la configurazione di analisi ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Prova il generatore di codice" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7473,33 +7481,33 @@ msgstr "" "numero di blocco con la chiave dell'account per generare un codice. La " "stessa chiave e blocco producono lo stesso codice." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Spostare l'orologio attraverso 60 secondi" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Tempo" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "secondo" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Il nostro orologio di esempio regolabile" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "blocco di 30 secondi" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Blocco" @@ -7508,35 +7516,35 @@ msgstr "Blocco" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 secondi{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Codice generato" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Chiave account + blocco → sei cifre" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Tempo di esempio, in secondi" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 secondi" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 secondi" @@ -7545,7 +7553,7 @@ msgstr "60 secondi" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7557,7 +7565,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7567,7 +7575,7 @@ msgstr "" "La chiave è fissa, pubblica {ph0}Dati di prova RFC 6238{ph1}. La demo " "implementa il calcolo recuperato dal APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7576,18 +7584,18 @@ msgstr "" "Il diagramma mostra il risultato a 59 secondi. Abilita JavaScript per " "cambiare l'orologio." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Trova il codice con REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Restringere il APK a tre classi" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7598,14 +7606,14 @@ msgstr "" "avanzamento e gli account importati. TOTP indica una password una tantum " "basata sul tempo." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Collegare il generatore al display dell'app" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7616,7 +7624,7 @@ msgstr "" "base. Ispezionare {ph0} poi mostra il display chiamata {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7626,14 +7634,14 @@ msgstr "" "Le richieste mostrano un percorso di input abbreviato. I nomi delle classi " "dei risultati omettono il comune {ph0} prefisso." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Leggi il calcolo" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7648,7 +7656,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7656,7 +7664,7 @@ msgstr "{ph0}01{ph1} Blocco di tempo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7664,7 +7672,7 @@ msgstr "{ph0}02{ph1} Chiave + blocco" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7672,7 +7680,7 @@ msgstr "{ph0}03{ph1} Sei cifre" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7684,7 +7692,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7698,7 +7706,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7712,7 +7720,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7723,7 +7731,7 @@ msgstr "" "visualizzazione. Il pannello di destra è un riassunto esplicativo. {ph0} Il " "codice Aegis è GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "All'interno del generatore" @@ -7732,7 +7740,7 @@ msgstr "All'interno del generatore" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7742,7 +7750,7 @@ msgstr "" "Il APK rilasciato mette {ph0} in {ph1}. REA segue la chiamata da {ph2} e " "restituisce questo corpo; la fonte originale chiama l'helper {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7759,20 +7767,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Confronta con la sorgente di rilascio corrispondente{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Controlla la ricostruzione" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7785,29 +7793,29 @@ msgstr "" "indipendente su {ph0}133 casi di prova{ph1}, compresi i limiti del blocco " "temporale e i codici che iniziano con zero." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Tempo di esempio" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Codice a sei cifre" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 secondi" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 secondi" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7818,17 +7826,17 @@ msgstr "" "in {ph0}RFC 6238{ph1}. Controlla l'implementazione del browser contro di " "loro:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Eseguire controlli di riferimento" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Leggi il calcolo della demo" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7837,7 +7845,7 @@ msgstr "" "I casi di riferimento utilizzano otto cifre. Il controllo verifica anche i " "loro risultati a sei cifre." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7846,14 +7854,14 @@ msgstr "" "Verifica esegue metodi Java estratti e la nuova demo. L'Android APK è stato " "ispezionato staticamente." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Ispezionare il APK da soli" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7865,7 +7873,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7875,18 +7883,18 @@ msgstr "" "Android analysis ha bisogno di un JDK completo 17 o successivo. Selezionalo " "con {ph0} o {ph1}. Questo caso ha usato JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Puntare REA sul file del provider e ispezionare APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7898,7 +7906,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7908,7 +7916,7 @@ msgstr "" "Una prossima domanda: {ph0}cosa succede quando un account utilizza otto " "cifre o un intervallo di tempo diverso?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Fonte" @@ -7924,7 +7932,7 @@ msgstr "Fonte" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7938,13 +7946,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}RFC 6238 casi di riferimento{ph1} · {ph2}Dati di prova demo{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7969,37 +7977,37 @@ msgstr "" "Ispeziona Aegis Android APK con REA, recupera il calcolo del codice di " "accesso a sei cifre e prova una ricostruzione con un orologio regolabile." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Studio di caso Aegis APK" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Copia il prompt di esempio di Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Segui il calcolo del codice di accesso" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Copia il comando di ispezione APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -8008,26 +8016,26 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Casa{ph1} / {ph2}Vetrina{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Caso di studio * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Trova la bandiera in{ph0}un binario CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8038,17 +8046,17 @@ msgstr "" "regole in equazioni e trovare un input che faccia stampare il programma " "originale {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "quadrati mascherati bandiera checker * Facile * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Visualizza la sfida originale" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Da un binario a una risposta controllata" @@ -8059,7 +8067,7 @@ msgstr "Da un binario a una risposta controllata" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8077,7 +8085,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8095,7 +8103,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8107,21 +8115,21 @@ msgstr "" "Corretta!{ph3}{ph4}Uno script Python risolve le equazioni. REA cattura il " "programma originale accettando il risultato.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" "La sfida è di joseph, pubblicato nel repository ufficiale di DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "In questo caso di studio" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8129,7 +8137,7 @@ msgstr "{ph0}Trova il codice di controllo{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8137,7 +8145,7 @@ msgstr "{ph0}Leggi una maschera{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8145,7 +8153,7 @@ msgstr "{ph0}Assembly a codice leggibile{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8153,7 +8161,7 @@ msgstr "{ph0}Risolvi le equazioni{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8161,20 +8169,20 @@ msgstr "{ph0}Controlla la risposta{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Provalo tu stesso{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Trova il codice di controllo" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8192,17 +8200,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Copia" @@ -8213,7 +8221,7 @@ msgstr "Copia" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8225,7 +8233,7 @@ msgstr "" "flag. Spiega come funzionano i controlli, quindi verifica la risposta con il" " programma originale.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8234,12 +8242,12 @@ msgstr "" "Un prompt di esempio, con la sfida scaricata disponibile localmente e " "un'analisi del provider di programmi di codice macchina collegato." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Seguire il prompt di input per la sua funzione" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8248,14 +8256,14 @@ msgstr "" "Il riferimento fornisce all'agente un posto in cui indagare, anche se i nomi" " delle funzioni originali dell'eseguibile sono stati rimossi." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Leggi il correttore e i suoi due aiutanti" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8268,7 +8276,7 @@ msgstr "" " con un numero memorizzato. Sua {ph0}- passi byte attraverso {ph1} i byte " "danno 26 maschere." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8278,12 +8286,12 @@ msgstr "" "destinazione locale viene abbreviato per la visualizzazione; gli indirizzi " "si riferiscono all'immagine importata di REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Un controllo rivela un carattere" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8296,14 +8304,14 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "" "Il settimo controllo seleziona solo una posizione. {ph0}Apri figura{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Leggi la maschera e il suo obiettivo dal binario" @@ -8312,7 +8320,7 @@ msgstr "Leggi la maschera e il suo obiettivo dal binario" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8325,12 +8333,12 @@ msgstr "" "Insieme, questi byte dicono all'agente che {ph2}, in modo che il carattere è" " {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Dalle istruzioni a un controllo leggibile" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8341,7 +8349,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8349,7 +8357,7 @@ msgstr "{ph0}01{ph1} Inizia" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8357,7 +8365,7 @@ msgstr "{ph0}02{ph1} Selezionare" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8365,7 +8373,7 @@ msgstr "{ph0}03{ph1} Aggiungere" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8373,18 +8381,18 @@ msgstr "{ph0}04{ph1} Anticipo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Confrontare" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * istruzioni originali selezionate" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Leggibile C * riepilogo di un controllo" @@ -8392,7 +8400,7 @@ msgstr "Leggibile C * riepilogo di un controllo" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8400,7 +8408,7 @@ msgstr "{ph0}01 * Inizia da zero.{ph1} {ph2} contiene la somma corrente." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8412,7 +8420,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8424,7 +8432,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8438,7 +8446,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8448,7 +8456,7 @@ msgstr "" "{ph0}05 * Confronta con l'obiettivo memorizzato.{ph1} Il chiamante riceve la" " somma in {ph2}. Una mancata corrispondenza salta a {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8458,12 +8466,12 @@ msgstr "" "un riassunto esplicativo con nomi descrittivi e un ciclo appiattito a 36 " "celle." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Risolvi le 26 equazioni" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8475,13 +8483,13 @@ msgstr "" "1441. Le selezioni sovrapposte danno equazioni che un piccolo script Python " "può risolvere insieme." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * estratto del risolutore" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8495,19 +8503,19 @@ msgstr "" "lettere, cifre, caratteri di sottolineatura e parentesi graffe. Il download " "completo include tutte le 26 maschere e obiettivi." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Scarica il risolutore completo" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Controlla la risposta con il programma originale" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8519,47 +8527,47 @@ msgstr "" "accettando il flag risolto. Modifica di un carattere selezionato da {ph0} " "per {ph1} fa la prima somma 1440 invece di 1441, e il programma lo rifiuta." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Input" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Uscita osservata" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Codice di uscita" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Bandiera del risolutore" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Un personaggio cambiato" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Mostra il flag recuperato e l'output catturato" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * uscita del programma originale" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Copia bandiera" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8569,12 +8577,12 @@ msgstr "" "sfida pubblicati dagli organizzatori, controllati dopo aver risolto il " "binario." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Fonte, identità di destinazione e dettagli di analisi" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8585,7 +8593,7 @@ msgstr "" "utilizzando REA 4.1.0 con Ghidra 12.1.4 su Linux x64. Il binario è un ELF " "x86-64 spogliato, 15.248 byte." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8608,7 +8616,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8618,12 +8626,12 @@ msgstr "" "{ph0}Confronta con la fonte degli organizzatori{ph1} · {ph2}Metadati sfida e" " flag{ph3} · {ph4} Note di prova REA{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Provalo tu stesso" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8633,13 +8641,13 @@ msgstr "" "il prompt sopra per indagare con il proprio agente o eseguire lo script " "incluso." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminale * risolvere ed eseguire" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8651,7 +8659,7 @@ msgstr "" "Risolvere i bisogni di Python e {ph0}. L'esecuzione dell'eseguibile " "originale richiede Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Configura REA con il tuo agente di codifica" @@ -8672,28 +8680,28 @@ msgstr "" "DownUnderCTF. Trova le funzioni di controllo, estrai le maschere e confronta" " un flag recuperato con il programma originale." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Caso di studio CTF flag-checker" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Copia CTF esempio prompt" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "" "Equazione maschera CTF; scorrere orizzontalmente su schermi più piccoli" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8704,42 +8712,42 @@ msgstr "" "14. Solo quella cella contribuisce alla somma. Il suo codice di carattere " "richiesto è 55, il che significa che il carattere è 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Segui il controllo CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Copia CTF assembly" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Copia controllo CTF leggibile" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Copia estratto del risolutore CTF" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Copia recuperato bandiera" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Copia i comandi del risolutore CTF" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -8748,25 +8756,25 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Casa{ph1} / {ph2}Vetrina{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Caso di studio * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Ricostruzione DX-Ball {ph0}dal suo eseguibile." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8775,14 +8783,14 @@ msgstr "" "L'obiettivo è una versione C mantenibile del gioco Windows del 1996. REA " "aiuta l'agente a ispezionare l'originale, una funzione alla volta." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8794,14 +8802,14 @@ msgstr "" "i chiamanti e le letture dei dati; il progetto di ricostruzione implementa e" " verifica il risultato. {ph0}Apri figura{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "In questo caso di studio" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8809,7 +8817,7 @@ msgstr "{ph0}Progetto{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8817,7 +8825,7 @@ msgstr "{ph0}Suono pan{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8825,23 +8833,23 @@ msgstr "{ph0}Controllo del risultato{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Continua il lavoro{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "funzioni C mantenute" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "confronto con il codice originale" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "funzioni con byte compilati corrispondenti" @@ -8852,7 +8860,7 @@ msgstr "funzioni con byte compilati corrispondenti" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8862,12 +8870,12 @@ msgstr "" "Checkpoint del progetto: 7 ottobre 2026. {ph0}Progress ledger{ph1} · " "{ph2}Copertura di prova{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Il progetto finora" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8882,12 +8890,12 @@ msgstr "" "gioco giocabile continua con la fisica della palla e della pagaia, la " "gestione dei potenziamenti e l'integrazione con Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Trovare il calcolo della posizione del suono sinistra/destra" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8907,17 +8915,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Copia" @@ -8928,7 +8936,7 @@ msgstr "Copia" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8939,7 +8947,7 @@ msgstr "" "posizionamento del suono stereo. Spiega il calcolo e mostra il " "codice.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8950,7 +8958,7 @@ msgstr "" "disponibile. L'indagine di seguito mostra le query REA e le prove dietro la " "risposta." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8965,7 +8973,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8979,12 +8987,12 @@ msgstr "" "input dello stack e operazioni in virgola mobile. Questa discrepanza ha dato" " all'agente un motivo concreto per continuare a indagare." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "La prima vista decompilatore" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8994,18 +9002,18 @@ msgstr "" "riportate di seguito rivela l'input e il calcolo che alimenta quella " "chiamata." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Tre domande risposte attraverso REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Recuperare l'input mancante" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9015,14 +9023,14 @@ msgstr "" "Il risultato della funzione include istruzioni insieme a pseudocodice e " "chiamanti. Qui, {ph0} espone l'input intero mancante dalla vista decompiler." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Seguire il chiamante per capire l'input" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9033,12 +9041,12 @@ msgstr "" "precedenti scala {ph0} con 30; l'aggiunta di 20 dà la coordinata dello " "schermo del mattone, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Leggere i valori dietro gli indirizzi di memoria" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9047,12 +9055,12 @@ msgstr "" "I byte restituiti stabiliscono le due costanti aritmetiche e la scala pan " "iniziale. L'agente ora ha i valori necessari per l'espressione C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Dai risultati di REA a C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9063,7 +9071,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9071,7 +9079,7 @@ msgstr "{ph0}01{ph1} Input" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9079,7 +9087,7 @@ msgstr "{ph0}02{ph1} Moltiplicare" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9087,7 +9095,7 @@ msgstr "{ph0}03{ph1} Sottrarre" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9095,18 +9103,18 @@ msgstr "{ph0}04{ph1} Scala" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Restituire" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Originale x86 * estratto" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Ricostruito C" @@ -9116,7 +9124,7 @@ msgstr "Ricostruito C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9136,7 +9144,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9153,7 +9161,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9171,7 +9179,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9188,7 +9196,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9200,7 +9208,7 @@ msgstr "" " {ph3}, identificato nei risultati del callee di REA. Il C lancia il " "risultato a {ph4}; originale-x86 confronti controllare il valore restituito." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9211,23 +9219,23 @@ msgstr "" "ritorno. L'elenco completo di seguito include anche i negozi intermedi e " "l'impostazione e la pulizia delle funzioni." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Assemblea completa e prove a sostegno" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA risultato * 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Cosa fornisce il chiamante" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9237,54 +9245,54 @@ msgstr "" "La funzione brick-hit a {ph0} ridimensiona la sua coordinata tile di 30, " "aggiunge 20, quindi la spinge prima della chiamata:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Ciò che i dati leggono stabiliscono" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA byte legge, decodificato come little-endian raddoppia" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Indirizzo" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Valore" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Usato per" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Prima moltiplicazione" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Sottrazione" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} inizialmente" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Scala pan memorizzata" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9300,7 +9308,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9310,12 +9318,12 @@ msgstr "" "{ph0}Fonte mantenuta{ph1} · {ph2}Note di indagine e riferimenti alle " "prove{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Controllo della funzione recuperata" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9325,12 +9333,12 @@ msgstr "" "corrispondono all'originale e i suoi byte compilati corrispondono " "all'eseguibile." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 casi di comportamento" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9341,12 +9349,12 @@ msgstr "" "ritorno con il C mantenuto.Coprono ogni posizione intera da 0 a 640 a cinque" " scale pan: 0, 0.5, 1, 20 e -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 byte corrispondenti" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9357,7 +9365,7 @@ msgstr "" "del compilatore corrisponde alla funzione completa dopo aver applicato le " "rilocazioni riviste e controllato le costanti di riferimento." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9372,18 +9380,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Leggi i dettagli di riproduzione del compilatore{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Continua l'indagine" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9395,7 +9403,7 @@ msgstr "" "pertinenti, recuperare il loro stato e le dipendenze, quindi confrontare " "l'implementazione con l'originale." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9405,7 +9413,7 @@ msgstr "" "di installazione del progetto DX-Ball e fornire il relativo target originale" " corrispondente. Allora corri:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "Nel checkout DX-Ball" @@ -9414,7 +9422,7 @@ msgstr "Nel checkout DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9428,7 +9436,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9444,7 +9452,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9468,7 +9476,7 @@ msgstr "" "Seguire una ricostruzione DX-Ball dall'analisi binaria attraverso REA a C " "mantenuto, test originali-x86 e corrispondenti byte di funzioni compilate." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9476,7 +9484,7 @@ msgstr "" "DX-Ball sound-pan investigation; scorri orizzontalmente su schermi più " "piccoli" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9492,70 +9500,70 @@ msgstr "" "dall'originale x86 in 3.205 casi e dal replay del compilatore VC4.0 che " "corrisponde a 63 byte." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball ricostruzione caso di studio" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Copia esempio prompt" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Seguire il calcolo di sinistra / destra posizione del suono" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Copia estratto di assemblaggio originale" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Copia suono-funzione pan" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Copia suono completo-pan assembly" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Copia il comando di analisi DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Vai al contenuto" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Casa{ph1} / Vetrina" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "Studi di casi REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9564,17 +9572,17 @@ msgstr "" "Android, giochi, Electron e una sfida CTF, con codice, figure e risultati " "controllati." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * Analisi APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Come un autenticatore genera un codice di accesso" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9585,22 +9593,22 @@ msgstr "" "Traccia i metodi di generazione con REA, quindi sposta un orologio demo per " "vedere perché il codice cambia ogni 30 secondi." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Leggi il case study di Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Analisi di programmi a codice macchina" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Risolvere un CTF flag checker" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9611,22 +9619,22 @@ msgstr "" " controllo, trasforma maschere e somme in equazioni, quindi verifica il flag" " risolto con il programma originale." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Leggi il caso di studio CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Nativo * Ricostruzione" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball ' s calcolo di sinistra / destra posizione del suono" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9638,22 +9646,22 @@ msgstr "" "costanti numeriche portano a una piccola funzione C, verificata rispetto al " "comportamento originale e a tutti i 63 byte compilati." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Leggi il caso di studio DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Funzione di tracciamento" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Come Notion copia testo e HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9665,22 +9673,22 @@ msgstr "" "come un piccolo marcatore HTML mantiene i dati dei blocchi ricchi collegati " "a una copia." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Leggi il caso di studio Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * Ricostruzione" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Come TH04 mira un anello di proiettili" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9691,17 +9699,17 @@ msgstr "" " operazioni di moltiplicazione, divisione e coordinamento a C++ leggibile, " "quindi guarda come producono un anello rivolto al giocatore." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Leggi il caso di studio TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Guide passo-passo" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9710,7 +9718,7 @@ msgstr "" "Le guide seguono un calcolo nativo, un'esportazione Electron e una richiesta" " del browser. Ognuno inizia con un prompt e un obiettivo concreto." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Leggi le guide" @@ -9729,12 +9737,12 @@ msgstr "" "Segui le indagini REA attraverso codice, figure e demo: un autenticatore " "Android, DX-Ball , Notion , TH04 e un correttore di flag DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -9743,25 +9751,25 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Casa{ph1} / {ph2}Vetrina{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Caso di studio * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Come copie Notion{ph0}testo e HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9771,12 +9779,12 @@ msgstr "" "attraverso il precarico e il processo principale, allo scrittore degli " "appunti di Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Desktop 7.6.1 · JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Il ponte all'interno del pacchetto desktop Notion" @@ -9788,7 +9796,7 @@ msgstr "Il ponte all'interno del pacchetto desktop Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9805,7 +9813,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9822,7 +9830,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9839,7 +9847,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9850,13 +9858,13 @@ msgstr "" "testo e l'HTML forniti.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Un canale unisce i due lati: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9866,14 +9874,14 @@ msgstr "" " e principale. La risoluzione dei wrapper rivela le chiamate Electron dietro" " quei nomi." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "In questo caso di studio" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9881,7 +9889,7 @@ msgstr "{ph0}Segui il ponte degli appunti{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9889,19 +9897,19 @@ msgstr "{ph0}Mantenere la struttura di un blocco{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Altri esempi e fonti{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Dove va l'operazione di copia?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9921,17 +9929,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Copia" @@ -9942,7 +9950,7 @@ msgstr "Copia" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9952,7 +9960,7 @@ msgstr "" "{ph0}›{ph1}{ph2}Utilizzare REA per tracciare come Notion copia testo e HTML " "negli appunti di sistema. Mostra il codice ad ogni passaggio.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9961,12 +9969,12 @@ msgstr "" "Un prompt di esempio con il pacchetto di applicazioni locali di Notion " "disponibile per l'agente di codifica." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA trova dove iniziare a leggere" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9977,13 +9985,13 @@ msgstr "" "e la chiamata che invia una richiesta IPC. Entrambi i risultati sono dotati " "di intervalli di origine nel pacchetto minificato:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA risultati → due posti da aprire" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9997,7 +10005,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10011,12 +10019,12 @@ msgstr "" "dà all'agente qualcosa di preciso da cercare nel pacchetto principale. I " "quattro estratti qui sotto mostrano il percorso che collega." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Quattro brevi pezzi di codice" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -10025,13 +10033,13 @@ msgstr "" "Semplificato dal pacchetto JavaScript, con nomi di variabili leggibili. I " "membri non correlati sono omessi." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Inizia dall'API esposta alla pagina" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10041,13 +10049,13 @@ msgstr "" "Questo membro fornisce il nome del canale. L'attuazione di {ph0} ci dice " "come la richiesta lascia il processo della pagina." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Risolvere il wrapper del precarico" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10058,14 +10066,14 @@ msgstr "" "risposta di Electron. Ora possiamo cercare {ph0} dal lato del processo " "principale." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Controlla come è registrato il ricevitore" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10075,12 +10083,12 @@ msgstr "" "Il processo principale utilizza un altro wrapper. Sua {ph0} metodo registra " "un {ph1} ricevitore per quel canale." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Trova la scrittura e il suo controllo mittente" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10091,13 +10099,13 @@ msgstr "" "passa i dati forniti all'API degli appunti di Electron. Il canale e i due " "wrapper risolti collegano il metodo esposto a questa chiamata." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "In che modo un blocco copiato mantiene la sua struttura?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10107,27 +10115,27 @@ msgstr "" "L'editor web di Notion invia testo e HTML attraverso {ph0}. Mantiene i dati " "del blocco localmente e inserisce un ID nell'HTML copiato per collegarli." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Collegamenti HTML ai dati di blocco salvati" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Leggi l'ID HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Trova lo stesso ID locale" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Ripristinare i dati del blocco Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10137,7 +10145,7 @@ msgstr "" " blocco quando gli ID corrispondono; una voce obsoleta restituisce solo " "testo e HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10146,24 +10154,24 @@ msgstr "" "In incolla, Notion cerca l'ID HTML e lo controlla rispetto alla copia " "salvata. Gli ID corrispondenti ripristinano i dati del blocco." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Formato appunti registrato da risorse Web memorizzate nella cache il 13 " "luglio 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Altri esempi e fonti" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Un altro esempio: tabelle Markdown" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10172,12 +10180,12 @@ msgstr "" "Notion analizza Markdown in dati di blocco. Questo esempio mostra come una " "tabella diventa intestazione e righe di dati." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Una tabella attraverso il parser Markdown di Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10186,13 +10194,13 @@ msgstr "" "Uscita registrata da un parser Markdown estratto. La tabella diventa righe e" " celle." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Un altro percorso: la connessione SQLite offline" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10206,7 +10214,7 @@ msgstr "" "l'altra a un processo di utilità SQLite. I successivi lotti di istruzione e " "i risultati viaggiano su quella porta." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10216,7 +10224,7 @@ msgstr "" "database e perché tracciare solo la richiesta IPC iniziale manca la " "conversazione successiva." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Fonti e come leggere gli estratti" @@ -10224,7 +10232,7 @@ msgstr "Fonti e come leggere gli estratti" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10242,7 +10250,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10258,7 +10266,7 @@ msgstr "" "eseguito moduli estratti e piccoli cablaggi; i loro output descrivono quelle" " sonde piuttosto che una sessione di interfaccia utente desktop catturata." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10273,7 +10281,7 @@ msgstr "" "pacchetto." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10291,7 +10299,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10305,7 +10313,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10331,52 +10339,52 @@ msgstr "" "wrapper IPC e il processo principale, con brevi estratti di codice e uno " "sguardo al suo ricco formato di appunti." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Studio di caso Notion Electron" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Copia il prompt di analisi Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Copia estratto di precarico Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Copia Notion invoke wrapper estratto" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Copia estratto del wrapper del gestore Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Copia estratto del ricevitore degli appunti Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Ripristino dei dati degli appunti ricchi su incolla" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Torna in alto" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Vai al contenuto" @@ -10385,25 +10393,25 @@ msgstr "Vai al contenuto" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Casa{ph1} / {ph2}Vetrina{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Caso di studio · Touhou 4: Lotus Land Story" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Ricostruzione di TH04{ph0}modelli di proiettile." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10413,17 +10421,17 @@ msgstr "" "REA per ispezionare la funzione DOS originale, quindi seguire le sue " "istruzioni in C++leggibile." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * DOS a 16 bit * C++ e assemblaggio" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Visualizza la ricostruzione TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Dalle istruzioni originali alla fonte controllata" @@ -10434,7 +10442,7 @@ msgstr "Dalle istruzioni originali alla fonte controllata" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10450,7 +10458,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10468,7 +10476,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10484,7 +10492,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10496,7 +10504,7 @@ msgstr "" " controlli del compilatore registrati coprono il codice di generazione " "bullet che contiene questo helper.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10505,14 +10513,14 @@ msgstr "" "REA restituisce il codice originale e le sue prove di analisi. Il progetto " "TH04 fornisce i controlli di origine e compilatore mantenuti." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "In questo caso di studio" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10520,7 +10528,7 @@ msgstr "{ph0}Il bullet ring{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10528,7 +10536,7 @@ msgstr "{ph0}Cosa restituisce REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10536,7 +10544,7 @@ msgstr "{ph0}Montaggio in C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10544,18 +10552,18 @@ msgstr "{ph0}Verifica della fonte{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Il progetto completo{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Come un anello mira al giocatore" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10574,16 +10582,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Il tuo agente di codifica" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Copia" @@ -10594,7 +10602,7 @@ msgstr "Copia" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10604,7 +10612,7 @@ msgstr "" "{ph0}›{ph1}{ph2}Usa REA per scoprire come TH04 crea un anello di proiettili " "e lo mira al giocatore. Spiega il calcolo e mostra il codice.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10614,7 +10622,7 @@ msgstr "" "ricostruzione disponibili localmente." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10628,7 +10636,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10639,12 +10647,12 @@ msgstr "" "16, la direzione del giocatore 40 e la rotazione del modello 0. {ph0}Apri " "figura{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Il modello di cottura nella fonte recuperata" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Elly's ring attack * fonte estratto" @@ -10653,7 +10661,7 @@ msgstr "Elly's ring attack * fonte estratto" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10663,13 +10671,13 @@ msgstr "" "Queste linee selezionano il modello prima della difficoltà e della messa a " "punto delle prestazioni. {ph0}Leggi la fonte dell'attacco{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Cosa restituisce REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10681,12 +10689,12 @@ msgstr "" "proiettile. REA restituisce le sue istruzioni, pseudocodice e riferimenti. " "Tre parti di questo risultato spiegano il modello." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Controllare l'immagine DOS prima di leggere il suo codice" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10696,7 +10704,7 @@ msgstr "" "all'eseguibile fornito. Il percorso sopra è abbreviato per la " "visualizzazione." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Leggi l'anello moltiplica e dividi" @@ -10704,7 +10712,7 @@ msgstr "Leggi l'anello moltiplica e dividi" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10716,12 +10724,12 @@ msgstr "" "quindi la divisione utilizza il conteggio letto da {ph1}. I nomi di origine " "mantenuti quel campo {ph2}. La sequenza completa appare sotto." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Trova dove il modello gira verso il giocatore" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10735,12 +10743,12 @@ msgstr "" "REA consente all'agente di controllare le operazioni originali dietro di " "loro." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Dall'assembly al C++leggibile" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10753,7 +10761,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10761,7 +10769,7 @@ msgstr "{ph0}01{ph1} Indice" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10769,7 +10777,7 @@ msgstr "{ph0}02{ph1} Spazio" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10777,7 +10785,7 @@ msgstr "{ph0}03{ph1} Obiettivo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10785,18 +10793,18 @@ msgstr "{ph0}04{ph1} Ruotare" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Memorizzare" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * istruzioni originali a 16 bit" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "C++ leggibile * riepilogo dell'anello mirato" @@ -10804,7 +10812,7 @@ msgstr "C++ leggibile * riepilogo dell'anello mirato" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10818,7 +10826,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10834,7 +10842,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10850,7 +10858,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10865,7 +10873,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10879,7 +10887,7 @@ msgstr "" " cast di byte senza segno. La sorgente circostante converte anche questo " "angolo e velocità in velocità." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10891,7 +10899,7 @@ msgstr "" " controlli del compilatore riportati di seguito si applicano all'origine " "mantenuta nel progetto collegato." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Leggi l'anello mantenuto e la fonte aim" @@ -10908,7 +10916,7 @@ msgstr "Leggi l'anello mantenuto e la fonte aim" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10918,12 +10926,12 @@ msgstr "" "{ph0}Anello macro{ph1} · {ph2}Sorgente di mira e velocità{ph3} · " "{ph4}Rappresentazione angolare{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Verifica della fonte mantenuta" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10933,12 +10941,12 @@ msgstr "" "bullet, incluso questo helper, con la sua toolchain Turbo C++ 4.0 J " "bloccata." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 byte corrispondenti" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10947,12 +10955,12 @@ msgstr "" "Il codice di generazione bullet compilato corrisponde a una sezione di 2.139" " byte dell'eseguibile originale." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Due build pulite" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10965,66 +10973,66 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "" "Registrato il 3 ottobre 2026. {ph0}Leggi i controlli del compilatore{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Identità target e ambito di analisi" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Obiettivo originale" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156,258 byte, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Helper entry" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} nell ' immagine caricata di REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Offset file originale" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, restituito da {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Ispezione del codice registrato" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 Ottobre 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11035,7 +11043,7 @@ msgstr "" " il trasferimento sovrapposto." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11051,7 +11059,7 @@ msgstr "" "riportati." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11068,7 +11076,7 @@ msgstr "" "bloccata dal suo repository manifest, con la provenienza indipendente di " "pristine-dump ancora aperta." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11079,12 +11087,12 @@ msgstr "" "tempi e il comportamento hardware PC-98 hanno controlli di runtime separati " "nel progetto di ricostruzione." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "La ricostruzione completa TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11097,7 +11105,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11109,7 +11117,7 @@ msgstr "{ph0}Esplora il repository TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11125,7 +11133,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11141,7 +11149,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11167,22 +11175,22 @@ msgstr "" "l'assemblea e recuperato C++ per vedere come un anello di proiettili è " "distanziato e rivolto al giocatore." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "In questa pagina" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "Caso di studio TH04 bullet-pattern" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Copia il prompt di esempio di TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11190,7 +11198,7 @@ msgstr "" "TH04 anelli di proiettile fissi e mirati; scorrere orizzontalmente su " "schermi più piccoli" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11204,27 +11212,27 @@ msgstr "" "giocatore. Entrambi mantengono una spaziatura di 16 unità angolari o 22,5 " "gradi." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Copia TH04 modello di cottura" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Seguire il calcolo dell'anello di puntamento TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Copia estratto dell'assemblea TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Copia leggibile mirato-anello di calcolo" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Torna in alto" @@ -11334,7 +11342,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Velocità fissa: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11343,7 +11351,7 @@ msgstr "" "Rigiocato la regola recuperata. Tutti e quattro i valori corrispondono al " "controllo del gioco originale controllato quando arrotondati a tre decimali." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11711,591 +11719,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Stessa spaziatura: 256 ÷ 16 = 16 unità angolari = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Casi pratici" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Inizia" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Guide" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Codice sorgente" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Licenza MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Unisciti alla community" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Seguici su X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * sorgente script selezionata" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Codice sorgente" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Uscita formatter prevista" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Istruzione" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Chiamante" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Costante" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Funzione C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Pulsante" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API Precarico" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "File CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Il tuo click" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Richiesta acquisita" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Esporta script" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA risultato * riepilogo.estratto ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "Estratto di istruzioni REA * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA chiamante estratto * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "Risultati byte REA * interpretati come doppi little-endian" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Recuperato C * estratto" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Guarda come funziona REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Vetrina →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Impostazioni selezionate dallo script ispezionato" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Riepilogo leggibile del gestore %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * istruzioni originali selezionate" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "ID operatore * Fonte di Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Segui @reatools su X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agente → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → agente * risultati selezionati" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → agente * metodi e chiamanti" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * Java decompilato selezionato" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Riepilogo leggibile * interpretazione dell'agente" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, corpo completo" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Scarica Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Scarica Android analysis provider" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agente → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → agente * risultati selezionati" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → agente * istruzioni selezionate" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agente → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → agente * settima voce" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Eseguibile originale * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Scarica la sfida originale" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Scarica risolutore" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "Risultato REA * estratto di pseudocodice" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agente → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → agente * estratto di istruzioni" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → agente * estratto del chiamante" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agente → REA * due {ph0} richiesta" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Risultati byte REA * decodificati come doppi" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Inizia con il tuo obiettivo" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Generazione di codice" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Regola recuperata" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Orologio regolabile" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Binario" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Controllo del codice" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Equazione" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Esatto!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Eseguibile" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Risultati REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Recuperato C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Convalida" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "App pacchettizzata" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "API esposte" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Wrapper IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Appunti" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Codice DOS originale" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Istruzioni REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Calcolo dell'angolo" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Anello di proiettile" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "API pagina esposta" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Renderer Chiamata IPC" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Inviato agli appunti di sistema" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Salvato localmente da Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Ingresso markdown" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Uscita parser strutturata * estratto" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analizza la tua app" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agente → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → agente * campi selezionati" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agente → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → agente * estratto di istruzioni" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Stesso risultato di funzione * estratto aim" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Corrispondente mantenuto C++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Macro anello * Ramo TH04, estratto" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Angolo e velocità * fonte estratto" @@ -12329,7 +12345,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12346,7 +12362,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12367,7 +12383,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12388,7 +12404,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12407,7 +12423,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12426,7 +12442,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12437,14 +12453,14 @@ msgstr "" "per me.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Ricostruzione · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12455,7 +12471,7 @@ msgstr "" " codifica e rivedi le modifiche proposte." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12464,7 +12480,7 @@ msgstr "Un esempio fornito · {ph0} e npm * Il tuo agente di codifica" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12483,7 +12499,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12499,7 +12515,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12518,7 +12534,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12529,7 +12545,7 @@ msgstr "" " {ph7} e scrive il file.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12544,7 +12560,7 @@ msgstr "{ph0} * linee 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12557,7 +12573,7 @@ msgstr "" " previsione e l'output effettivo.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12568,7 +12584,7 @@ msgstr "" "controlla il formattatore direttamente con {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12576,7 +12592,7 @@ msgstr "{ph0} · CSV formatter" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12586,7 +12602,7 @@ msgstr "" "con {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12594,7 +12610,7 @@ msgstr "Non ho {ph0}, o non sicuro?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12607,7 +12623,7 @@ msgstr "" "{ph1} 24 LT:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12621,7 +12637,7 @@ msgstr "{ph0} * esempio fonte estratto" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12632,9 +12648,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12642,7 +12658,7 @@ msgstr "{ph0} * esempio sorgente" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12657,7 +12673,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12670,7 +12686,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12684,7 +12700,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12695,7 +12711,7 @@ msgstr "" " dà 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12704,7 +12720,7 @@ msgstr "REA * caricato {ph0} * linee selezionate" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12722,7 +12738,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12741,7 +12757,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12754,28 +12770,28 @@ msgstr "" "demo in cui posso cambiare l’ora.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * Membro API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * IPC helper" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "principale/{ph0} * handler helper" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12785,12 +12801,1434 @@ msgstr "principale/{ph0} * ricevitore appunti" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Inizia {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Passa alla modalità chiara" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Passa alla modalità scura" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Per esaminare i corpi delle richieste e delle risposte HTTP, usa " +"{ph0}Fiddler Everywhere: acquisizioni SAZ, MCP e skill pubbliche{ph1}. " +"Esporta SAZ o HAR 1.2 per ottenere Evidence delle acquisizioni in REA " +"offline, oppure collega il server MCP di Everywhere per esaminare il " +"traffico acquisito con il tuo agente." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Modelli specializzati{ph0}Saggio" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Il reverse engineering ha bisogno di un modello più grande?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Cosa suggerisce la ricostruzione di Touhou sui modelli generali, quelli " +"specializzati e l’apprendimento dal feedback del compilatore." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Da N0zoM1z0 · 13 ottobre 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Vai al contenuto" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Home{ph1} / {ph2}Blog{ph3} / Modelli e reverse engineering" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Saggio" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Il reverse engineering necessita di un modello più grande?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Da N0zoM1z0 · 13 ottobre 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Punti chiave" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}La capacità del modello influisce sulle ipotesi che un agente AI può " +"proporre.{ph1} Le sessioni successive hanno risolto problemi che il lavoro " +"precedente aveva lasciato irrisolti." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Un compilatore familiare offre modelli concreti da apprendere per un " +"modello specializzato.{ph1} Alcune corrispondenze esatte del codice macchina" +" dipendono da modelli di codice sorgente specifici e riutilizzabili." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Includi la conoscenza del repository in un confronto equo.{ph1} Un " +"modello più piccolo con un buon recupero della conoscenza potrebbe già avere" +" informazioni sufficienti per fare progressi." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Addestra il modello per scegliere il prossimo esperimento utile e " +"testare il suo strumento di verifica.{ph1} Il feedback è utile solo nella " +"misura in cui lo strumento verifica le cose giuste." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Valuta i risultati verificati della ricostruzione insieme a tempi e " +"costi.{ph1} Questo è ciò che voglio misurare per il flusso di lavoro " +"completo dell'agente AI." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "In questo articolo" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Che cosa hanno cambiato i modelli più capaci{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Perché specializzarsi?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Dove dovrebbe essere archiviata questa esperienza?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Imparare il prossimo esperimento utile{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Reverse engineering e apprendimento per rinforzo{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Quando il controllo di verifica è sbagliato{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Un confronto che vale la pena fare{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Che tipo di agente AI suggerisce questo?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Che cosa hanno cambiato i modelli più capaci" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Dall'agosto 2026, ho esplorato quanto reverse engineering può eseguire un " +"agente con l'accesso a un programma e un modo per verificarne il lavoro. La " +"maggior parte della mia esperienza deriva dalla ricostruzione di giochi, in " +"particolare Touhou. Man mano che ho cambiato modello, i repository hanno " +"tenuto traccia di ciò che è riuscita a recuperare ciascuna sessione." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Gran parte di questo lavoro mira alla ricostruzione esatta: compiliamo il " +"sorgente mantenuto in una toolchain storica con versioni fisse e " +"controlliamo se riproduce la funzione di destinazione. Quando un modello " +"successivo riesce dove il lavoro precedente si era bloccato, le modifiche " +"alla fonte mostrano cosa ha reso possibile quel progresso." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Le variabili temporanee necessitavano di vite sovrapposte" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Gran parte della logica della funzione di attacco TH09 era già stata " +"ricostruita, ma il compilatore memorizzava ancora i risultati temporanei in " +"modo diverso dall'originale. Il problema rimanente era quanto tempo " +"occorreva a quei risultati per rimanere in vita e quando la loro " +"conservazione poteva essere riutilizzata." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Un {ph0}GPT-6-Sol record di sessione{ph1} ha segnalato questa mancata " +"corrispondenza dopo aver testato diverse disposizioni ordinarie del codice " +"sorgente. Quando {ph2}GPT-6.1-Sol ha esaminato nuovamente il problema{ph3}, " +"ha proposto un'ipotesi utile sulla durata di queste variabili temporanee." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"La funzione ha prodotto risultati temporanei e li ha copiati in posizioni di" +" animazione. In C++, un risultato temporaneo rimane attivo finché " +"l'espressione che lo utilizza non termina. Raggruppare le operazioni reali " +"in un'unica espressione ha mantenuto vivi insieme i risultati, quindi il " +"compilatore non poteva più riutilizzare la stessa memoria per tutti loro." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Un risultato ha ancora spazio di archiviazione condiviso con un valore " +"utilizzato successivamente per i controlli di collisione. Dare a quel valore" +" la propria durata ha risolto la rimanente sovrapposizione. Dopo diversi " +"esperimenti mirati, {ph0}una ricompilazione pulita dal sorgente ha " +"confermato che l'intera funzione corrispondeva a{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Sono interessato a come la scoperta e i test si siano supportati a vicenda. " +"L’ipotesi sulla durata temporanea degli oggetti ha dato all’agente AI una " +"nuova direzione. Il feedback del compilatore ha aiutato a perfezionare " +"quell'ipotesi in una disposizione del codice sorgente che corrispondesse." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Un diverso grafico del flusso di controllo" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Una seconda funzione TH09 mostra perché questa nuova direzione può essere " +"importante. In questo caso, l’ostacolo era il modo in cui diversi rami " +"condividevano il loro lavoro finale. Il lavoro precedente di " +"{ph0}GPT-6.1-Sol{ph1} faceva corrispondere parti della funzione, ma i rami " +"si univano ancora in modo diverso dall'originale." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra ha cambiato il grafico del flusso di controllo " +"circostante{ph1}. I percorsi principali conducono ora ad un aggiornamento " +"finale condiviso e al ritorno. In quella struttura sorgente, il compilatore " +"ha combinato i rami nello stesso modo dell'originale. La funzione completa " +"corrispondeva e un {ph2}controllo di ricostruzione separato lo ha " +"confermato{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}La modifica della rappresentazione ha aperto uno spazio di ricerca più " +"produttivo.{ph1} Entrambi i casi mi danno un motivo per prendere sul serio " +"le capacità generali del modello: un agente può continuare a provare " +"variazioni locali per molto tempo prima di trovare un modo migliore per " +"esprimere il lavoro circostante." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Le sessioni successive hanno anche ereditato il codice precedente e i " +"tentativi falliti già documentati. Questo lavoro accumulato faceva parte del" +" loro vantaggio. La cronologia permette di esaminare le scoperte e le " +"verifiche; un confronto controllato aiuterebbe a separare il contributo del " +"modello da quello dell’esperienza ereditata." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Questo è ciò che rende la domanda interessante per me. Alcuni progressi sono" +" arrivati ​​dalla ricerca di una nuova rappresentanza. Gran parte del lavoro" +" rimanente prevedeva il test di diverse disposizioni del codice sorgente " +"rispetto a un compilatore familiare. Quanto di tutto ciò richiede un’ampia " +"capacità di ragionamento? Quanto potrebbe imparare un modello lavorando " +"ripetutamente con quel compilatore e quel codice?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Perché un modello di IA specializzato potrebbe funzionare bene?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou ci dà una ragione concreta per aspettarci che quell'esperienza sia " +"d'aiuto. Gran parte del codice del gioco proviene dallo stesso autore, ZUN, " +"quindi le abitudini ricorrenti sono un presupposto di partenza ragionevole. " +"I repository lo confermano con esempi utili: cicli correlati e disposizioni " +"di supporto hanno fornito ipotesi attraverso i giochi." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Questi modelli di origine diventano più specifici quando includiamo il " +"compilatore. In una particolare versione e insieme di opzioni, piccole " +"modifiche all'origine possono produrre differenze ripetibili nel codice " +"macchina. Alcune di queste differenze sono sorprendentemente oscure." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"In TH095, ad esempio, {ph0}anche il nome di una variabile locale potrebbe " +"influenzare dove VC7.1 l'ha memorizzata{ph1}. Lo spostamento della sua " +"dichiarazione non ha risolto il layout di archiviazione. Tuttavia, una " +"precedente funzione in background aveva rivelato un modello di denominazione" +" che influenzava la scelta del compilatore. Ciò ha suggerito un'ipotesi più " +"promettente per {ph2}ricostruire {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Il riutilizzo di quel modello per la variabile della dimensione del file ha " +"prodotto il layout richiesto senza aggiungere spazio di archiviazione. La " +"funzione completa quindi corrispondeva." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Questo è un dettaglio molto specifico che un modello di intelligenza " +"artificiale generica potrebbe non conoscere quando incontra per la prima " +"volta il problema. Un modello specializzato per questo compilatore potrebbe " +"vedere molti casi simili e apprendere quali variazioni del codice sorgente " +"vale la pena testare per prime." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"L'opportunità è particolarmente chiara nei problemi di abbinamento finale in" +" cui ne comprendiamo già il comportamento. Ci stiamo quindi chiedendo quale " +"disposizione ordinaria del codice sorgente questo compilatore trasforma " +"nelle istruzioni osservate. La specializzazione potrebbe aiutare il modello " +"a proporre tali forme in modo più efficiente, mentre l’obiettivo determina " +"ancora quali ipotesi sopravvivono." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Gli schemi utili devono conservare il loro contesto. TH08 usa una versione " +"di Visual C++ precedente a quella di TH095 e TH09. TH04 usa un altro " +"compilatore dell’epoca DOS. La {ph0}ricostruzione del codice del " +"giocatore{ph1} richiedeva ipotesi diverse sugli schemi del sorgente e sul " +"collegamento del codice in un eseguibile. Lo stesso autore ci dà " +"un’aspettativa iniziale, ma ogni obiettivo indica se è applicabile. Un " +"modello specializzato dovrebbe imparare a distinguere questi contesti." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Dove dovrebbe essere archiviata questa esperienza?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Prima di decidere di insegnare questi modelli attraverso l'addestramento dei" +" modelli, esaminerei la conoscenza che già conserviamo nel repository. Nel " +"{ph0}saggio precedente{ph1} ho scritto che diventa la memoria di lavoro del " +"progetto. Quella memoria include lezioni del compilatore, insieme alla fonte" +" e agli esperimenti falliti che li hanno resi utili." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Recuperando quel record, un agente può iniziare con un risultato noto e " +"verificare come lo abbiamo raggiunto. Può anche evitare alternative che " +"hanno già fallito nello stesso contesto. Il punto di partenza migliora senza" +" modificare i parametri addestrati del modello." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Durante la ricostruzione della funzione di TH09 per la creazione di nemici, " +"una sessione {ph0}GPT-6-Luna-max{ph1} ha preso un'ipotesi dal relativo " +"codice sorgente TH08. Il codice precedente suggeriva come organizzare il " +"ciclo e gestire gli errori al suo interno. Le prove di TH09 hanno fornito i " +"dettagli specifici del gioco. Le ricostruzioni dall'origine hanno confermato" +" che la funzione completa corrispondeva." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"Il modello non conosceva quella stranezza del compilatore\" e \"il " +"modello non poteva usarlo\" sono problemi diversi.{ph1} Il recupero può " +"risolvere il primo, ma trasformare questo fatto in un candidato utile " +"richiede ancora lavoro. E se il codice sorgente candidato fallisce, il " +"modello deve decidere cosa significherà il risultato per il suo prossimo " +"tentativo. Conoscere il modello rilevante è solo l’inizio di quel processo." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Per questo motivo, includerei in ogni confronto un modello di intelligenza " +"artificiale generico più piccolo con un buon recupero. Fornire la stessa " +"libreria di esperienze ci aiuterebbe a identificare ciò che la formazione " +"aggiunge: una migliore generazione di candidati, decisioni migliori dopo il " +"feedback o entrambi." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Imparare il prossimo esperimento utile" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Quelle decisioni dopo il feedback sono ciò che mi piacerebbe di più " +"studiare. Nella ricostruzione agentica, il modello propone una spiegazione e" +" la mette alla prova rispetto al programma. Anche quando il codice sorgente " +"candidato fallisce, il risultato può restringere le possibilità rimanenti e " +"suggerire un prossimo esperimento più utile." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Consideriamo nuovamente l'esempio dei risultati temporanei. La sua fonte " +"finale mostra la soluzione che ha funzionato, ma il percorso verso quella " +"fonte contiene più informazioni. Ciascuno dei seguenti esperimenti ha " +"contribuito a identificare ciò che ancora doveva cambiare." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Esperimento" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Cosa ci ha insegnato il suo risultato" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Prova un modo diverso per copiare i risultati" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Il codice di copia cambia, ma la funzione cambia ancora." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Utilizzare direttamente i valori restituiti" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"La copia segue lo schema originale, ma l'archiviazione temporanea differisce" +" ancora." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Mantieni valide tutte le variabili temporanee contemporaneamente" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Ottengono un'archiviazione separata, ma uno si sovrappone comunque a un " +"valore utilizzato successivamente per i controlli di collisione." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Mantenere separato il valore del controllo collisioni" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Una ricompilazione pulita dalla fonte conferma la corrispondenza completa." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Esperimenti selezionati dalla ricostruzione della funzione di attacco sopra," +" raggruppati in base a ciò che ci hanno insegnato." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Un registro dell'addestramento che mantenga questa sequenza può insegnare " +"più della sola fonte finale. Collega ogni modifica proposta a un risultato " +"osservato e alla decisione successiva. Anche mantenere le variazioni " +"inefficaci è importante: dicono a un agente successivo quali ipotesi sono " +"già state testate in quel contesto." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Vorrei che il modello imparasse come utilizzare il feedback.{ph1} Un " +"risultato neutro è un motivo per riconsiderare la variazione; una mancata " +"corrispondenza modificata può indicare un'altra causa. Quando le modifiche " +"locali smettono di essere informative, l'agente dovrebbe essere in grado di " +"rivisitare la rappresentazione originale o ispezionare nuovamente le prove." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Imparare a fare queste scelte richiede autonomia. A volte il passaggio " +"successivo utile è ispezionare un altro chiamante anziché compilare un'altra" +" modifica. Una rigida sequenza di riscritture richieste eliminerebbe quella " +"scelta, insieme a parte del comportamento che vogliamo che il modello " +"impari." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "" +"Perché il reverse engineering è interessante per l'apprendimento per " +"rinforzo" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"La ricostruzione limitata ci offre un ambiente pratico per studiare queste " +"scelte. Una volta fissate le versioni di destinazione e del compilatore, " +"molti esperimenti di origine producono un feedback rapido e ripetibile. " +"L'agente può compilare un candidato, ispezionare la mancata corrispondenza e" +" utilizzare tale osservazione per scegliere il passaggio successivo." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"L’apprendimento per rinforzo potrebbe addestrare il processo decisionale " +"attraverso il feedback che riceve. Un candidato accettato con una verifica " +"definita ci dà un risultato concreto, mentre la sequenza dei tentativi ci " +"permette di osservare quanto lavoro è stato necessario per raggiungerlo." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Esistono già ricerche a sostegno di questa direzione. " +"{ph0}LLM4Decompile{ph1} studia modelli specializzati per la decompilazione. " +"{ph2}AutoDecompiler{ph3} addestra il perfezionamento multi-turn utilizzando " +"il feedback del compilatore e dell'esecuzione. I loro studi si concentrano " +"sul recupero funzionale. Per questo lavoro, li userei come punto di partenza" +" per il compito correlato di trovare fonti che corrispondano all'output di " +"un compilatore storico." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Per raggiungere un compito così ben definito, tuttavia, potremmo prima dover" +" stabilire quali risorse possiede una funzione o ideare un nuovo modo di " +"osservare il comportamento del programma durante l’esecuzione. In TH08, ad " +"esempio, una {ph0}differenza di collisione riportava al modo in cui il " +"programma originale gestiva i calcoli in virgola mobile{ph1}. Prima che " +"l'agente potesse testare una correzione utile, doveva capire cosa misurare." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Ciò suggerisce un altro ruolo per un modello ampiamente capace: in primo " +"luogo, contribuire a rendere il problema controllabile. Una volta effettuato" +" questo controllo, possiamo indagare fino a che punto può arrivare una " +"politica di ricerca appresa." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Quando il controllo di verifica è sbagliato" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Quando una verifica viene usata per l’addestramento, anche la sua copertura " +"entra nell’ambiente di apprendimento. Chiamo oracle quel riferimento o " +"verificatore. Persino una risposta ripetibile va interpretata in base a ciò " +"che verifica davvero." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 ha mostrato quanto si può nascondere al di fuori di quella copertura. " +"Alcune funzioni ricostruite hanno superato i confronti esatti con costanti " +"in virgola mobile errate. Il comparatore aggiustava gli indirizzi trasferiti" +" prima di controllare le istruzioni, ma controllava i valori dietro quegli " +"indirizzi solo quando erano stati esplicitamente registrati per la verifica." +" Altri riferimenti letterali potrebbero passare senza che i loro valori " +"vengano esaminati." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Per colmare questa lacuna, un {ph0}controllo più ampio{ph1} ha rilevato " +"costanti errate nelle funzioni che avevano già superato la verifica. In un " +"calcolo, il codice sorgente ricostruito aggiungeva {ph2}, mentre l'originale" +" aggiungeva {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Un modello premiato dal vecchio controllo di verifica potrebbe imparare" +" a produrre una ricostruzione errata.{ph1} Non abbiamo addestrato un modello" +" RL utilizzando quel controllo. L'errore che abbiamo osservato riguardava il" +" controllo stesso. Ma se lo usassimo come ricompensa, lo stesso punto cieco " +"diventerebbe parte dell’ambiente di apprendimento." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Un test funzionale può avere un punto cieco simile. {ph0}La ricerca che " +"utilizza il fuzzing differenziale sui decompilatori LLM{ph1} ha rilevato " +"differenze comportamentali al di fuori dei test forniti. Dobbiamo quindi " +"comprendere una prova di superamento in termini dei casi che esercita. Allo " +"stesso modo, la corrispondenza di un'istruzione deve essere intesa in " +"termini di byte e dati che verifica." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Prima di utilizzare uno dei due tipi di controllo di verifica come " +"ricompensa, lo testerei con risultati deliberatamente errati. Vorrei anche " +"mantenere l'accettazione finale separata dal codice sorgente che l'agente AI" +" può modificare. Il modello deve superare la verifica ricostruendo " +"correttamente il programma. Altrimenti, la semplice copia di un array di " +"byte dalla destinazione potrebbe ingannare un ingenuo sistema di punteggio " +"senza recuperare codice sorgente utile." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Migliorare lo studente e migliorare il suo strumento di verifica " +"appartengono allo stesso problema di ricerca.{ph1} Man mano che lo studente " +"migliora nell'ottimizzare il feedback che gli forniamo, anche comprendere " +"quel feedback diventa più importante." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Un confronto che vale la pena fare" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Con questi controlli in atto, inizierei il confronto su una famiglia di " +"attività VC7.1 fissa. Innanzitutto, stabilirei le linee di base per un forte" +" modello di intelligenza artificiale generale e uno più piccolo. L'aggiunta " +"della conoscenza del repository al modello più piccolo mostrerebbe quali " +"cambiamenti nel recupero. Da lì, la specializzazione supervisionata e una " +"versione addestrata con RL ci permetterebbero di esaminare cosa aggiunge la " +"formazione." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Per rendere informativi questi confronti, ciascun modello riceverebbe le " +"stesse prove e strumenti target. Per i confronti specifici della formazione," +" manterrei fisso anche il modello base e le conoscenze disponibili. Prove " +"ripetute aiuterebbero a distinguere una strategia di ricerca affidabile da " +"una soluzione candidata che ha successo per caso." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Separerei quindi due condizioni iniziali: ricostruire una funzione dalle sue" +" istruzioni e chiudere le ultime differenze nel sorgente mantenuto. Un " +"modello di IA specializzato potrebbe essere eccellente per il secondo " +"compito, mentre un modello di IA generico svolge gran parte del lavoro " +"necessario per raggiungerlo. Misurarli separatamente rivelerebbe quella " +"divisione del lavoro." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Entrambi i compiti necessitano di esempi di test esclusi dall'addestramento " +"e dal recupero. I giochi Touhou correlati condividono il codice motore. " +"Escludere un gioco dall'allenamento potrebbe comunque lasciare funzioni " +"quasi identiche nel set di allenamento. Invece, escluderei interi gruppi di " +"codice sorgente correlato e manterrei le loro risposte verificate fuori sia " +"dai dati di addestramento che dalla libreria di recupero." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Per questi esempi, il risultato sarebbe corrispondenze complete e verificate" +" in modo indipendente. Budget uguali per le proposte dei candidati o i " +"tentativi di compilazione aiuterebbero a confrontare la qualità della " +"ricerca. La misurazione del tempo e dei costi totali, inclusa la " +"compilazione, mostrerebbe se tale qualità produce un flusso di lavoro " +"efficiente. I costi di formazione dovrebbero essere misurati separatamente." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Entrambe le misurazioni contano. Una proposta economica può portare a un " +"flusso di lavoro costoso se comporta più compilazioni che non forniscono " +"informazioni utili. Al contrario, un modello più lento può essere più " +"economico se trova prima un esperimento utile. Il confronto dovrebbe " +"includere questi costi." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Il conteggio dei risultati accettati mantiene inoltre in prospettiva i " +"progressi intermedi. Un TH09 {ph0}candidato al replay-save{ph1} sembrava " +"promettente perché la funzione compilata aveva le dimensioni previste, ma un" +" confronto completo ha comunque rilevato differenze sostanziali. I " +"cambiamenti nel modo in cui il compilatore organizza le istruzioni possono " +"anche far sembrare un candidato più vicino al risultato atteso senza " +"risolvere il problema di fondo. Tale diagnostica può guidare il prossimo " +"esperimento, ma convaliderei qualsiasi ricompensa per \"avvicinarsi\" " +"rispetto al controllo completo di accettazione." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Sarei interessato allo schema tra questi risultati. Se un modello di " +"intelligenza artificiale specializzato funziona bene all’interno di una " +"famiglia di compilatori familiare, tale vantaggio sopravvive a un " +"cambiamento nella toolchain? E una volta che entrambi i modelli di " +"intelligenza artificiale hanno un buon recupero, quanto aggiunge ancora " +"l’addestramento? Le risposte ci aiuterebbero a decidere dove ciascun tipo di" +" modello è più utile." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Che tipo di agente AI suggerisce questo?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Se i modelli si rivelano utili in diverse fasi, una soluzione utile potrebbe" +" essere un ampio agente con accesso a un modello di intelligenza artificiale" +" specializzato. Una volta che un'attività diventa una ricerca familiare del " +"compilatore, potrebbe richiedere il modello di intelligenza artificiale " +"specializzato per i candidati. Se i risultati smettono di avere senso, " +"l’agente più ampio potrebbe tornare all’evidenza target o indagare sulla " +"misurazione stessa." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"In questo modo, la specializzazione diventa uno strumento che l’agente può " +"scegliere man mano che l’indagine si sviluppa. L'agente mantiene la libertà " +"di cambiare direzione che ha reso possibili i progressi precedenti." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Ciò deriva naturalmente dal cambiamento industriale che ho descritto nel " +"saggio precedente. Essere in grado di eseguire molti più esperimenti cambia " +"il modo in cui organizziamo il lavoro. Ci dà anche una ragione per chiederci" +" quali decisioni necessitano di un ampio giudizio e quali migliorano " +"attraverso l’esperienza ripetuta con una particolare imbarcazione." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Per ora il modello generale più forte si è guadagnato il suo posto nel mio " +"lavoro risolvendo problemi che avevo lasciato aperti. Sono proprio questi " +"successi a farmi studiare il processo: quanto dipendeva dall’ampiezza delle " +"sue capacità, e quanto potrebbe fare un modello addestrato specificamente " +"per questo tipo di ricostruzione?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}I repository ci offrono un modo per testare la domanda.{ph1} Vorrei " +"utilizzare quel record per creare il confronto e vedere cosa impariamo." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Evidenze e attribuzione del modello" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Gli esempi descrivono i confronti storici a livello di funzione registrati " +"nei commit collegati. I controlli di runtime dell'intero gioco sono " +"traguardi separati. I record di origine e corrispondenza sono stati " +"esaminati il 13 ottobre 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"L'etichetta TH09 {ph0} significa GPT-6-Astra. Il modello associato a {ph1} è" +" cambiato nel tempo, quindi l'etichetta da sola non può identificare il " +"modello utilizzato in una specifica esecuzione. I nomi espliciti dei modelli" +" negli altri commit citati forniscono l'attribuzione registrata. Queste " +"cronologie non includono misurazioni coerenti dei costi o dell'impegno per " +"ogni esecuzione." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 durata degli oggetti temporanei:{ph1} la {ph2}revisione del " +"contesto precedente{ph3} e la {ph4}ricostruzione completa verificata da una " +"ricompilazione pulita dall'origine{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front callback:{ph1} {ph2}aree diagnostiche che non " +"corrispondevano{ph3}, il nuovo grafico del flusso di controllo di " +"{ph4}Astra{ph5} e il relativo {ph6}controllo di ricompilazione " +"accettato{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Conoscenze del compilatore:{ph1} {ph2}TH095 riutilizzo del " +"comportamento del bucket di identificatori{ph3}, {ph4}TH04 codice sorgente " +"del giocatore e ordine dei linker{ph5} e {ph6}Luna ricostruzione completa " +"della funzione di creazione del nemico di TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Controlli e diagnostica:{ph1} {ph2}TH08 audit costante in virgola " +"mobile{ph3}, {ph4}TH08 indagine numerica{ph5} e {ph6}TH09 ricostruzione con " +"salvataggio replay{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"I confronti proposti tra modelli specializzati e la formazione RL sono " +"esperimenti futuri. Le storie dei progetti li motivano. Per questo saggio " +"non è stato valutato alcun modello specializzato addestrato." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Il reverse engineering necessita di un modello più grande? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Cosa mi ha insegnato la ricostruzione Touhou sui modelli generali, sui " +"modelli specialistici e sull'imparare a proporre ipotesi migliori dal " +"feedback del compilatore." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "In questa pagina" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Modelli e saggio di reverse engineering" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Esperimenti di ricostruzione selezionati" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Torna in alto" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"Le {ph0}note dettagliate sulle prove{ph1} includono i confronti registrati e" +" il contesto degli esperimenti." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Di N0zoM1z0 · 13 ottobre 2026 · Bozza da rivedere" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Guida all’installazione" diff --git a/website/locales/ja/messages.po b/website/locales/ja/messages.po index dc0d6e7f6..17d784abd 100644 --- a/website/locales/ja/messages.po +++ b/website/locales/ja/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}ホーム{ph1} /ブログ" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "ブログ。" -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "リバースエンジニアリングに関する考え。" #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "ゲーム再構築{ph0}小論文" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "リバースエンジニアリングにおける産業革命" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -51,34 +51,35 @@ msgid "" msgstr "" "どのようなマニュアル再とTH08を再構築,TH095とTH04は、エージェントについて教えてくれました,プロジェクト間で化合物の検証と知識." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "記事を読む" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "によってN0zoM1z0•10 10月2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -97,6 +98,8 @@ msgid "" msgstr "REAとAIエージェントの実践的な経験に基づいて、リバースエンジニアリングに関する考え。" #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -130,112 +133,117 @@ msgid "" "agent." msgstr "REA—ソフトウェアがどのように動作するかを調べます。 コーディングエージェントとのリバースエンジニアリング。" -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "REA ホーム" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "メインナビゲーション" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "GitHub で REA を見る" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "REA の Discord に参加" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "X で REA をフォロー" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -244,35 +252,35 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}ホーム{ph1} / {ph2}ブログ{ph3} /東方復興" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "エッセイ·東方復興" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "リバースエンジニアリングにおける産業革命。" -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "によってN0zoM1z0•10 10月2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "要点" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -282,7 +290,7 @@ msgstr "{ph0}エージェントに調査の自律性を与えます。{ph1} 明 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -295,7 +303,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -307,7 +315,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -319,7 +327,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -327,65 +335,65 @@ msgid "" "methods are still taking shape. There is plenty left to explore." msgstr "{ph0}私たちはREの産業革命の初期にいます。{ph1} メソッドはまだ形を取っています。 探索することがたくさん残っています。" -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "どのように経験化合物" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}人間の方向性{ph1} *目標と合格基準" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "自律性" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "エージェント" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "実験を選択します。{ph0}仮説を提案する。" -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "検証" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "検証基準" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Aに対するテスト{ph0}具体的な参照。" -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "リポジトリ" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "作業の記憶" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -394,7 +402,7 @@ msgstr "コード、証拠,{ph0}チェックとレッスン。" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -403,40 +411,40 @@ msgstr "ミスマッチ{ph0}{ph1}仮説を修正する{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "より良い{ph0}{ph1}出発点{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "再利用" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}パス{ph1} *結果とその証拠を保持する" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " "fixing the checks when we discover a gap." msgstr "各プロジェクトは、より良い出発点で次のものを残します。 それには、ギャップを発見したときにチェックを修正することが含まれます。" -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "この記事の内容" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -444,7 +452,7 @@ msgstr "{ph0}2026年8月{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -452,7 +460,7 @@ msgstr "{ph0} TH08:続き{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -460,7 +468,7 @@ msgstr "{ph0}二つのアプローチ{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -468,7 +476,7 @@ msgstr "{ph0} TH095:配合{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -476,7 +484,7 @@ msgstr "{ph0} TH04:アーキテクチャ間{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -484,7 +492,7 @@ msgstr "{ph0}正確なものから読みやすいものへ{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -492,18 +500,18 @@ msgstr "{ph0}産業シフト{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}何が可能になるか{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "2026年8月に何が変わったのか" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -515,7 +523,7 @@ msgstr "" "この作業の前に、私は多くの手動リバースエンジニアリングを行っていました。 私は説明があるまで関数を検査し、その説明をプログラムに対してテストします。 " "さらに得ることは、次の機能に自分の時間をもっと費やすことを意味しました。 それはまた、私の頭の中でますます大きな絵を保つことを意味しました。" -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -527,7 +535,7 @@ msgstr "" "それがこの記事の背後にある経験です。 " "このメソッドは他の場所でも役立ちますが、各フィールドは信頼できる参照に対してチェックできるものを確立する必要があります。" -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -539,7 +547,7 @@ msgstr "" "私は、エージェントがプログラムや通常の開発ツールにアクセスすることでどこまで得ることができるかを見たかったのです。 " "東方復興は私に見つけるための実質的なプロジェクトを与えました。" -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -554,7 +562,7 @@ msgstr "" "小さな診断を記述し、その結果を使用して次に何を試すかを決定することができます。 " "自由が違いをもたらしたことをそれに与える:私はプロジェクトの方向性とそのチェックが信頼できるかどうかにもっと注意を払うことができ" -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -564,7 +572,7 @@ msgstr "" "ペースは最初に私の注意を得ました。 それから私は現在のプロジェクトを超えて何が生き残るのだろうかと思い始めました。 " "次のゲームは、私たちが学んだすべてのものから利益を得るでしょうか?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08:人間の仕事の上に構築" @@ -573,7 +581,7 @@ msgstr "TH08:人間の仕事の上に構築" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -585,7 +593,7 @@ msgstr "" "{ph0} TH08 {ph1}、不滅の夜は、の続きとして始まった {ph2} GensokyoClubの再構築{ph3}. " "彼らの公的な情報源は私に実質的な基盤を与えました。 それは、ビルドの知識と私が継続して保存した貢献の歴史が付属していました。" -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -595,7 +603,7 @@ msgstr "" "同年10月場所で初土俵を踏んだ。 私の独立した継続は8月13日に始まりました。 " "8月19日までに、台帳は1,107の特定されたゲーム機能すべてのソースを記録しました。" -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -605,7 +613,7 @@ msgstr "" "Linux再構築ポートは、継続が始まった約十一日後の8月24日にコミットされました。 Web版が続いた。 " "ネイティブLinux64ビットリリースは8月30日に到着しました。" -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -618,7 +626,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -634,12 +642,12 @@ msgstr "" "実行時チェックは、実行されたルートが予想される状態に達するかどうかを確認できます。 " "エージェントは説明を提案し、それをテストします;不一致はそれに調査するために特定の何かを与えます。" -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "間違った定数と完全に一致する" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -649,7 +657,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -660,7 +668,7 @@ msgstr "" "9月には、ダウンストリームスイッチポートから報告されたバグがアイテムの自動収集に戻りました。 再構築されたソースは、プレーヤーのパワーをチェックしました" " {ph0}. 使用される原物 {ph1}、最大電力しきい値。" -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -674,13 +682,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}しかし、関数はすでに正確な比較に合格していました。{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -694,7 +702,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -709,7 +717,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -721,7 +729,7 @@ msgstr "" "ザ- {ph0}2月の修正{ph1} ソースを修正し、参照された定数の実際のバイトを比較チェックしました。 A {ph2}より広い監査{ph3} " "次に、1,548個の浮動小数点定数参照を調べました。 それは5つの受け入れられた関数間で別の12の誤った参照を見つけました。" -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -733,7 +741,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -742,7 +750,7 @@ msgid "" msgstr "" "{ph0}検証リファレンス(oracle)も再構築する必要がありました。{ph1} それを修復することは、ゲームを修復することの一部でした。" -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -758,7 +766,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -773,7 +781,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -781,7 +789,7 @@ msgid "" " for the next batch.{ph1}" msgstr "{ph0}バッチが成功すると、復元されたコードと次のバッチのためのより良い環境の両方が得られました。{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "再建の2つの異なるアイデア" @@ -790,7 +798,7 @@ msgstr "再建の2つの異なるアイデア" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -801,7 +809,7 @@ msgstr "" "GensokyoClubの {ph0}パブリックREADME{ph1} この種の作業との意見の相違を明示的にします。 " "この通知により、さらなる開発が完了するまで非公開で行われることが発表されました。 一つの通路が読みます:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -809,7 +817,7 @@ msgid "" msgstr "" "私たちの仕事から取って、この空間でのグリフター(AIの逆コンパイルとポート)の台頭は、将来の逆コンパイルの努力のための悪いイメージを描きます…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -823,7 +831,7 @@ msgstr "" "彼らは自分の自由な時間を困難な仕事に入れており、その仕事は私の継続を可能にするのに役立ちました。 私はその背後にある努力を尊重します。 " "私が議論したい意見の相違は、復興をどのように進めるべきか、そして貢献をどのように判断すべきかということです。" -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -834,7 +842,7 @@ msgstr "" "私が知っていた手動ワークフローでは、機能の理解を開発し、それを再構築することは、通常、同じ人に落ちました。 " "プロジェクトはその人の専門知識に大きく依存していました。 彼らが働いている間に推論の多くが起こったので、貢献者への信頼は重要でした。" -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -844,7 +852,7 @@ msgstr "" "既存のプロジェクトは、ソースとビルドツールの知識をすでに保持しています。 " "私にとって変わったのは、エージェントがその知識を使って次の調査を単独で追求できるということでした。" -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -857,7 +865,7 @@ msgstr "" "その提案された再建は、関連するチェックを生き残るために持っています。 " "エージェントがほとんどの作業を行ったとしても、他の人がなぜ実装を選んだのかを調べることができるようにしたいと思います。" -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -868,7 +876,7 @@ msgstr "" "これは難しい移行になる可能性があります。 注意深い仕事の年は大いにより速く動く継続のための基礎になるかもしれない。 " "それは信用についての実質の質問を上げる。 また、コントリビューションを受け入れる前にメンテナが知る必要があることも変更されます。" -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -881,7 +889,7 @@ msgstr "" "機械はその技術が必要とされるところで変わる。 誰かがまだプロセスを設計し、その出力が間違っているときに認識する必要があります。 " "さまざまなコミュニティが、その変更のどれだけを実行したいかを選択できます。" -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -904,7 +912,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -915,14 +923,14 @@ msgstr "" "ソース:GensokyoClubの {ph0}READMEのお知らせ{ph1}、2026年10月10日にチェックされ、その " "{ph2}貢献方針{ph3}. 引用は短縮された抜粋です。 TH08の {ph4}クレジットと出所{ph5} 継続境界を記録します。" -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095:経験は配合を開始します" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -935,7 +943,7 @@ msgstr "" "私たちはまだゲームを学ばなければなりませんでした。 " "しかし、私たちはすでに再建を開始する方法とそれを動かし続ける方法についてはるかに多くを知っていました。" -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -946,7 +954,7 @@ msgstr "" "9月7日までに、特定された697のゲーム機能すべてがソースを持っていました。 8年(696年)までには、正確な比較として受け入れられていた。 " "プログラム全体は9月にリンクされています。 Windows i386は、初期化から約10日後の10月に再構築された。" -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -956,7 +964,7 @@ msgstr "" "私はこれが最初のプロジェクトのスピードよりも刺激的だと感じました。 新しいターゲットは、別のゲームで行われた作業の恩恵を受けることができます。 " "この経験は、ツールとプロジェクトの編成方法にすでに存在していました。" -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -969,7 +977,7 @@ msgstr "" "いくつかの回復された関数が同じ状態に依存している場合、それらの分離された比較は重要な質問を開いたままにします。 " "彼らが一緒に働いているのを見る必要があります。 このレッスンは、TH095のプログラム全体のビルドにどのようにアプローチしたかを形作るのに役立ちました。" -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -980,7 +988,7 @@ msgstr "" "私がそこにいる間、私の頭の中にとどまるレッスンは役に立ちます。 別のセッションが実行できるチェックになると、私が移動した後も助け続けることができます。 " "次のエージェントは、それにつながった調査を繰り返すことなく、結果を使用することができます。" -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -993,7 +1001,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1004,7 +1012,7 @@ msgstr "" "{ph0}この方法は、次のゲームの出発材料の一部になります。{ph1} " "私たちは、次のプロジェクトの努力の多くを、その目標について実際に新しいものに費やすことができます。" -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1015,7 +1023,7 @@ msgstr "" "同じ利点は、後で参加する人々に利用可能です。 彼らは決定を検査し、作業を続行する前にそのチェックを再実行することができます。 " "彼らは、ソースがそれがないように見える理由を見つけるために、プロジェクト全体の履歴を再構築する必要はありません。" -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04:ワークフローは異なるアーキテクチャで存続します" @@ -1024,7 +1032,7 @@ msgstr "TH04:ワークフローは異なるアーキテクチャで存続しま #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1039,7 +1047,7 @@ msgstr "" "そのハードウェアの動作を理解するには、Windowsゲームとは異なる証拠が必要でした。 既存の {ph2}Rec98作品{ph3} " "私たちに貴重な知識とソース材料をここにも与えました。" -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1050,7 +1058,7 @@ msgstr "" "DOSの再構築は現在機能しています。 私の手動テストでは、私は彼らのエンディングを介して完全な通常のルートを再生し、保存を確認しました。 " "現在の作業はネイティブの64ビットポートです。 動作中のDOSバージョンを確立すると、最初にそのポートに参照が与えられます。" -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1061,7 +1069,7 @@ msgstr "" "建築は私達が調査するために必要としたものを変えた。 また、作業をチェックしたコンパイラとランタイムも変更されました。 " "しかし、エージェントはまだ結果に至るまでの質問に従うことができ、その結果は次の実験を導くことができます。" -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1074,7 +1082,7 @@ msgstr "" "私たちは、どの州がその境界を越えて運び、どのプログラムがそれを担当しているかを知る必要があります。 それはDOS製品に対して調査できるものです。 " "証拠とチェックが利用可能になると、エージェントはWindowsタイトルと同じように質問を処理することができます。" -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1084,7 +1092,7 @@ msgstr "" "これが、TH04が引数に重要である理由です。 プラットフォームを大幅に変更しても、新しい作業方法でやり直すことはできませんでした。 " "アーキテクチャは問題を定義しましたが、ワークフローはまだそれを解決する方法を与えてくれました。" -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1100,7 +1108,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1110,19 +1118,19 @@ msgstr "" "2026年10月10日現在のプロジェクト状況: {ph0}DOSの再構成および手動テスト{ph1} · {ph2}64ビットポート{ph3}. " "港は開発中のままです。" -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "正確なコードから読みやすいコードへ" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "復興がうまくいったら、他の誰かにそれを理解してもらいたいです。" -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1135,7 +1143,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1150,7 +1158,7 @@ msgstr "" "その役割を説明できるまで、ゲームがどのようにそれを使用するかに従います。 それから、意味のある名前と証拠に合ったタイプを与えることができます。 " "次の人がその解釈がどこから来たのかを見ることができるように、私たちは推論をソースと一緒に保ちます。" -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1163,14 +1171,14 @@ msgstr "" "これは、どのオブジェクトがその状態を所有すべきかを決定する上で、64ビットの実装にはほとんど助けになりません。 " "動作を安全に移動するには、古いメモリアクセスの背後にある関係を回復する必要があります。" -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "私が今使用している順序は次のとおりです:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1184,7 +1192,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1199,7 +1207,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1214,7 +1222,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1227,7 +1235,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1241,7 +1249,7 @@ msgstr "" "最初の検証リファレンス(oracle)では、変更されたソースが関連する元のコードとデータを再現しているかどうかを確認します。 " "第二は、再構築されたプログラムがまだ構築され、我々が行使するパスに沿って正しく動作することを確認します。" -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1253,7 +1261,7 @@ msgstr "" "所有権の変更は、状態の異なるコピーを使用してゲームの2つの部分を残すことができます。 " "両方のチェックを利用できるようにしておくと、リファクタリングをさらに実行する前にエージェントが具体的に調査できなくなります。" -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1269,7 +1277,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1286,7 +1294,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1296,12 +1304,12 @@ msgstr "" "{ph0}正確な再構成は私たちに参照を与えます。 セマンティック再構成は、回収された知識を使用可能にする。{ph1} " "ポートは、両方の上に構築することができます。" -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "これを産業シフトにするものは何ですか" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1313,7 +1321,7 @@ msgstr "" "エージェントが調査の多くを前進させることができれば、彼らの作業環境を改善することは私ができる最も有用なことの一つになりました。 " "より良いツールは、それを必要とするすべての後の機能を助けることができます。" -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1325,7 +1333,7 @@ msgstr "" "エージェントは、予想外のどこかでその結果に従うのに十分な自由を必要とします。 " "私が各ステップを処方するのを待たなければならない場合、仕事の多くは私の注意に結びついています。" -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1337,7 +1345,7 @@ msgstr "" "失敗したチェックは、それが再試行するのに十分な間違いを理解するのに役立つはずです。 " "私はまだ蓄積された証拠がプロジェクトのマイルストーンをサポートしているかどうかを判断する必要があります。" -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1350,7 +1358,7 @@ msgstr "" "Reconstructionプロジェクトは、コンパイラとそれ自身の参照チェックを提供します。 " "エージェントはそれらを使用して、提案するソースをテストし、その説明がどこに保持されているかを確認できます。" -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1366,7 +1374,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1384,7 +1392,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1399,7 +1407,7 @@ msgstr "" "共有ツールに欠陥が見つかった場合は、それを修復し、影響を受けた結果を再検討する必要があります。 " "次のプロジェクトは、より強力なツールを継承することができます。" -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1413,7 +1421,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1424,7 +1432,7 @@ msgstr "" "ザ- {ph0}東方復興工場{ph1} その必要性から成長しました。 それはプロジェクトに彼らの点検およびレッスンを先に運ぶ共有された方法を与える。 " "あるゲームでの作業は、別のゲームの開始条件を改善することができます。" -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1434,12 +1442,12 @@ msgstr "" "それが私にとって産業的な類推を意味のあるものにしているのです。 経験は、他の人が使用できるツールの一部になり始めます。 " "これらのツールを改善することで、次の人、または次のエージェントがどれだけ達成できるかが変わります。" -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "今考えられるプロジェクトは" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1450,7 +1458,7 @@ msgstr "" "ゲームはリバースエンジニアリングにとって魅力的であり、現実的にそれを与えることができるよりも私自身の注意を要求することができます。 " "多くのプロジェクトは、アイデアを滞在します。" -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1466,7 +1474,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1476,7 +1484,7 @@ msgstr "" "私は今、なじみのないプログラムを見て、尋ねる: " "{ph0}どのようなアクセス、フィードバック、蓄積された知識が、エージェントがこれに確実に取り組むことを可能にするでしょうか?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1486,12 +1494,12 @@ msgstr "" "その質問は、私が以前に一人で残していたであろうプロジェクトを考えさせます。 それぞれが私たちが次のアプローチ方法を改善することができます。 " "私はそれが私たちをどこまで連れて行くことができるかを探求し続けたいです。" -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "プロジェクトのマイルストーンとソース" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1523,7 +1531,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1557,7 +1565,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1574,7 +1582,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1597,7 +1605,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1618,7 +1626,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1634,7 +1642,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1654,7 +1662,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1668,7 +1676,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1688,27 +1696,27 @@ msgstr "" "N0zoM1z0は、手動リバースエンジニアリング、AIエージェントによる東方再構築、TH08、TH095、PC-98 " "TH04の知識がどのように化合物であるかを反映しています。" -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "プロジェクト間で実施された経験" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "東方復興エッセイ" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -1717,18 +1725,18 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}ホーム{ph1}{ph2}/{ph3}恐竜スピードラボ" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "検査→再構築→変更" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "恐竜のスピードルールを再構築します。" @@ -1737,7 +1745,7 @@ msgstr "恐竜のスピードルールを再構築します。" #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1748,15 +1756,15 @@ msgstr "" "ゲームの加速を再現するには、まずその速度を制御するルールを見つけます。 {ph0} REAが実行中のスクリプトを返しました;{ph1} " "私たちは、このミニゲームを構築するために、そのルールを使用しました {ph2}調節可能な速度。{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "このページでは" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1764,7 +1772,7 @@ msgstr "{ph0}再生し、速度を変更します{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1772,7 +1780,7 @@ msgstr "{ph0}回復されたルールを読む{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1780,18 +1788,18 @@ msgstr "{ph0}再構築を確認する{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}分析を試してみてください{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "再生し、速度を変更します" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1801,54 +1809,54 @@ msgstr "" "プレスプレイは、その後、サボテンの上にジャンプします。 速度スライダを動かして、より遅いまたはより速いゲームを試してみてください。 " "回復されたルールを選択して6から開始し、徐々に再び加速します。" -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "再構築したゲームで遊ぶ" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "スタート" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "ジャンプ ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "リスタート" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "速度" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "回復された加速ルールを使用する" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "元のルール:6から開始し、13に向かって増加します。" -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "スライダーを動かして独自の速度を設定します。 スペースまたはジャンプはサボテンをクリアします。" -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "再構成を再生するには、JavaScriptを有効にします。 上記のコードと説明は読みやすいままです。" -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "返されたスクリプトREAを読みます" @@ -1856,7 +1864,7 @@ msgstr "返されたスクリプトREAを読みます" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1870,7 +1878,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1878,18 +1886,18 @@ msgid "" "update without a collision." msgstr "設定は次のとおりです {ph0}, {ph1} と {ph2}. ゲームは衝突することなく更新時にこのブランチを実行します。" -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "新しいゲームで同じルールを使用します" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "コピー" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -1904,18 +1912,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}スピードルールをダウンロードする{ph1} · {ph2}ゲームコードを読む{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "再構築を確認する" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -1924,41 +1932,41 @@ msgid "" msgstr "" "私たちは、障害物や自動スケジューリングを無効にして、元のゲームの更新機能と呼びました。 これらの記録された速度を、回復されたルールの再生と比較します。" -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "更新情報" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "オリジナルゲーム" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "再構築されたルール" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "速度チェックを実行する" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " "final increment can take speed just above 13." msgstr "値は小数点以下3桁に丸められます。 分岐は追加する前にチェックするので、最終的な増分は13をちょうど上回る速度を取ることができます。" -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "自分で分析を試してみてください" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -1967,14 +1975,14 @@ msgstr "{ph0}REAのセットアップ {ph1} あなたのコーディングの代 #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "フォローしてください {ph0}ブラウザ接続手順{ph1}、を使用して {ph2} ページURLとして。" -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -1989,7 +1997,7 @@ msgstr "エージェントにページURLとローカルデバッグエンドポ #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2001,7 +2009,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディング #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2014,7 +2022,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2029,7 +2037,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2052,64 +2060,64 @@ msgid "" "speed and play." msgstr "REAで恐竜ゲームの速度ルールを読んで、それを再構築し、速度を変更して再生します。" -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "恐竜スピード復元" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "恐竜ミニゲーム。 ゲームがフォーカスされている間にジャンプボタンを使用するか、スペースを押します。" -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "再構築された速度ルールのコピー" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "コピー恐竜解析プロンプト" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}ホーム{ph1} /よくある質問" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REAよくある質問。" -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "セットアップ、更新、分析、トラブルシューティング。" -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "トピックス" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2117,7 +2125,7 @@ msgstr "{ph0}セットアップと更新{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2125,7 +2133,7 @@ msgstr "{ph0}分析{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2133,31 +2141,31 @@ msgstr "{ph0}トラブルシューティング{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}データと共有{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "セットアップと更新" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "REA のインストール方法は?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "端末·エージェントの設定" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "コピー" @@ -2165,7 +2173,7 @@ msgstr "コピー" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2177,12 +2185,12 @@ msgstr "" "セットアップは REA の MCP " "接続を登録し、対応する調査スキルをインストールします。完了したらエージェントを再起動し、調べたいファイルのパスと質問を渡してください。必要な環境と最初の分析手順は{ph0}セットアップガイド{ph1}で確認できます。" -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "REAを使用できるコーディングエージェントはどれですか?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2197,31 +2205,31 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}コーディングエージェントを接続する{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "REA の更新方法は?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " "npm:" msgstr "REAは、バグ修正を含め、頻繁にリリースされます。 CLIをnpmとともにインストールした場合 :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "ターミナル*インストールされているCLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2229,14 +2237,14 @@ msgid "" "agent through {ph0}, run:" msgstr "更新によって印刷されたsetup refreshコマンドに従います。 エージェントを設定した場合 {ph0}、走る:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "端末·更新エージェントの設定" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2248,14 +2256,14 @@ msgstr "" "の接続設定にはパッケージのバージョンが指定されているため、セットアップをやり直すと新しいリリースを使えます。単発の CLI 操作では、{ph0} " "の後にコマンドを続けてください。" -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "からスキルをインストールしていますskills.sh もういい?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2266,24 +2274,24 @@ msgstr "" "スキルは、あなたのエージェントの調査の指示を与えます。 走れ。 {ph0} REAセットアップ{ph1} " "MCPサーバーに接続して一致するスキルをインストールするには、エージェントを再起動してツールを呼び出すことができます。" -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "分析" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "REAで何を分析できますか?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "あなたが持っている種類のソフトウェアから始めてください:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2293,7 +2301,7 @@ msgstr "{ph0}ネイティブ実行可能ファイルとライブラリ{ph1}:関 #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2303,7 +2311,7 @@ msgstr "{ph0} JavaScriptおよびElectronアプリ{ph1}:モジュール、イ #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2311,7 +2319,7 @@ msgstr "{ph0}ブラウザのページ{ph1}:スクリプト、要求、およ #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2322,12 +2330,12 @@ msgstr "" "REAには、マネージアセンブリ、Android Apk、ファームウェア、パッケージリソースのワークフローもあります。 " "{ph0}ケーススタディを見る{ph1} 働いた調査のために。" -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Hopper、Ghidra、またはIDAが必要ですか?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2338,7 +2346,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2349,26 +2357,26 @@ msgstr "" "既存のGhidraまたはIDAインストールを接続するか、セットアップにHopperを検出させてインストールを提案させます。 " "使用できるプロバイダーは、ホストとターゲットによって決まります。 {ph0}マシンコードプログラムの解析の設定{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "コーディングエージェントなしでREAを使用できますか?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " "Electron app:" msgstr "はい。. CLIは同じ分析ワークフローを使用します。 ローカルJavaScriptまたはElectronアプリの場合:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "端末*静的アプリケーション解析" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2378,13 +2386,13 @@ msgstr "" "パスを抽出したアプリケーションフォルダまたはASARファイルに置き換えます。 {ph0}CLIを使用する {ph1} インストールオプション用。" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA はどんなコードを返しますか?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2398,7 +2406,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2409,12 +2417,12 @@ msgstr "" "エージェントは、これらの調査結果を使用して、動作を説明したり、実装を記述してテストしたりします。 ザ- {ph0} DX-Ball計算{ph1} と " "{ph2}CTFフラグチェッカー{ph3} そのプロセスがどのように機能するかを示します。" -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "エージェントに何を聞けばいい?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2429,7 +2437,7 @@ msgstr "それにローカルターゲットと調査するための一つの動 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2437,7 +2445,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディング #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2446,18 +2454,18 @@ msgid "" msgstr "" "パスをターゲットに置き換えます。 ザ- {ph0}ガイド{ph1} ネイティブ、Electron、およびブラウザの例のプロンプトを提供します。" -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "トラブルシューティング" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "エージェントにREAツールが表示されないのはなぜですか?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2465,7 +2473,7 @@ msgid "" " {ph0}; for Codex:" msgstr "セットアップ後にエージェントを再起動または再接続します。 でそのREA登録を確認してください {ph0};Codexのため :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "端末·一つのクライアントを確認してください" @@ -2473,7 +2481,7 @@ msgstr "端末·一つのクライアントを確認してください" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2483,14 +2491,14 @@ msgstr "" "置換 {ph0} クライアントIDでは、次のようになります {ph1} または {ph2}. " "レポートに不足している登録または古い登録が表示されている場合は、そのクライアントのセットアップを実行します:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "端末*クライアントのセットアップを修復" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2501,14 +2509,14 @@ msgstr "" "その計画を確認し、クライアントを再起動します。 登録は正常ですが、ツールが存在しない場合は、クライアントのMCP接続エラーを確認してください。 " "{ph0}より多くのセットアップ診断{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "最初にHopperを起動する必要がありますか?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2519,14 +2527,14 @@ msgstr "" "REAは、操作が必要なときにHopperを開始します。 macOSでは、無人分析の前にデモモードまたはライセンス認証の最初の実行選択を完了します。 " "{ph0}ネイティブプロバイダーの設定を参照してください{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "バグが起きたらどうすればいい?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2537,7 +2545,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2549,24 +2557,24 @@ msgstr "" "あなたのREAバージョン、オペレーティングシステム、ターゲットタイプ、再現する手順とエラー出力を使用します。 " "問題がマシンコードプログラムの分析に関係する場合は、プロバイダー名を含めます。" -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "データと共有" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "REAは私のアプリをアップロードしますか?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " "its model provider's data policy applies to those results." msgstr "REAは、マシン上のターゲットを分析します。 エージェントは結果を受け取り、モデルプロバイダーのデータポリシーがその結果に適用されます。" -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "例を共有したり、貢献したりするにはどうすればよいですか?" @@ -2575,7 +2583,7 @@ msgstr "例を共有したり、貢献したりするにはどうすればよい #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2589,7 +2597,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2610,91 +2618,91 @@ msgid "" "coding agents, troubleshooting and sharing examples." msgstr "一般的なREAの質問への回答:インストール、更新、分析ツール、コーディングエージェント、トラブルシューティングと共有例。" -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "REAに関するよくある質問" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "コピー REAセットアップコマンド" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "COPY REA updateコマンド" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Copy agent setup refreshコマンド" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "コピー REA CLI解析コマンド" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "分析例のコピー" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "クライアント診断コマンドのコピー" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "スコープ設定のコピーコマンド" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}ホーム{ph1} /あなたの最初の調査" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "どこを見つける{ph0}エクスポートされたノートは行きます。" -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" " detail yourself." msgstr "REAを使用して、小さなアプリを検査し、そのエクスポートノートボタンに従って、自分で詳細を確認します。" -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "この演習では" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2702,7 +2710,7 @@ msgstr "{ph0}1. セットアップ{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2710,7 +2718,7 @@ msgstr "{ph0}2. 輸出について尋ねる{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2718,7 +2726,7 @@ msgstr "{ph0}3. 答えに従ってください{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2726,13 +2734,13 @@ msgstr "{ph0}4. 予測を確認する{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. 別の質問をする{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. エージェントをREAに接続します" @@ -2745,43 +2753,43 @@ msgstr "1. エージェントをREAに接続します" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "コピー" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "または、ターミナルでこのコマンドを実行します:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " "connected? Continue below." msgstr "計画を確認し、設定を承認してから、エージェントを再起動します。 すでに接続されていますか? 以下に進みます。" -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. CSVがどこに書かれているかを尋ねる" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2792,7 +2800,7 @@ msgstr "" "この例では、6つのファイルElectronアプリを使用しています。 {ph0}ノートのエクスポート{ph1} ボタン。 " "エージェントは、Electronをインストールまたは起動せずにコードを検査できます。" -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2802,14 +2810,14 @@ msgstr "エージェントはファイルをダウンロードし、検査のた #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}ダウンロード例ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2819,12 +2827,12 @@ msgstr "" "エージェントがファイルをダウンロードできない場合は、このアーカイブを自分で解凍します。 それへの道を与えてください {ph0} " "フォルダと同じエクスポートの質問。" -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. コードに戻って答えに従ってください" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "ファイルと行の参照に関する簡単な説明を探してください:" @@ -2833,7 +2841,7 @@ msgstr "ファイルと行の参照に関する簡単な説明を探してくだ #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2844,19 +2852,19 @@ msgstr "" "ボタンはaを送ります {ph0} メッセージ。 メインプロセスは、CSVとしてノートをフォーマットし、書き込みます {ph1} " "ユーザーのダウンロードフォルダにあります。 列は次のとおりです {ph2} と {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "ボタンからファイルライターへ" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" " read from code." msgstr "REAの静的解析は、メッセージとそのハンドラーをペアリングします。 宛先はコードから読み取られます。" -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -2867,37 +2875,37 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}完全なコードトレースと記録されたREA結果を参照してください{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. 予測を確認する" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " "contains a comma or quotation marks?" msgstr "コンマはCSV列を区切っています。 ノートタイトル自体にコンマまたは引用符が含まれている場合はどうなりますか?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "自分でチェックを実行します" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "開梱された端末で端末を開く {ph0} フォルダ:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -2906,24 +2914,24 @@ msgstr "" "このコマンドは、bashやZshなどのhere-documentをサポートするシェルを使用します。 " "エージェントは、プラットフォームのシェルで同じJavaScriptを実行できます。" -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. 別の質問をする" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "同じ会話でフォローアップを試してみてください:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "ファイルを書き込めない場合はどうなりますか? エラーに従ってページに戻ります。" -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -2934,7 +2942,7 @@ msgstr "または、エージェントに独自のアプリを提供し、一つ #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2947,7 +2955,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2960,7 +2968,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2983,113 +2991,113 @@ msgstr "" "小さなノートアプリでREAを試してみてください。 " "エージェントを設定し、エクスポートされたノートの場所を尋ね、サンプルタイトル付きのCSVフォーマッタを確認します。" -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "あなたの最初のREA調査" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "コピー REAインストールプロンプト" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Copy setupコマンド" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "コピーノート調査プロンプト" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "コピー CSVチェックプロンプト" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "コピーフォーマッタチェックコマンド" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}ホーム{ph1} /はじめに" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "REAをセットアップします。" -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "REAをコーディングエージェントに接続するか、端末からローカルアプリを検査します。" -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "ターミナルを開いて確認してください:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "ターミナル" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "コピー" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows(PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3100,7 +3108,7 @@ msgstr "条件に同意するように求められた場合は、\"Y\"と入力 #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3110,17 +3118,17 @@ msgstr "" "PowerShellが後で言う場合 {ph0}「このシステムでスクリプトの実行が無効になっています」{ph1} あなたが実行するとき " "{ph2}、これを一度実行して再試行してください:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Homebrewを使用する場合 :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "それ以外の場合:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "ターミナルを閉じて、もう一度開いてから、:" @@ -3128,7 +3136,7 @@ msgstr "ターミナルを閉じて、もう一度開いてから、:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3139,7 +3147,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3151,7 +3159,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3159,14 +3167,14 @@ msgid "" "{ph0}nodejs.org{ph1}." msgstr "通常のインストーラを好みますか? からLTSバージョンをダウンロードしてください {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "セットアップオプション" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3174,7 +3182,7 @@ msgstr "{ph0}コーディングエージェントを接続する{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3182,7 +3190,7 @@ msgstr "{ph0}CLIを使用する {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3190,18 +3198,18 @@ msgstr "{ph0}マシンコードプログラムの解析の設定{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}助けを得る{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "コーディングエージェントを接続する" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3212,12 +3220,12 @@ msgstr "" "Code、Codex、Cursor、Gemini CLI、Windsurf、Grok " "Build、およびその他のサポートされているMCPクライアントが含まれます。 Grok Botのコネクタはチャットから追加されます。" -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "コーディングエージェントは初めてですか?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3227,7 +3235,7 @@ msgstr "" "コーディングエージェントは、ブラウザタブではなくコンピュータ上で動作するAIアシスタントです。 " "ファイルを読み込んでコマンドを実行することができ、変更を加える前に要求します。 REAはリバースエンジニアリングツールを提供します。" -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3237,7 +3245,7 @@ msgstr "まだお持ちでない場合は、1つを選択し、インストー #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3248,7 +3256,7 @@ msgstr "{ph0}{ph1} Claude Code {ph2}{ph3} Anthropicによって。 有料Claude #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3259,7 +3267,7 @@ msgstr "{ph0}{ph1} Codex {ph2}{ph3} OpenAIによって。 ChatGPTアカウント #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3267,7 +3275,7 @@ msgid "" "your choice." msgstr "{ph0}{ph1} OpenCode {ph2}{ph3}、オープンソース。 お好みのモデルプロバイダを接続します。" -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3282,18 +3290,18 @@ msgstr "次に、それを開き、下のプロンプトをその中にコピー #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "または自分でセットアップを実行します" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "ターミナルを開くにはどうすればよいですか?" @@ -3302,7 +3310,7 @@ msgstr "ターミナルを開くにはどうすればよいですか?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3318,7 +3326,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3330,7 +3338,7 @@ msgstr "{ph0} macOS :{ph1} プレス {ph2} {ph3}、タイプ {ph4}ターミナ #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3343,7 +3351,7 @@ msgstr "{ph0} Linux :{ph1} プレス {ph2} {ph3} {ph4} ほとんどのデスク #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3353,7 +3361,7 @@ msgstr "" "でコマンドを貼り付ける {ph0} {ph1} (macOS : {ph2} {ph3};Linux端子: {ph4} {ph5} " "{ph6})を押し、Enterキーを押します。" -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3363,12 +3371,12 @@ msgstr "" "クライアントを選択し、セットアッププランを確認します。 REAは、MCP接続とマッチング調査スキルを追加し、既存の構成のバックアップを保持します。 " "変更を適用する前に尋ねます。" -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "セットアップが完了したら、クライアントを再起動します。" -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "クライアントを再起動するにはどうすればよいですか?" @@ -3377,7 +3385,7 @@ msgstr "クライアントを再起動するにはどうすればよいですか #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3392,7 +3400,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3401,7 +3409,7 @@ msgid "" msgstr "" "{ph0}ターミナルエージェント{ph1} (Claude Code,Codex,Gemini CLI):セッションを終了し、再度開始します。" -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3409,7 +3417,7 @@ msgid "" msgstr "エージェントにターゲットパスと特定の質問を与えます。 JavaScriptまたはElectronアプリの場合は、次のように開始できます:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3419,12 +3427,12 @@ msgstr "" "を見てください {ph0} そして、それはデータをエクスポートする方法を見つけます。 " "関連するエントリポイント、呼び出し、依存関係、および調査結果のソースの場所を表示します。" -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "パスをローカルターゲットに置き換えます。" -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "フォルダのフルパスを取得するにはどうすればよいですか?" @@ -3433,7 +3441,7 @@ msgstr "フォルダのフルパスを取得するにはどうすればよいで #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3447,7 +3455,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3459,7 +3467,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3467,31 +3475,31 @@ msgid "" "appears." msgstr "{ph0}任意のシステム:{ph1} フォルダをターミナルウィンドウにドラッグすると、そのパスが表示されます。" -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "ターミナルでは、スペースを含むパスの周りに引用符を付けます。" -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "CLIを使用する" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " "running the app:" msgstr "アプリを実行せずに、JavaScriptまたはElectronアプリケーションフォルダーまたはASARアーカイブを分析します:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "静的アプリケーション分析" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3500,13 +3508,13 @@ msgid "" msgstr "" "パスを抽出したアプリディレクトリに置き換えます。 {ph0} ファイル。 Windowsでは、次のようなパス {ph1} ここで働いています。" -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "どこでアプリを見つけるのですか。asarファイル?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3517,7 +3525,7 @@ msgstr "Electronアプリは、通常、それを維持します {ph0} フォル #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3529,7 +3537,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3540,20 +3548,20 @@ msgstr "{ph0} macOS :{ph1} {ph2} (アプリを右クリックして選択し #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} 多くの場合 {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "一部のアプリは他の場所にインストールされます。 アプリのフォルダを検索します {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3562,31 +3570,31 @@ msgid "" msgstr "結果はアプリを識別し、モジュール間の接続を示し、ソースの場所を示します。 REAが解決できない接続は、結果にマークされています。" #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "パーマネントをご希望の場合は {ph0} シェル内のコマンド:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "CLIをインストールする" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}JavaScriptアプリケーションガイドの続きを読む{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "マシンコードプログラムの解析の設定" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3594,12 +3602,12 @@ msgid "" msgstr "" "マシンコードプログラムには、ローカル解析ツールが必要です。 以下のいずれかを選択して設定し、REAに実行可能ファイルまたはライブラリを与えます。" -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "ツールを選択します:Ghidra、HopperまたはIDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3609,17 +3617,17 @@ msgstr "" "既存のGhidra12.1を使用します。X64またはarm64上のLinuxまたはmacOS上のXインストールおよび64ビットJDK21以降。 " "Ghidraインストールには、ホストアーキテクチャ用のネイティブ逆コンパイラが必要です。 セットアップを実行する前にパスを設定します:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Ghidraインストールを接続します" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra接続•macOS/Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3629,12 +3637,12 @@ msgstr "" "両方のパスを既存のインストールに置き換えます。 セットアップはそれらをチェックし、選択したクライアントの有効な設定を記録します。 Linux " "arm64では、Ghidraのネイティブ逆コンパイラを個別にビルドする必要がある場合があります。" -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "GhidraをWindowsに接続する" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3645,18 +3653,18 @@ msgstr "" "x64は、固定ローカルNTFSドライブ上のネイティブx86およびx64PEアプリケーションとDllのための実験的な、読み取り専用のサポートを持っています。" " 既存のGhidra12.1を使用します。Xのインストールおよび64ビットJDK21以降:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra接続•Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "2つのパスをインストールに置き換えてから、セットアップの計画を確認します。" -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3665,14 +3673,14 @@ msgstr "" "HopperをmacOSまたはLinuxに接続します。 " "上記のsetupコマンドを実行します。既存のインストールを検出するか、承認のためのインストール計画を提供します。" -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " "activation before an unattended analysis." msgstr "macOSでは、無人分析の前にデモモードまたはライセンス認証のHopperの最初の実行選択を完了します。" -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3682,7 +3690,7 @@ msgstr "" "検証済みのIDAセットアップでは、Windowsを使用し、接続されたGUIまたはヘッドレスデータベース用の既存のMCP登録が使用されます。 " "LinuxおよびmacOSヘッドレス解析は未検証のままです。" -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "既存のIDA MCP登録を接続する" @@ -3692,7 +3700,7 @@ msgstr "既存のIDA MCP登録を接続する" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3703,13 +3711,13 @@ msgstr "" "アップストリームサーバーの動作を維持する {ph0}, {ph1} とオプション {ph2} JSONファイルで。 既存の {ph3} " "を持つオブジェクト {ph4} エントリーも受け付けています。 セットアップ前にそのファイルにREAをポイントします:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA接続•Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3725,7 +3733,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3736,29 +3744,29 @@ msgstr "" "REAに元の実行可能ファイルパスを与え、次のようにします {ph0} CLIクエリで。 エージェントの場合は、次のものが含まれます。 {ph1} " "REA登録の環境で、バイナリを開くときにIDAを選択します。" -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "既存のGhidraセットアップでは、次のような関数を検査します:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "関数解析" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "置換 {ph0} 検査する関数名またはアドレスを指定します。" -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "マシンコード-プログラム-セッションの分析の仕組み" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3770,7 +3778,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3778,18 +3786,18 @@ msgid "" "leads to a recovered calculation." msgstr "{ph0}マシンコードプログラムの分析の例に従ってください{ph1} 関数の結果がどのように回復された計算につながるかを確認します。" -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "助けを得る" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "エージェントにREAが表示されない場合" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3797,27 +3805,27 @@ msgid "" "{ph0}; for Codex:" msgstr "セットアップ後にクライアントを再起動または再接続します。 とのREA接続を確認してください {ph0};Codexのため :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "一つのクライアントをチェック" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "プロバイダが注意を必要とする場合" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "使用しているプロバイダーを確認してください。 Ghidraのため :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "一つのプロバイダを確認してください" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "レポートには、失敗したチェックと推奨される次のステップが表示されます。" @@ -3826,7 +3834,7 @@ msgstr "レポートには、失敗したチェックと推奨される次のス #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3837,7 +3845,7 @@ msgstr "{ph0} REAよくある質問{ph1}{ph2}更新、エージェント、分 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3849,7 +3857,7 @@ msgstr "{ph0}調査ガイドを選ぶ{ph1}{ph2}バイナリ、Electronアプリ #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3861,7 +3869,7 @@ msgstr "{ph0} GitHubの問題{ph1}{ph2}コマンドと診断に関する問題 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3883,112 +3891,112 @@ msgstr "" "REAをコーディングエージェントに接続するか、ターミナルからローカルのJavaScriptまたはElectronアプリを検査します。 " "セットアップ、最初の質問とネイティブプロバイダガイド。" -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "コピー Node.jsバージョンチェック" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "コピー Node.js のインストールコマンド Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "PowerShell実行ポリシーコマンドのコピー" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "コピー Homebrew Node.jsインストールコマンド" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "macOSのfnmインストールコマンドのコピー" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Node.js24コマンドをmacOSにコピーする" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Linuxのfnmインストールコマンドのコピー" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Node.js24コマンドをLinuxにコピーする" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA入門ガイド" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "コピー REAインストールプロンプト" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Copy agent setupコマンド" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Copy JavaScript解析コマンド" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Copy CLIインストールコマンド" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "macOS・Linux 用の Ghidra 接続コマンドをコピー" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Windows PowerShell用のGhidra接続のコピー" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Windows PowerShell用のIDA接続のコピー" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "ネイティブ関数解析コマンドのコピー" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "クライアント診断コマンドのコピー" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "プロバイダ診断コマンドのコピー" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -3997,34 +4005,34 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}ホーム{ph1} / {ph2}ガイド{ph3} /ブラウザ観察" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "何が起こるか見てください{ph0}あなたがクリックすると。" -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " "JavaScript that builds a download." msgstr "小さなブラウザアプリを使用して、アクション、そのネットワーク要求、およびダウンロードを構築するJavaScriptを接続します。" -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "このガイドの内容" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4032,7 +4040,7 @@ msgstr "{ph0}この例は次のとおりです{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4040,7 +4048,7 @@ msgstr "{ph0}ブラウザを開く{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4048,7 +4056,7 @@ msgstr "{ph0}あなたの代理店に尋ねる{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4056,13 +4064,13 @@ msgstr "{ph0}CLIからのキャプチャ {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}リクエストとスクリプトを読む{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "[エクスポート]をクリックするとどうなりますか?" @@ -4072,7 +4080,7 @@ msgstr "[エクスポート]をクリックするとどうなりますか?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4083,7 +4091,7 @@ msgstr "" "ザ- {ph0}ノートブラウザの例{ph1} を持っている {ph2}ノートのエクスポート{ph3} ボタン。 それをクリックするとロードされます " "{ph4}、CSVとして二つのノートをフォーマットし、ダウンロードを開始します。" -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "クリックからCSVダウンロードへ" @@ -4094,7 +4102,7 @@ msgstr "クリックからCSVダウンロードへ" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4109,7 +4117,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4127,7 +4135,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4137,38 +4145,38 @@ msgstr "" "{ph0}03*あなたの代理店{ph1}{ph2}エクスポートコードを読む{ph3}{ph4}監視された要求をに接続して下さい {ph5} で " "{ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "[ノートのエクスポート]をクリックする前に、キャプチャを開始します。" -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "リモートデバッグでChromeを開く" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " "debugging port. On Linux:" msgstr "別のブラウザプロファイルとローカルデバッグポートを使用して、ホストされたNotesの例を開きます。 Linuxについて :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "例のブラウザを起動します" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "コピー" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4177,14 +4185,14 @@ msgstr "" "インストールされているブラウザの実行可能パスをmacOSまたはWindowsに使用します。 " "ページのURLを検査する別のページに置き換えることができます。" -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" " the action, and close the browser when finished." msgstr "REAは、この既存のブラウザに接続します。 ページの制御を維持し、アクションを実行し、終了したらブラウザを閉じます。" -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "一つのアクションを見るためにあなたのエージェ" @@ -4197,7 +4205,7 @@ msgstr "一つのアクションを見るためにあなたのエージェ" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4209,7 +4217,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディング #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4220,7 +4228,7 @@ msgstr "" "それはどのような要求を行い、CSVはどのように構築されていますか?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4229,7 +4237,7 @@ msgid "" msgstr "" "プロンプトの例。 エージェントにデバッグエンドポイントを与える, {ph0}、およびページのURL。 クリックする前にキャプチャを開始しましょう。" -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4238,23 +4246,23 @@ msgid "" msgstr "" "エージェントはページターゲットを検出し、観察ウィンドウを開始し、結果の証拠を読み取ります。 その後、エクスポートの背後にあるスクリプトを検査できます。" -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "または端末からキャプチャします" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "ページのターゲットIDを検索する:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "ページを探す" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4262,14 +4270,14 @@ msgid "" "ID, then run:" msgstr "Notesの例のURLでターゲットを選択します。 置換 {ph0} そのIDで以下を実行し、次に実行します:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "次の10秒をキャプチャします" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4279,7 +4287,7 @@ msgstr "" "コマンドを数秒間接続してから、をクリックします {ph0}ノートのエクスポート{ph1} そのブラウザで。 " "結果は、観測ウィンドウが終了した後に到着します。" -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4289,49 +4297,49 @@ msgstr "" "キャプチャされた結果には、選択されたページ、そのウィンドウ中のネットワークアクティビティ、およびJSON応答の形状が含まれます。 " "以前の要求はこのキャプチャの外にあります。" -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "リクエストとエクスポートスクリプトを読む" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "ローカルノートの例でREA4.1.0で記録されました" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "捕獲された事実" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "値" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "リクエスト" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "応答" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "リクエストイニシエータ" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} •スクリプト" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "応答構造" @@ -4339,19 +4347,19 @@ msgstr "応答構造" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} と {ph1} と {ph2} フィールド" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "ロードされたスクリプトを読む" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4362,7 +4370,7 @@ msgstr "" "キャプチャされたスクリプトソースを読んで、データの使用方法を確認します:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4372,7 +4380,7 @@ msgid "" msgstr "ダウンロードは、JSON応答を使用してページで構築されます。 CSV書式設定ステップはスクリプトから取得されます。 {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4382,7 +4390,7 @@ msgstr "要求するスクリプトを見つけます {ph0}. カンマや引用 #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4405,65 +4413,65 @@ msgid "" msgstr "" "REAを使用してノートのエクスポートを観察する:ブラウザページを選択し、クリックをキャプチャし、要求を検査し、エクスポートスクリプトに従います。" -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "ブラウザ観察" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "例のブラウザをコピーして起動します" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "プロンプトの例をコピーする" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "コピーページを探す" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "次の10秒をキャプチャしてコピーします" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "ロードされたスクリプトをコピーして読みます" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}ホーム{ph1} /ガイド" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REAガイド." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4471,59 +4479,59 @@ msgid "" msgstr "" "ネイティブ関数、Electronエクスポート、またはブラウザ要求を分析します。 各ガイドには、プロンプト、コード、および結果が含まれています。" -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "最初の調査" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "REAのセットアップ" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "コーディングエージェントを接続するか、端末からREAを使用します。" -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "REAを始める" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "マシンコードプログラム" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "左/右の音の位置の計算を回復します" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," " read numeric constants and check the recovered C." msgstr "Windowsゲーム実行可能ファイルから始めます。 命令を検査し、呼び出し元に従って、数値定数を読み取り、回復されたCを確認します。" -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "機械コードの解析プログラムガイド" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "CSVエクスポートに従ってください" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4532,37 +4540,37 @@ msgstr "" "小さなNotesアプリは、レンダラー、プリロード、メインプロセス全体に一つの機能を広げます。 " "REAを使用して、API、IPCチャネル、およびファイルライターを接続します。" -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript&Electronガイド" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "大規模なパッケージ化されたアプリの場合は、次の {ph0} Notionのクリップボードブリッジ{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "ブラウザの動作" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "クリックを観察する" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " "that turns its response into a download." msgstr "作業ノートの例を開き、エクスポート要求をキャプチャして、その応答をダウンロードに変換するコードを見つけます。" -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "ブラウザ観察ガイド" @@ -4579,12 +4587,12 @@ msgid "" "CSV export and a browser request." msgstr "ネイティブ計算、Electron CSVエクスポートとブラウザ要求:短い働いた例を通してREAを学びます。" -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -4593,34 +4601,34 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}ホーム{ph1} / {ph2}ガイド{ph3} /JavaScript&Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Electronをトレースする {ph0} CSV輸出。" -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " "file writer." msgstr "ページAPIからElectron IPCを介して、CSVファイルライターにボタンをクリックします。" -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "このガイドの内容" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4628,7 +4636,7 @@ msgstr "{ph0}この例は次のとおりです{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4636,7 +4644,7 @@ msgstr "{ph0}あなたの代理店に尋ねる{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4644,7 +4652,7 @@ msgstr "{ph0}エクスポートコードのトレース{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4652,20 +4660,20 @@ msgstr "{ph0}例を試してみてください{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}CSVライターを検査する{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"エクスポートノート\"はどこに行くのですか?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4676,7 +4684,7 @@ msgstr "" "このガイドでは、小さなElectronアプリを使用しています。 クリック {ph0}ノートのエクスポート{ph1} " "ページ内のAPIを呼び出し、メインプロセスに交差し、CSVを書き込みます。 動作は複数のファイルに分散されます。" -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "CSVは、Electronプロセス間でエクスポートします" @@ -4690,7 +4698,7 @@ msgstr "CSVは、Electronプロセス間でエクスポートします" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4707,7 +4715,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4723,7 +4731,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4736,13 +4744,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} メモの書式設定→ {ph1} 書き込み {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -4752,14 +4760,14 @@ msgstr "" "REAは、そのハンドラーへのリテラルIPC呼び出しと一致し、公開されたAPIを識別します。 " "パスはコードから推測され、ランタイムキャプチャは何が実行されるかを確認できます。" -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "CSV輸出について尋ねる" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4775,14 +4783,14 @@ msgstr "{ph0}エージェントをREAに接続します {ph1} そして、それ #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "コピー" @@ -4793,7 +4801,7 @@ msgstr "コピー" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4804,7 +4812,7 @@ msgstr "" "CSVはどこで作成されますか?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4812,7 +4820,7 @@ msgid "" "{ph0}." msgstr "プロンプトの例。 アプリケーションフォルダへの絶対パスを含めるか、 {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -4822,17 +4830,17 @@ msgstr "" "REAはアプリケーションファイルを読み取り、エントリポイント、モジュール、およびプロセス境界のマップを構築します。 " "エージェントはそのマップを使用して、調査をエクスポート機能に絞り込みます。" -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "エクスポートコードのトレース" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "ページは小さなAPIを呼び出します" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -4841,7 +4849,7 @@ msgstr "ページはメソッド名を知っています。 実装はプリロ #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4851,7 +4859,7 @@ msgstr "REAレコード {ph0} とリテラルチャンネル {ph1}. その呼び #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4861,7 +4869,7 @@ msgstr "" "ハンドラーを読むことは元の質問に答えます: {ph0} メモをフォーマットし、メインプロセスは書き込みます {ph1} " "ユーザーのダウンロードフォルダに移動します。" -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -4869,7 +4877,7 @@ msgid "" msgstr "" "以下のダウンロード可能な例でREA4.1.0によって記録されました。 ソースの場所は、API、チャネル、およびハンドラーの調査結果に伴います。" -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "自分で例を分析してください" @@ -4877,25 +4885,25 @@ msgstr "自分で例を分析してください" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}ダウンロード例ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "6つのソースファイルを参照します。" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "静的アプリケーション分析" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4905,7 +4913,7 @@ msgstr "" "パスを解凍したフォルダに置き換えます。 あなたは1つのIPCチャネルと1つの一致するハンドラを見つける必要があります {ph0}. " "ソースの場所は次のとおりです {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -4915,13 +4923,13 @@ msgstr "" "独自のアプリの場合は、そのディレクトリまたはASARパスで同じコマンドを使用します。 " "エージェントは、REAの機能トレースツールを使用して、リテラル文字列、API名、またはIPCチャネルを追跡できます。" -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "CSVライターを検査する" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4929,7 +4937,7 @@ msgid "" "happens if writing the file fails?" msgstr "フォロー {ph0} そのハンドラに。 どの入力がCSVライターに到達し、ファイルの書き込みに失敗した場合はどうなりますか?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -4941,7 +4949,7 @@ msgstr "これらの詳細を検査するには、ソースの場所を使用し #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4955,7 +4963,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4967,7 +4975,7 @@ msgstr "{ph0}ブラウザのエクスポートを観察する{ph1}{ph2}実際の #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4990,32 +4998,32 @@ msgstr "" "トレースAノートCSVレンダラー API、プリロード、およびREAを使用したIPCハンドラーを介してエクスポートします。 " "ダウンロード可能なサンプルファイルと検証済みの分析結果が含まれています。" -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "プロンプトの例をコピーする" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "静的アプリケーション分析のコピー" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -5024,34 +5032,34 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}ホーム{ph1} / {ph2}ガイド{ph3} /機械コードプログラムの解析" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "回復DX-Ballの{ph0}左/右の音の位置の計算。" -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " "check the recovered C." msgstr "元の命令を調べ、入力と定数を特定してから、復元されたCを確認します。" -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "このガイドの内容" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5059,7 +5067,7 @@ msgstr "{ph0}この例は次のとおりです{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5067,7 +5075,7 @@ msgstr "{ph0}あなたの代理店に尋ねる{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5075,7 +5083,7 @@ msgstr "{ph0}REAの結果を読む{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5083,18 +5091,18 @@ msgstr "{ph0}回復とチェック{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}独自のバイナリを使用する{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "左/右のステレオサウンドの位置を計算する" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5103,7 +5111,7 @@ msgstr "DX-Ballでは、レンガのヒットが水平画面の位置を供給 #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5114,7 +5122,7 @@ msgstr "" "開始機能, {ph0}、短い逆コンパイラの結果を持っています:への呼び出し {ph1}. " "REAはまた、エージェントに不足している算術を調査する方法を与えるその命令と呼び出し元を返します。" -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "これらの条件に新しいですか?" @@ -5123,7 +5131,7 @@ msgstr "これらの条件に新しいですか?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5133,7 +5141,7 @@ msgstr "{ph0}説明書:{ph1} プロセッサが実行する手順は、次のよ #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5145,7 +5153,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5156,7 +5164,7 @@ msgstr "{ph0}発信者:{ph1} これを呼び出す関数。 どの値が渡さ #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5166,7 +5174,7 @@ msgstr "{ph0}住所:{ph1} プログラム内の場所で、次のような16進 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5174,7 +5182,7 @@ msgid "" "and decoded." msgstr "{ph0}定数:{ph1} プログラムに格納されている固定番号は、生のバイトとして読み取られ、デコードされます。" -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "証拠の三つの部分、一つの計算" @@ -5185,7 +5193,7 @@ msgstr "証拠の三つの部分、一つの計算" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5201,7 +5209,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5217,7 +5225,7 @@ msgstr "{ph0}02*発信者{ph1}{ph2}画面座標{ph3}{ph4}ブリックヒット #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5227,14 +5235,14 @@ msgstr "" "{ph0}03*データバイト{ph1}{ph2}数値定数{ph3}{ph4}参照されたバイトはに解読します {ph5}, {ph6} " "とスケール値。{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " "interprets them together." msgstr "REAは、命令、関数呼び出しの関係、およびバイトを提供します。 エージェントはそれらを一緒に解釈します。" -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "行動について尋ねる" @@ -5243,7 +5251,7 @@ msgstr "行動について尋ねる" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5253,19 +5261,19 @@ msgstr "" "後 {ph0}REAをエージェントに接続する{ph1} と " "{ph2}マシンコードプログラムの解析ツールの設定{ph3}、ローカル実行可能ファイルと質問を提供します:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "どの分析ツールを使うべきですか?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REAは、ネイティブプログラムを読むためにこれらのいずれかが必要です:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5278,7 +5286,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5290,7 +5298,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5299,7 +5307,7 @@ msgstr "{ph0} IDA {ph1} (Windows):MCP登録を持つ既存のIDAセットアッ #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5313,14 +5321,14 @@ msgstr "見る {ph0}マシンコードプログラムの解析の設定{ph1} ス #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "コピー" @@ -5331,7 +5339,7 @@ msgstr "コピー" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5341,7 +5349,7 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用して、DX-Ballがステレオサウンドの位置を計算する方法を見つけます。 " "計算を説明し、コードを表示します。{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5351,7 +5359,7 @@ msgstr "" "プロンプトの例。 エージェントにローカルのDX-Ball1.07実行可能ファイルへのパスを指定します。 REAにはDX-" "Ballが含まれていないため、独自のコピーを使用するか、持っている別の小さなWindowsプログラムについて同じ種類の質問をしてください。" -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "ファイルのフルパスを取得するにはどうすればよいですか?" @@ -5360,7 +5368,7 @@ msgstr "ファイルのフルパスを取得するにはどうすればよいで #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5374,7 +5382,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5386,7 +5394,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5394,30 +5402,30 @@ msgid "" "appears." msgstr "{ph0}任意のシステム:{ph1} ファイルをターミナルウィンドウにドラッグすると、そのパスが表示されます。" -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "REAの結果を読む" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "入力を読む" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " "arithmetic. This is the input absent from the first pseudocode view." msgstr "命令は整数引数をロードし、浮動小数点演算用に変換します。 これは、最初の擬似コードビューに存在しない入力です。" -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "発信者に従ってください" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5426,24 +5434,24 @@ msgid "" msgstr "" "REAは、ブリックヒット呼び出し元を識別します。 以前の手順では、タイル座標に30を掛けます。 {ph0} (20)は、レンガの画面位置を与えます。" -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "参照される定数の読み取り" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " "actual values; the instruction order tells the agent how they are used." msgstr "算術はこれらのアドレスを参照します。 命令の順序は、それらがどのように使用されているかをエージェントに伝えます。" -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "復元された機能の書き込みと確認" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5453,7 +5461,7 @@ msgstr "" "縮尺が1.0の場合、画面の位置0、320、640は整数変換の前に-500、0、500にマップされます。 " "この計算では、画面の中心がステレオフィールドの中心に置かれます。" -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5465,20 +5473,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}完全な調査とアセンブリとCの比較を参照してください{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "独自のバイナリで試してみてください" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5491,20 +5499,20 @@ msgstr "" "次に、エージェントにローカルの実行可能ファイルまたはライブラリと調査する機能を提供します。 " "有用な開始質問には、\"このファイルはどのように解析されますか?\"または\"このメニューアクションを処理する関数はどれですか?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " "terminal. For a configured Ghidra installation:" msgstr "関数名またはアドレスがすでにわかっている場合は、端末からクエリできます。 構成されたGhidraインストールの場合:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "関数解析" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5517,7 +5525,7 @@ msgstr "" "各CLI呼び出しは、バイナリをインポートして分析し、そのセッションを閉じます。 " "エージェントのMCPクエリは、セッションが開いている間にインポートされたバイナリを再利用します。" -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5536,50 +5544,50 @@ msgid "" "caller, read constants and check reconstructed C." msgstr "REAでネイティブ計算を復元する:命令を検査し、呼び出し元に従って、定数を読み取り、再構成されたCを確認します。" -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "機械コードプログラムの解析" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "プロンプトの例をコピーする" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "コピー関数解析" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "このページでは" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "REAのセットアップ" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5587,7 +5595,7 @@ msgstr "{ph0}REAのセットアップ {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5595,7 +5603,7 @@ msgstr "{ph0}REとは何ですか?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5603,7 +5611,7 @@ msgstr "{ph0}REA がどう役立つか{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5611,7 +5619,7 @@ msgstr "{ph0}恐竜ゲーム{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5619,7 +5627,7 @@ msgstr "{ph0}電卓{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5627,7 +5635,7 @@ msgstr "{ph0}REAを試してみてください {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5635,7 +5643,7 @@ msgstr "{ph0}さらに詳しく{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5643,25 +5651,25 @@ msgstr "{ph0}ヘルプとフィードバック{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}コミュニティ{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "コーディングエージェントとのリバースエンジニアリング" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "ソフトウェアの{ph0}仕組みを知ろう。" -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5670,7 +5678,7 @@ msgstr "REA は、プログラムを調べて動作を説明するためのツ #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5678,13 +5686,13 @@ msgstr "すでに再を知っていますか? {ph0}分析ガイドへスキッ #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "もっと深く行きたいですか? {ph0}ブログを読む→{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "このプロンプトをコーディングエージェントに貼り付けてください:" @@ -5697,38 +5705,38 @@ msgstr "このプロンプトをコーディングエージェントに貼り付 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "コピー" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "ターミナルから実行することもできます:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "設定の変更内容を確認して承認したら、エージェントを再起動します。" -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "リバースエンジニアリングとは?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5741,7 +5749,7 @@ msgstr "{ph0}プログラムそのものを調べて{ph1}、ソフトウェア #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5753,7 +5761,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -5761,7 +5769,7 @@ msgstr "REA を使う前 · {ph0}自分で{ph1}調べる" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -5769,7 +5777,7 @@ msgstr "{ph0}01{ph1} 枝をデコードする" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -5777,7 +5785,7 @@ msgstr "{ph0}02{ph1} トレース呼び出し" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -5787,20 +5795,20 @@ msgstr "{ph0}03{ph1} ルールを回復する" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}オリジナルx64·選択された指示{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01*どの支店?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5808,29 +5816,29 @@ msgid "" "these?”" msgstr "“{ph0}0x5b? 0x5c?{ph1} 同じ場所に2つのジャンプ。 これらはどの演算子ですか?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "コマンドIdを検索し、ブランチにラベルを付けます。" -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "ディバイド÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "乗算×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · 呼び出された関数は何をする?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5838,24 +5846,24 @@ msgid "" "value goes in?{ph1}”" msgstr "「100は明らかです。 呼び出しは単なるアドレスです。 {ph0}どちらが分かれていますか? どの値が入りますか?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "ヘルパー関数を検査し、格納されている値をトレースします。" -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "ディバイド" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03·ルールとは何ですか?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5863,19 +5871,19 @@ msgid "" "after +.”" msgstr "\"このパスは、他の入力によって乗算されます。 だから {ph0}10%は200の10%を意味します{ph1} +の後。”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "オペランドに名前を付け、両方の演算子パスを確認します。" -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "図解専門家の推論" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5885,20 +5893,20 @@ msgstr "{ph0}命令をデコードし、関数呼び出しに従って計算を #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "REA を使うと · {ph0}エージェント{ph1}に聞く" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "プロンプトは一つだけ。" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -5912,49 +5920,49 @@ msgstr "{ph0}普段の言葉で{ph1}エージェントに質問します。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}プロンプトの例*電卓" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "回答例*調査結果に基づく" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "+の後に、%ボタンがかかります {ph0}最初の数の割合。{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA が提供する情報" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "ハンドラーの命令、逆コンパイルされたコード、および呼び出し。" -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "エージェントが説明すること" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "どのブランチが適用され、何が計算され、どのように再構築するか。" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5965,7 +5973,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5973,37 +5981,37 @@ msgid "" "Calculator and rebuild its % button." msgstr "{ph0}2つの例を試してみましょう。{ph1} ゲームの速度を変更し、電卓に戻り、その%ボタンを再構築します。" -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "例01•Chromeの恐竜ゲーム" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "恐竜はなぜ速くなる?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "ゴール" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "でゲームを再構築する {ph0}調節可能な速度。{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "なぜそれをリバースエンジニアリング?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6013,61 +6021,61 @@ msgstr "" "その加速を再現するには、次のものが必要です " "{ph0}実行中のゲームのルール{ph1}:どのくらいの速、それが増加し、それが停止したときに、それが開始されます。" -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "再構築したゲームで遊ぶ" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "スタート" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "ジャンプ ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "リスタート" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "速度" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "回復された加速ルールを使用する" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "元のルール:6から開始し、13に向かって増加します。" -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "スライダーを動かして独自の速度を設定します。 スペースまたはジャンプはサボテンをクリアします。" -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "再構成を再生するには、JavaScriptを有効にします。 上記のコードと説明は読みやすいままです。" -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA が返した結果" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6084,7 +6092,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6096,7 +6104,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}例プロンプト*恐竜ゲー #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6109,7 +6117,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6121,7 +6129,7 @@ msgstr "検査対象: {ph0}wayouのChromium派生ブラウザ版{ph1}." #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6130,12 +6138,12 @@ msgid "" msgstr "" "{ph0}6時からスタート。{ph1} 追加 {ph2}0.001{ph3} 速度は以下のとおりですが、衝突のない各更新 {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "スピードラボを開く→" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "各部分が何をするか" @@ -6146,7 +6154,7 @@ msgstr "各部分が何をするか" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6161,7 +6169,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6176,7 +6184,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6185,13 +6193,13 @@ msgid "" msgstr "" "{ph0}03*あなた{ph1}{ph2}スピードとプレイを変更します{ph3}{ph4}元の加速を試してから、自分のペースを選択してください。{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "スクリプト、チェック、および分析を試す方法を参照してください" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6201,7 +6209,7 @@ msgstr "" "REAは、ローカルデバッグ接続を介してHTTP browser editionを検査し、ロードされたものを返しました " "{ph0}、そのソースとダイジェストを含みます。" -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6213,7 +6221,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6228,7 +6236,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6244,26 +6252,26 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" "{ph0}Inspected speed code{ph1} · {ph2}Chromium Authors · BSD license{ph3}" msgstr "{ph0}検査された速度コード{ph1} · {ph2} Chromium著者·BSDライセンス{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "例02•Windows計算機" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "電卓の % ボタンを再現する。" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6272,7 +6280,7 @@ msgstr "処理する小さな電卓を構築する {ph0}+と×の両方が正し #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6282,29 +6290,29 @@ msgstr "" "同じボタンを使用します {ph0}+と×の後の異なるルール。{ph1} " "インストールされているアプリを調べて、パーセンテージが適用されている数を見つけます。" -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "計算を試してみてください" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "リセット" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10%の200=20. 次に、200+20=220。" -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "検査されたパーセンテージルールのインタラクティブなイラスト。" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6314,7 +6322,7 @@ msgstr "{ph0}1つの枝は100で割ります。 もう1つは、最初の数で #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6328,7 +6336,7 @@ msgstr "この例では, {ph0} と {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6342,7 +6350,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}プロンプトの例*%ボタン #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6353,7 +6361,7 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用して、Windows計算機の%ボタンを検査します。 " "+と×の後にルールを回復し、両方を使用する小さな電卓を作成します。{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "と+" @@ -6361,13 +6369,13 @@ msgstr "と+" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}最初の数の10%を取ります。{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "×付き" @@ -6375,13 +6383,13 @@ msgstr "×付き" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}10%を0.1に変えます。{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "インストールされているアプリから作業中の%ボタンへ" @@ -6393,7 +6401,7 @@ msgstr "インストールされているアプリから作業中の%ボタン #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6410,7 +6418,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6420,12 +6428,12 @@ msgid "" msgstr "" "{ph0}03*あなたのエージェントはそれを解釈します{ph1}{ph2}ルールの説明と再現{ph3}{ph4}ブランチをMicrosoftのソースと照合してから、上記の+と×を試してください。{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "実際のコードと答えがどのようにチェックされたかを参照してください" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6445,7 +6453,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6453,29 +6461,29 @@ msgid "" "{ph4}Native setup guide{ph5}" msgstr "{ph0}割合の実装{ph1} · {ph2}マイクロソフトのテストケース{ph3} · {ph4}ネイティブセットアップガイド{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "あなたの最初の調査" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "小さなアプリでREAを試してみてください。" -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " "input." msgstr "私たちのノートの例をダウンロードし、そのCSVエクスポートをトレースし、一つの変更された入力を確認してください。" -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "ガイド付きの例を試してください" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "もっと詳しく知りたい?" @@ -6484,7 +6492,7 @@ msgstr "もっと詳しく知りたい?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6503,13 +6511,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}プロンプトの例·ウェブサイト" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "はい、これ。" @@ -6522,7 +6530,7 @@ msgstr "はい、これ。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6535,7 +6543,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}例プロンプト·ゲームの #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6548,69 +6556,69 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}DX-Ballのケーススタディを見る→{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "設定と分析の手順については、ターゲットを選択します:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "マシンコードプログラム" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" " and libraries." msgstr "実行可能ファイルおよびライブラリ内の関数、文字列、参照、および関数呼び出しの関係を検査します。" -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "機械コードの解析プログラムガイド" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " "or ASAR archive." msgstr "アプリケーションフォルダまたはASARアーカイブからモジュール、ルート、IPCおよびネイティブ依存関係をマップします。" -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "アプリケーションワークフロー" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "ブラウザとランタイムアクティビティ" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " "across runs." msgstr "選択したブラウザまたはプロセスアクティビティをキャプチャし、実行間で結果を比較します。" -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "ブラウザ観察ガイド" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "質問がありますか?" @@ -6621,7 +6629,7 @@ msgstr "質問がありますか?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6631,12 +6639,12 @@ msgstr "" "{ph0}よくある質問を読む{ph1}, {ph2}Discordで私たちとチャット {ph3}、または {ph4}GitHubの問題を開く{ph5} " "バグや機能要求のために。" -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "コミュニティに参加" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -6657,64 +6665,64 @@ msgstr "" "コーディングエージェントを使用して、アプリ、バイナリ、ブラウザの動作をリバースエンジニアリングします。 " "明確なガイドに従って、REAを使用してインタラクティブな例を試してください。" -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "コピー REAインストールプロンプト" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Copy setupコマンド" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "手動計算機の分析に従ってください" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "コピー電卓パーセントの質問" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "恐竜ミニゲーム。 ゲームがフォーカスされている間にジャンプボタンを使用するか、スペースを押します。" -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "コピー恐竜解析プロンプト" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "計算を選択する" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "コピー電卓分析プロンプト" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "ウェブサイトプロジェクトプロンプトをコピーする" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "コピーゲーム再構築プロンプト" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -6723,42 +6731,42 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}ホーム{ph1} / {ph2}展示会のご案内{ph3} /アンドロイド" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "ケーススタディ·Aegis認証器" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "オーセンティケータはどのようにしていますか{ph0}ログインコードを生成しますか?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " "in an Android APK, then rebuild it with a clock you can control." msgstr "6桁のコードは30秒ごとに変更されます。 REAを使用してAndroid APKで計算を見つけ、制御できる時計で再構築します。" -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis3.4.3·アンドロイド·公式リリースAPK*6.9MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "AegisをGitHubに表示する" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "APKから再現できるコードへ" @@ -6769,7 +6777,7 @@ msgstr "APKから再現できるコードへ" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6786,7 +6794,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6803,7 +6811,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6814,14 +6822,14 @@ msgstr "" "{ph0}03*再構築とチェック{ph1}{ph2}クロックを変更します。 " "コードを見てください。{ph3}{ph4}新しいブラウザのデモでは、ルールを再現し、公開されている参照ケースと照合します。{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "このケーススタディでは" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -6829,7 +6837,7 @@ msgstr "{ph0}あなたの代理店に尋ねる{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -6837,7 +6845,7 @@ msgstr "{ph0}コードジェネレータを試してみてください{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -6845,7 +6853,7 @@ msgstr "{ph0}REAでコードを見つける {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -6853,7 +6861,7 @@ msgstr "{ph0}計算を読む{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -6861,20 +6869,20 @@ msgstr "{ph0}再構築を確認する{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}APKを自分で調べてください{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "あなたの代理店に尋ねる" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6891,21 +6899,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "コピー" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6914,14 +6922,14 @@ msgid "" msgstr "" "ダウンロードしたAPKのプロンプトの例で、REAのAndroid分析が構成されています。 {ph0}APKと解析セットアップを入手↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "コードジェネレータを試してみてください" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6932,33 +6940,33 @@ msgstr "" "アプリは時間を次のようにグループ化します {ph0}30秒のブロック。{ph1} ブロック番号とアカウントキーを組み合わせてコードを生成します。 " "同じキーとブロックは同じコードを生成します。" -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "時計を60秒に移動する" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "時間" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "秒" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "私達の調節可能な例の時計" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30秒ブロック" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "ブロック" @@ -6967,35 +6975,35 @@ msgstr "ブロック" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59秒{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "生成されたコード" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "アカウントキー+ブロック→6桁" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "時間の例(秒単位)" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59秒" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60秒" @@ -7004,7 +7012,7 @@ msgstr "60秒" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7015,7 +7023,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7024,25 +7032,25 @@ msgid "" msgstr "" "キーは固定されており、公開されています {ph0}RFC6238テストデータ{ph1}. このデモでは、APKから回収された計算を実装しています。" -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " "clock." msgstr "この図は、59秒での結果を示しています。 クロックを変更するには、JavaScriptを有効にします。" -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "REAでコードを見つける" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "APKを3つのクラスに絞り込みます" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7051,14 +7059,14 @@ msgid "" msgstr "" "{ph0} 他の2つは、プログレスバーとインポートされたアカウントに関するものです。 TOTPは、時間ベースのワンタイムパスワードを意味します。" -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "ジェネレータをアプリのディスプレイに接続します" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7068,7 +7076,7 @@ msgstr "" "REAはタイムスタンプオーバーロードを識別し、基本メソッドの呼び出し元を検索します。 検査 {ph0} 次に、表示呼び出しを表示します {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7076,14 +7084,14 @@ msgid "" "{ph0} prefix." msgstr "要求には、入力パスが短縮されて表示されます。 結果クラス名は共通を省略します {ph0} プレフィクス..." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "計算を読む" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7096,7 +7104,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7104,7 +7112,7 @@ msgstr "{ph0}01{ph1} タイムブロック" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7112,7 +7120,7 @@ msgstr "{ph0}02{ph1} キー+ブロック" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7120,7 +7128,7 @@ msgstr "{ph0}03{ph1} 六桁" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7130,7 +7138,7 @@ msgstr "{ph0}時間はブロックを選択します。{ph1} 秒30から59まで #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7143,7 +7151,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7157,7 +7165,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7167,7 +7175,7 @@ msgstr "" "いくつかの検査方法からの抜粋、表示のためのラインラッピング。 右のパネルは説明的な要約です。 {ph0} " "AegisコードはGPL-3.0です。{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "発電機の中" @@ -7176,7 +7184,7 @@ msgstr "発電機の中" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7185,7 +7193,7 @@ msgid "" msgstr "" "リリースされたAPKは {ph0} で {ph1}. REAはからの呼び出しに従います {ph2} 元のソースはヘルパーを呼び出します {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7200,20 +7208,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}一致するリリースソースとの比較{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "再構築を確認する" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7224,29 +7232,29 @@ msgstr "" "選択したREA-返されたJavaメソッドを小さなテストプログラムで組み立てました。 彼らの出力は、上の独立した再構成に一致しました " "{ph0}133件のテストケース{ph1}、タイムブロック境界とゼロで始まるコードを含みます。" -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "時間例" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "6桁のコード" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30秒" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109秒" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7256,38 +7264,38 @@ msgstr "" "ジェネレータは、公開されている六つのSHA-1リファレンスケースにも一致します {ph0}6238{ph1}. " "それらに対するブラウザの実装を確認してください:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "参照チェックの実行" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "デモの計算を読む" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" "digit results." msgstr "参照ケースは8桁を使用します。 このチェックでは、6桁の結果も確認されます。" -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " "was inspected statically." msgstr "検証は、抽出されたJavaメソッドと新しいデモを実行します。 Android APKは静的に検査されました。" -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "APKを自分で調べてください" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7299,7 +7307,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7309,18 +7317,18 @@ msgstr "" "Android analysisには完全なJDK17以降が必要です。 で選択します。 {ph0} または {ph1}. " "このケースはJDK21を使用していました。" -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "プロバイダーファイルでREAをポイントし、APKを検査します :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS/Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7332,7 +7340,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7340,7 +7348,7 @@ msgid "" "different time interval?{ph1}" msgstr "次の質問: {ph0}アカウントが8桁または異なる時間間隔を使用するとどうなりますか?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "ソース" @@ -7356,7 +7364,7 @@ msgstr "ソース" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7369,13 +7377,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}RFC6238参照ケース{ph1} · {ph2}デモテストデータ{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7397,37 +7405,37 @@ msgid "" "calculation and try a reconstruction with an adjustable clock." msgstr "Aegis Android APKをREAで検査し、その六桁のログインコード計算を回復し、調整可能なクロックで再構築を試してください。" -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APKケーススタディ" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "コピー Aegisプロンプトの例" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "ログインコードの計算に従ってください" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "コピー APK検査コマンド" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -7436,26 +7444,26 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}ホーム{ph1} / {ph2}展示会のご案内{ph3} /CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "ケーススタディ·DownUnderCTF2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "で旗を見つける{ph0}CTFバイナリ。" #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7463,17 +7471,17 @@ msgid "" "find an input that makes the original program print {ph0}." msgstr "REAを使用して、小さなフラグチェッカーを検査し、そのルールを方程式に変換し、元のプログラムを印刷する入力を見つけます {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "マスクされた正方形の旗チェッカー*簡単·Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "オリジナルのチャレンジを見る" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "バイナリからチェックされた答えへ" @@ -7484,7 +7492,7 @@ msgstr "バイナリからチェックされた答えへ" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7501,7 +7509,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7518,7 +7526,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7529,20 +7537,20 @@ msgstr "" "{ph0}03*解決して実行する{ph1}{ph2}回収フラグ→正解!{ph3}{ph4}Pythonスクリプトは方程式を解きます。 " "REAは、結果を受け入れる元のプログラムをキャプチャします。{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "課題はjosephによるもので、DownUnderCTFの公式リポジトリに掲載されています。" -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "このケーススタディでは" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7550,7 +7558,7 @@ msgstr "{ph0}チェックコードを見つける{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7558,7 +7566,7 @@ msgstr "{ph0}1つのマスクを読む{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7566,7 +7574,7 @@ msgstr "{ph0}読み取り可能なコードへのアセンブリ{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7574,7 +7582,7 @@ msgstr "{ph0}方程式を解く{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7582,20 +7590,20 @@ msgstr "{ph0}答えを確認してください{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}自分で試してみてください{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "チェックコードを見つける" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7613,17 +7621,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "コピー" @@ -7634,7 +7642,7 @@ msgstr "コピー" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7645,33 +7653,33 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用してms_flag_checkerを分析し、フラグを見つけます。 " "チェックがどのように機能するかを説明し、元のプログラムで答えを確認します。{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " "native analysis provider connected." msgstr "ローカルで利用可能なダウンロードされたチャレンジと接続されているマシンコードのプログラムプロバイダーの分析との例のプロンプト、。" -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "その機能に入力プロンプトに従ってください" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " "executable's original function names have been removed." msgstr "この参照は、実行可能ファイルの元の関数名が削除されていても、エージェントに調査する場所を提供します。" -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "チェッカーとその2つのヘルパーを読む" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7682,19 +7690,19 @@ msgstr "" "最初のループは36文字コードをコピーします。 チェックループはマスクをデコードし、選択したコードを合計し、結果を格納された番号と比較します。 その " "{ph0}-バイト-ステップ-アクロス {ph1} バイトは26個のマスクを与えます。" -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " "is shortened for display; addresses refer to REA's imported image." msgstr "これらは、新鮮なREA分析から選択された結果です。 アドレスはREAのインポートされたイメージを参照します。" -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "一つのチェックは、一つの文字を明らかに" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -7706,13 +7714,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "7番目のチェックでは、1つの位置のみが選択されます。 {ph0}オープンフィギュア{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "バイナリからマスクとそのターゲットを読み取ります" @@ -7721,7 +7729,7 @@ msgstr "バイナリからマスクとそのターゲットを読み取ります #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7732,12 +7740,12 @@ msgstr "" "命令 {ph0} マスクバイトを符号付き値として読み取ります。 これが理由です {ph1} -21を意味します。 " "ターゲットはリトルエンディアンの整数です。 一緒に、これらのバイトはエージェントに次のことを伝えます {ph2}、その文字は {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "指示から読み取り可能なチェックまで" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -7746,7 +7754,7 @@ msgstr "加算ヘルパーとその呼び出し元をCの同じルールに接 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -7754,7 +7762,7 @@ msgstr "{ph0}01{ph1} スタート" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -7762,7 +7770,7 @@ msgstr "{ph0}02{ph1} 選択" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -7770,7 +7778,7 @@ msgstr "{ph0}03{ph1} 追加" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -7778,18 +7786,18 @@ msgstr "{ph0}04{ph1} アドバンス" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} 比較" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA*選択されたオリジナルの指示" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "読み取り可能なC*ワンチェックの概要" @@ -7797,7 +7805,7 @@ msgstr "読み取り可能なC*ワンチェックの概要" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -7805,7 +7813,7 @@ msgstr "{ph0}01*ゼロから開始します。{ph1} {ph2} 実行中の合計を #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7815,7 +7823,7 @@ msgstr "{ph0}02*マスクセルを確認します。{ph1} ゼロ値は文字を #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7825,7 +7833,7 @@ msgstr "{ph0}03*文字コードを追加します。{ph1} 同じオフセット #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7837,7 +7845,7 @@ msgstr "{ph0}04*次のセルに移動します。{ph1} 元のループは整数 #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7846,19 +7854,19 @@ msgid "" msgstr "" "{ph0}05*保存されたターゲットと比較します。{ph1} 呼び出し元は、合計を受信します {ph2}. ミスマッチがジャンプします {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " "explanatory summary with descriptive names and a flattened 36-cell loop." msgstr "命令は、加算ヘルパーとその呼び出し元から来ています。 Cは、説明的な名前と平坦化された36セルループを持つ説明的な要約です。" -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "26の方程式を解く" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -7868,13 +7876,13 @@ msgstr "" "ほとんどのマスクは複数のセルを選択します。 たとえば、最初のチェックでは16個の文字コードが追加され、合計1441個が必要です。 " "重複する選択は、小さなPythonスクリプトが一緒に解くことができる方程式を与えます。" -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python*ソルバーの抜粋" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7886,19 +7894,19 @@ msgstr "" "Z3は、これらの方程式を満たす値を見つけるソルバーです。 この抜粋は、抽出されたチェックを使用し、aを前提としています {ph0} " "文字、数字、アンダースコアと中括弧を持つフラグ。 完全なダウンロードには、26個のマスクとターゲットすべてが含まれています。" -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "完全なソルバーをダウンロードする" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "元のプログラムで答えを確認してください" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7909,59 +7917,59 @@ msgstr "" "REAのプロセスキャプチャは、解決されたフラグを受け入れる元の実行可能ファイルを記録します。 から選択した文字を変更する {ph0} に {ph1} " "最初の合計を1441ではなく1440にし、プログラムはそれを拒否します。" -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "入力" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "観測された出力" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "終了コード" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "ソルバーの旗" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "一つの文字が変更されました" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "回収されたフラグとキャプチャされた出力を表示する" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA•オリジナルプログラム出力" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "フラグのコピー" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " "challenge metadata, checked after solving the binary." msgstr "回復された値は、バイナリを解決した後にチェックされた、主催者の公開されたチャレンジメタデータのフラグとも一致します。" -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "ソース、ターゲットの識別情報および分析の詳細" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -7971,7 +7979,7 @@ msgstr "" "2026年10月8日に、REA4.1.0とGhidra12.1.4をLinux x64で使用して、新鮮な分析と2つのプロセスキャプチャを行いました。 " "バイナリは削除されたx86-64ELF、15,248バイトです。" -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -7993,7 +8001,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8002,12 +8010,12 @@ msgid "" msgstr "" "{ph0}主催者のソースと比較する{ph1} · {ph2}チャレンジメタデータとフラグ{ph3} · {ph4} REA証拠ノート{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "自分で試してみてください" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8015,13 +8023,13 @@ msgid "" msgstr "" "元のチャレンジとソルバーを1つのフォルダにダウンロードします。 上記のプロンプトを使用してエージェントに調査するか、含まれているスクリプトを実行します。" -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "ターミナル*解決して実行" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8032,7 +8040,7 @@ msgstr "" "スクリプトは候補フラグを出力します。プログラムのプロンプトに貼り付けます。 ニーズを解決するPythonと {ph0}. " "元の実行可能ファイルを実行するには、Linux x86-64が必要です。" -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "コーディングエージェントでREAをセットアップする" @@ -8052,27 +8060,27 @@ msgstr "" "REAを使用して、DownUnderCTFのマスクされた正方形のフラグチェッカーを解決します。 " "チェック機能を見つけ、マスクを抽出し、復元されたフラグを元のプログラムと比較します。" -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTFフラグチェッカーのケーススタディ" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "CTFの例をコピーするプロンプト" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "CTFマスク方程式;小さな画面で水平にスクロール" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8082,42 +8090,42 @@ msgstr "" "第七のマスクは、21個のセルをスキップし、位置21を選択し、次に14をスキップします。 そのセルだけが合計に貢献します。 " "必要な文字コードは55で、文字が7であることを意味します。" -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "CTFチェックに従ってください" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "CTFアセンブリのコピー" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "読み取り可能なCTFチェックのコピー" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "CTFソルバーの抜粋をコピー" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "回収フラグのコピー" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "CTFソルバーコマンドのコピー" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -8126,39 +8134,39 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}ホーム{ph1} / {ph2}展示会のご案内{ph3} /DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "ケーススタディ•DX-Ball1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "DX-Ballの再構築 {ph0}その実行可能ファイルから。" -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" " agent inspect the original, one function at a time." msgstr "目標は、1996年のWindowsゲームの保守可能なCバージョンです。 REAは、エージェントが元の機能を一度に検査するのに役立ちます。" -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386*C·REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8169,14 +8177,14 @@ msgstr "" "実行可能ファイルからチェックされたC.REAまでの一つの関数は、命令、呼び出し元、およびデータ読み取りを提供します。 " "{ph0}オープンフィギュア{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "このケーススタディでは" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8184,7 +8192,7 @@ msgstr "{ph0}プロジェクト{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8192,7 +8200,7 @@ msgstr "{ph0}サウンドパン{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8200,23 +8208,23 @@ msgstr "{ph0}結果の確認{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}仕事を続ける{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "維持されたC関数" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "元のコードとの比較" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "コンパイルされたバイトに一致する関数" @@ -8227,7 +8235,7 @@ msgstr "コンパイルされたバイトに一致する関数" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8235,12 +8243,12 @@ msgid "" "coverage{ph3}" msgstr "プロジェクトチェックポイント:2026年10月7日。 {ph0}進捗台帳{ph1} · {ph2}テストカバレッジ{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "これまでのプロジェクト" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8253,12 +8261,12 @@ msgstr "" "現在のビルドには、検査ユーティリティと分析ライブラリが用意されています。 " "プレイ可能なゲームの作業は、ボールとパドルの物理学、パワーアップハンドリングとWindowsの統合を続けています。" -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "左/右の音の位置の計算を見つける" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8275,17 +8283,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "コピー" @@ -8296,7 +8304,7 @@ msgstr "コピー" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8306,7 +8314,7 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用して、DX-Ballがステレオサウンドの位置を計算する方法を見つけます。 " "計算を説明し、コードを表示します。{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8316,7 +8324,7 @@ msgstr "" "ローカルの実行可能ファイルを使用して、コーディングエージェントのプロンプトの例を示します。 " "以下の調査は、REAクエリと答えの背後にある証拠を示しています。" -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8329,7 +8337,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8341,30 +8349,30 @@ msgstr "" "の最初の関数の結果 {ph0} 擬似コード宣言が含まれています {ph1} と呼び出し {ph2}. " "その命令ビューは、スタック入力と浮動小数点演算を示しました。 その不一致は、エージェントに調査を続ける具体的な理由を与えました。" -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "最初の逆コンパイラビュー" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " "the input and the calculation feeding that call." msgstr "出力に変換呼び出しが表示されます。 以下の手順を読むと、入力とその呼び出しを供給する計算が明らかになります。" -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "REAを通じて答えた三つの質問" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "不足している入力を回復する" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8373,14 +8381,14 @@ msgid "" msgstr "" "関数の結果には、擬似コードと呼び出し元と一緒に命令が含まれます。 ここに, {ph0} 逆コンパイラビューから欠落している整数入力を公開します。" -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "入力を理解するために発信者に従ってください" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8390,24 +8398,24 @@ msgstr "" "REAは、最初の結果でこの呼び出し元を識別しました。 その前の指示はスケールします {ph0} 30で、20を追加すると、レンガの画面座標が得られます," " {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "メモリアドレスの背後にある値を読み取る" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " "scale. The agent now has the values needed for the C expression." msgstr "返されるバイトは、2つの算術定数と初期パンスケールを確立します。 エージェントは、C式に必要な値を持つようになりました。" -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "REAの調査結果からCへ" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8416,7 +8424,7 @@ msgstr "以下の5つの手順に従ってください。 各選択は、元の #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8424,7 +8432,7 @@ msgstr "{ph0}01{ph1} 入力" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8432,7 +8440,7 @@ msgstr "{ph0}02{ph1} 乗算" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8440,7 +8448,7 @@ msgstr "{ph0}03{ph1} 減算" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8448,18 +8456,18 @@ msgstr "{ph0}04{ph1} スケール" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} 戻る" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "オリジナルx86*抜粋" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "再構築されたC" @@ -8469,7 +8477,7 @@ msgstr "再構築されたC" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8487,7 +8495,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8503,7 +8511,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8520,7 +8528,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8536,7 +8544,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8547,7 +8555,7 @@ msgstr "" "{ph0}05*整数を返します。{ph1} での呼び出し {ph2} リーチ {ph3}、REAの呼び出し先の結果で識別されます。 " "Cは結果を次のようにキャストします {ph4};original-x86比較は戻り値をチェックします。" -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -8557,23 +8565,23 @@ msgstr "" "アセンブリの抜粋では、入力命令、算術命令、および戻り命令が選択されます。 " "以下の完全なリストには、介入する店舗と機能のセットアップとクリーンアップも含まれています。" -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "完全なアセンブリおよび支持の証拠" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA結果·0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "発信者が供給するもの" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8581,54 +8589,54 @@ msgid "" "then pushes it before the call:" msgstr "でのブリックヒット機能 {ph0} タイル座標を30でスケーリングし、20を加算してから、呼び出しの前にプッシュします:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "データが読み取るものが確立するもの" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REAバイト読み取り、リトルエンディアン倍精度としてデコード" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "住所" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "値" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "のために使用される" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "最初の乗算" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "引き算" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} 最初は" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "保存されたパンスケール" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -8642,7 +8650,7 @@ msgstr "ハッシュピン付きDX-Ball1.07ターゲット用にREA4.1.0で記 #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8650,24 +8658,24 @@ msgid "" "references{ph3}" msgstr "{ph0}維持されたソース{ph1} · {ph2}調査ノートおよび証拠の参照{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "復元された機能を確認する" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " "original, and its compiled bytes match the executable." msgstr "復元された関数は、戻り値が元のものと一致し、コンパイルされたバイトが実行可能ファイルと一致するという2つのチェックを渡します。" -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3,205件" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -8676,12 +8684,12 @@ msgid "" msgstr "" "テストでは、元のx86関数を実行し、その戻り値を維持されたCと比較します。0、0.5、1、20、-1の5つのパンスケールで、0から640までのすべての整数位置をカバーします。" -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63一致するバイト" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -8691,7 +8699,7 @@ msgstr "" "C関数は、ピン留めされたVC4.0ツールチェーンでコンパイルされます。 " "コンパイラの再生は、レビューされた再配置を適用し、参照された定数を確認した後、完全な関数と一致します。" -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -8705,18 +8713,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}コンパイラのリプレイの詳細を読む{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "調査を続ける" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -8725,7 +8733,7 @@ msgid "" msgstr "" "パーティクルの更新、爆発キュー、ボーナスの生成にも同じアプローチが使用されています。関連する関数を検査し、それらの状態と依存関係を回復し、実装を元のものと比較します。" -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -8733,7 +8741,7 @@ msgid "" msgstr "" "サウンドパン機能を自分で検査するには、DX-Ballプロジェクトのセットアップ手順に従って、一致する元のターゲットを指定します。 次に実行します:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "DX-Ballチェックアウトで" @@ -8742,7 +8750,7 @@ msgstr "DX-Ballチェックアウトで" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8754,7 +8762,7 @@ msgstr "{ph0} DX-Ballリポジトリ{ph1}{ph2}現在のソース、進行状況 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8768,7 +8776,7 @@ msgstr "{ph0} REA分析ワークフロー{ph1}{ph2}計算に従ってから、 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8789,13 +8797,13 @@ msgid "" msgstr "" "バイナリ解析からDX-Ball再構成をREAまで、維持されたC、元の-x86テスト、およびコンパイルされた関数バイトのマッチングに従ってください。" -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ballサウンドパン調査;小さな画面で水平にスクロール" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -8808,87 +8816,87 @@ msgstr "" "命令はxをロードし、1.5625を乗算し、500.0を減算し、pan_scaleを適用して整数を返します。 " "維持されているCは、元のx86に対して3,205ケースで独立してチェックされ、VC4.0コンパイラによって63バイトに一致します。" -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball再構築ケーススタディ" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "プロンプトの例をコピーする" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "左/右の音の位置の計算に従ってください" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "元のアセンブリの抜粋をコピーする" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "コピー音-パン機能" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "完全な音パンアセンブリをコピーします。" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Copy DX-Ball解析コマンド" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}ホーム{ph1} /ショーケース" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REAケーススタディ." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" " results." msgstr "アンドロイド、ゲーム、ElectronとCTFの挑戦、コード、数字とチェックされた結果と。" -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "アンドロイド*APK分析" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "認証者がログインコードを生成する方法" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -8898,22 +8906,22 @@ msgstr "" "リリースされたAPKでAegisの6桁のコード計算を見つけます。 " "REAを使用して生成メソッドをトレースし、デモクロックを移動して、コードが30秒ごとに変更される理由を確認します。" -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Androidのケーススタディを読む" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF•マシンコードプログラムの分析" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "CTFフラグチェッカーを解決する" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -8923,22 +8931,22 @@ msgstr "" "REAで簡単なダウンアンダーの挑戦を点検します。 " "そのチェック機能を見つけ、マスクと合計を方程式に変換してから、元のプログラムで解決されたフラグを確認します。" -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "CTFのケーススタディを読む" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "ネイティブ-リコンストラクション" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ballの左/右の音の位置の計算" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -8948,22 +8956,22 @@ msgstr "" "1996年のWindowsゲームから左/右の音の位置の計算を回復します。 " "REAの命令、呼び出し元の参照、数値定数は小さなC関数につながり、元の動作と63のコンパイルされたすべてのバイトに対してチェックされます。" -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "DX-Ballのケーススタディを読む" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron•機能トレース" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "NotionがテキストとHTMLをどのようにコピーするか" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -8973,22 +8981,22 @@ msgstr "" "Notionのパッケージ化されたJavaScriptを介してページに面したAPIをトレースします。 " "そのIPCラッパーに従ってシステムクリップボードに移動し、小さなHTMLマーカーが豊富なブロックデータをコピーに接続する方法を確認します。" -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Notionのケーススタディを読む" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS*再構成" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "どのようにTH04は弾丸のリングを目指していますか" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -8998,17 +9006,17 @@ msgstr "" "REAを使用して元の16ビット角度ヘルパーを検査します。 " "その乗算、除算、座標演算を読み取り可能なC++に一致させ、プレイヤーに向けたリングをどのように生成するかを確認します。" -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "TH04のケーススタディを読む" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "ステップバイステップガイド" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9017,7 +9025,7 @@ msgstr "" "ガイドは、ネイティブ計算、Electronエクスポート、およびブラウザ要求を順を追って説明します。 " "それぞれがプロンプトと具体的なターゲットで始まります。" -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "ガイドを読む" @@ -9036,12 +9044,12 @@ msgstr "" "コード、数字、デモを通じてREA調査に従ってください:Android認証器、DX-" "Ball、Notion、TH04、およびDownUnderCTFフラグチェッカー。" -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -9050,25 +9058,25 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}ホーム{ph1} / {ph2}展示会のご案内{ph3} /Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "ケーススタディ·Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "どのようにNotionコピー{ph0}テキストとHTML。" -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9076,12 +9084,12 @@ msgid "" msgstr "" "NotionのページAPIから、プリロードとメインプロセスを介してElectronのクリップボードライターにクリップボード呼び出しをトレースします。" -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notionデスクトップ7.6.1·JavaScript*REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Notionのデスクトップパッケージ内のブリッジ" @@ -9093,7 +9101,7 @@ msgstr "Notionのデスクトップパッケージ内のブリッジ" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9109,7 +9117,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9125,7 +9133,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9141,7 +9149,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9152,13 +9160,13 @@ msgstr "" "Electronは、指定されたテキストとHTMLを書き込みます。{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "一つのチャネルは、二つの側面を結合します: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9167,14 +9175,14 @@ msgstr "" "パッケージ化されたコードは、プリロードプロセスとメインプロセスで同じチャネルを使用します。 " "ラッパーを解決すると、これらの名前の背後にあるElectron呼び出しが明らかになります。" -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "このケーススタディでは" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9182,7 +9190,7 @@ msgstr "{ph0}クリップボードブリッジに従ってください{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9190,19 +9198,19 @@ msgstr "{ph0}ブロックの構造を維持する{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}より多くの例とソース{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "コピー操作はどこに行きますか?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9221,17 +9229,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "コピー" @@ -9242,7 +9250,7 @@ msgstr "コピー" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9252,19 +9260,19 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用して、NotionがテキストとHTMLをシステムクリップボードにコピーする方法を追跡します。 " "各ステップでコードを表示します。{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " "coding agent." msgstr "コーディングエージェントが使用できるNotionのローカルアプリケーションパッケージを使用した例のプロンプト。" -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REAは、読み取りを開始する場所を検索します" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9274,13 +9282,13 @@ msgstr "" "REAを使用してタブプリロードを分析すると、ページに公開されているAPIとIPC要求を送信する呼び出しが検索されます。 " "どちらの調査結果も、縮小されたバンドルのソース範囲が付属しています:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA調査結果→二つの場所を開く" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9293,7 +9301,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9305,25 +9313,25 @@ msgstr "" "エージェントはこれらの場所を開き、組み立てられたAPIでclipboardメンバーを見つけて、次のように {ph0}. そのコールサイトの供給 " "{ph1}. この名前は、エージェントにメインバンドルで探すための正確な何かを与えます。 以下の4つの抜粋は、それが接続するルートを示しています。" -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "コードの4つの短い部分" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " "Unrelated members are omitted." msgstr "パッケージ化されたJavaScriptから簡略化され、可読な変数名が付いています。 無関係なメンバーは省略されます。" -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "ページに公開されているAPIから開始します" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9331,13 +9339,13 @@ msgid "" "how the request leaves the page's process." msgstr "このメンバーは、チャネル名を指定します。 の実装 {ph0} リクエストがページのプロセスからどのように離れるかを示します。" -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "プリロードのラッパーを解決する" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9346,14 +9354,14 @@ msgid "" msgstr "" "返された関数は、Electronの要求と応答IPCを介して引数を転送します。 私たちは今、探すことができます {ph0} メインプロセス側。" -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "受信機の登録方法を確認する" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9361,12 +9369,12 @@ msgid "" "receiver for that channel." msgstr "メインプロセスは別のラッパーを使用します。 その {ph0} メソッドを登録します。 {ph1} そのチャンネルの受信機。" -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "書き込みとその送信者チェックを見つけます" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9376,13 +9384,13 @@ msgstr "" "これが目的地です。 送信者を確認した後、ハンドラーは提供されたデータをElectronのクリップボードAPIに渡します。 " "チャネルと2つの解決されたラッパーは、公開されたメソッドをこの呼び出しに接続します。" -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "コピーされたブロックはどのようにその構造を保持しますか?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9392,81 +9400,81 @@ msgstr "" "Notionのwebエディタは、テキストとHTMLを介して送信します {ph0}. " "ブロックデータをローカルに保持し、コピーされたHTMLにIDを入れて接続します。" -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "保存されたブロックデータへのHTMLリンク" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "HTML IDを読み取る" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "同じローカルIDを検索する" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Notionブロックデータの復元" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " "when IDs match; a stale entry returns only text and HTML." msgstr "例示的なテキストとID。 記録されたモジュールテストでは、Idが一致するとブロックデータが復元されます。" -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." " Matching IDs restore the block data." msgstr "貼り付け時に、NotionはHTML IDを探し、保存されたコピーと照合します。 一致するIdは、ブロックデータを復元します。" -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "2026年7月13日にキャッシュされたwebアセットから記録されたクリップボード形式。" -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "より多くの例とソース" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "別の例:Markdownテーブル" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " "becomes header and data rows." msgstr "NotionはMarkdownをブロックデータに解析します。 この例では、テーブルがヘッダー行とデータ行になる方法を示します。" -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "NotionのMarkdownパーサーを介したテーブル" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " "and cells." msgstr "抽出されたMarkdownパーサーからの出力を記録しました。 テーブルは行とセルになります。" -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "別のパス:オフラインSQLite接続" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9479,7 +9487,7 @@ msgstr "" "メインプロセスはメッセージチャネルを作成し、1つのポートをレンダラーに、もう1つのポートをSQLiteユーティリティプロセスに提供します。 " "後続のステートメントのバッチと結果は、そのポート上を移動します。" -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -9487,7 +9495,7 @@ msgid "" msgstr "" "このハンドオフに続いて、データベース作業がどこで実行されるか、および最初のIPC要求のみをトレースすると後の会話が失敗する理由を説明します。" -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "出典と抜粋の読み方" @@ -9495,7 +9503,7 @@ msgstr "出典と抜粋の読み方" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9512,7 +9520,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9526,7 +9534,7 @@ msgstr "" "{ph1}, {ph2} と {ph3}. これらのアセットには独自のバージョンがあります。 " "保存されたプローブは、抽出されたモジュールと小さなハーネスを実行しました。" -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -9538,7 +9546,7 @@ msgstr "" "これは、APIを検索し、操作を呼び出します。 クリップボードメンバーと一致する受信機は、パッケージ内のラッパー実装を読み取ることによって接続されます。" #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9555,7 +9563,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9569,7 +9577,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9591,52 +9599,52 @@ msgid "" msgstr "" "短いコードの抜粋とその豊富なクリップボード形式を見て、Electronのプリロード、IPCラッパーとメインプロセスを通じてNotionのクリップボードAPIに従ってください。" -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electronケーススタディ" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Notion分析プロンプトのコピー" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "コピー Notionプリロード抜粋" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "コピー Notion呼び出しラッパーの抜粋" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Notionハンドラーラッパーの抜粋をコピーする" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "コピー Notionクリップボードレシーバー抜粋" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "貼り付け時に豊富なクリップボードデータを復元する" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "ページ上部へ" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "コンテンツにスキップ" @@ -9645,42 +9653,42 @@ msgstr "コンテンツにスキップ" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}ホーム{ph1} / {ph2}展示会のご案内{ph3} /TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "ケーススタディ*東方4:蓮の国物語" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "TH04の再構築{ph0}弾丸のパターン。" -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " "the original DOS function, then follow its instructions into readable C++." msgstr "弾丸のリングは、短い角度の計算で始まります。 REAを使用して元のDOS関数を検査し、その指示に従って読み取り可能なC++に従います。" -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98*16ビットDOS·C++およびアセンブリ" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "TH04再構成を見る" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "元の指示からチェックされたソースへ" @@ -9691,7 +9699,7 @@ msgstr "元の指示からチェックされたソースへ" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9707,7 +9715,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9724,7 +9732,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9738,7 +9746,7 @@ msgstr "{ph0}03*C++を読む{ph1}{ph2}スペース→狙い→回転{ph3}{ph4} #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9748,21 +9756,21 @@ msgid "" msgstr "" "{ph0}04*ソースを確認する{ph1}{ph2}一致するバイト数2,139件{ph3}{ph4}記録されたコンパイラチェックは、このヘルパーを含む箇条書き生成コードをカバーします。{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " "supplies the maintained source and compiler checks." msgstr "REAは、元のコードとその分析証拠を返します。 TH04プロジェクトは、保守されたソースとコンパイラのチェックを提供します。" -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "このケーススタディでは" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -9770,7 +9778,7 @@ msgstr "{ph0}弾丸のリング{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -9778,7 +9786,7 @@ msgstr "{ph0}REAが返すもの{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -9786,7 +9794,7 @@ msgstr "{ph0}C++へのアセンブリ{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -9794,18 +9802,18 @@ msgstr "{ph0}ソースの確認{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}完全なプロジェクト{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "リングがプレーヤーをどのように狙うか" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -9823,16 +9831,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}あなたのコーディングエージェント" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "コピー" @@ -9843,7 +9851,7 @@ msgstr "コピー" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9853,7 +9861,7 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用して、TH04が弾丸のリングを作成し、プレイヤーにそれを向ける方法を見つけます。 " "計算を説明し、コードを表示します。{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -9861,7 +9869,7 @@ msgid "" msgstr "元の実行可能ファイルと再構築チェックアウトがローカルで利用可能なプロンプトの例。" #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9874,7 +9882,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9882,12 +9890,12 @@ msgid "" "40 and template rotation 0. {ph0}Open figure{ph1}" msgstr "カウント16、プレイヤーの方向40、およびテンプレートの回転0のための回収された角度の数学の図。 {ph0}オープンフィギュア{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "回収されたソース内の発射テンプレート" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "エリーのリングアタック·ソース抜粋" @@ -9896,7 +9904,7 @@ msgstr "エリーのリングアタック·ソース抜粋" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9904,13 +9912,13 @@ msgid "" "{ph0}Read the attack's source{ph1}." msgstr "これらの行は、難易度とパフォーマンスチューニングの前にパターンを選択します。 {ph0}攻撃のソースを読む{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "REAが返すもの" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9921,19 +9929,19 @@ msgstr "" "私達は点検します {ph0}、各弾丸の速度と角度を設定する関数。 REAは、その命令、擬似コード、および参照を返します。 " "その結果の3つの部分がパターンを説明しています。" -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "コードを読む前にDOSイメージを確認してください" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " "executable. The path above is shortened for display." msgstr "このチェックは、ロードされたコードと再配置レコードを提供された実行可能ファイルに関連付けます。 上記のパスは表示のために短縮されています。" -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "リングの乗算と除算を読む" @@ -9941,7 +9949,7 @@ msgstr "リングの乗算と除算を読む" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9952,12 +9960,12 @@ msgstr "" "{ph0} 箇条書きのインデックスを保持します。 シフトはそれに256を乗算し、除算はから読み取られたカウントを使用します {ph1}. " "そのフィールドに保持されているソース名 {ph2}. 完全なシーケンスが以下に表示されます。" -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "パターンがプレイヤーに向かって回転する場所を見つける" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -9968,12 +9976,12 @@ msgstr "" "命令オペランドは、2つの座標差と方向ヘルパーを公開します。 その戻り値は相対的なリング角度に追加されます。 " "REAは、エージェントがそれらの背後にある元の操作をチェックすることができます。" -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "アセンブリから読み取り可能なC++へ" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -9983,7 +9991,7 @@ msgstr "元の指示と角度の計算に一致するステップを選択しま #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -9991,7 +9999,7 @@ msgstr "{ph0}01{ph1} インデックス" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -9999,7 +10007,7 @@ msgstr "{ph0}02{ph1} スペース" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10007,7 +10015,7 @@ msgstr "{ph0}03{ph1} Aim" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10015,18 +10023,18 @@ msgstr "{ph0}04{ph1} 回転" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} 店舗" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA•オリジナルの16ビット命令" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "-----------" @@ -10034,7 +10042,7 @@ msgstr "-----------" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10048,7 +10056,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10062,7 +10070,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10076,7 +10084,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10090,7 +10098,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10102,7 +10110,7 @@ msgstr "" "{ph0}05*最終的な角度を1バイトに保ちます。{ph1} 店は書いています {ph2} spawn-angleフィールドに移動します。 " "値は、符号なしバイトのキャストと同じように、255の後に折り返します。 周囲のソースもこの角度と速度を速度に変換します。" -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10112,7 +10120,7 @@ msgstr "" "アセンブリは目的とされたリング枝、目的の計算および最終的な店を選ぶ。 上記のC++は読みやすい要約です。 " "以下のコンパイラチェックは、リンクされたプロジェクトの保守されたソースに適用されます。" -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "リングを読み、ソースを目指してください。" @@ -10129,7 +10137,7 @@ msgstr "リングを読み、ソースを目指してください。" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10137,12 +10145,12 @@ msgid "" "representation{ph5}" msgstr "{ph0}リングマクロ{ph1} · {ph2}目的および速度の源{ph3} · {ph4}角度表現{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "保守されたソースの確認" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10151,24 +10159,24 @@ msgstr "" "TH04プロジェクトの記録されたチェックは、このヘルパーを含む箇条書き生成コードを、固定されたTurbo " "C++4.0Jツールチェーンでコンパイルします。" -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "一致するバイト数2,139件" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " "original executable." msgstr "コンパイルされた箇条書き生成コードは、元の実行可能ファイルの2,139バイトのセクションに一致します。" -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "二つのクリーンビルド" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10179,65 +10187,65 @@ msgstr "2つの別々のビルドでは、同じ一致するバイトが生成 #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "2026年10月3日に録音されました。 {ph0}コンパイラチェックを読む{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "ターゲットidと分析範囲" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "元のターゲット" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}、156,258バイト、DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "ヘルパーエントリー" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} REAのロードされたイメージで" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "元のファイルオフセット" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}、によって返される {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "記録されたコード検査" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA4.1.0•2026年10月7日" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10247,7 +10255,7 @@ msgstr "" "彼らはまた、そのマップの貢献と重複した再配置を比較します。" #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10260,7 +10268,7 @@ msgstr "" "関数の結果は、517バイトのスパンにわたって2つの範囲で503のボディバイトを報告します。上記の選択された命令は、それらの報告された範囲にあります。" #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10273,7 +10281,7 @@ msgstr "" "ソース名とコンパイラチェックはTH04チェックポイントから来ています {ph0}. このページでは、同じ元のターゲットの新しいREA検査を追加します。 " "提供されたゲームのアイデンティティは、リポジトリマニフェストによって固定されており、独立した原始的なダンプの出所はまだ開いています。" -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10283,12 +10291,12 @@ msgstr "" "図は角度の計算を示しています。 " "完全なゲームコントロール、タイミング、およびPC-98ハードウェアの動作には、再構築プロジェクトで別々のランタイムチェックがあります。" -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "フルTH04の再構成" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10300,7 +10308,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10312,7 +10320,7 @@ msgstr "{ph0}TH04リポジトリを探索する{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10326,7 +10334,7 @@ msgstr "{ph0}箇条書き生成ソース{ph1}{ph2}完全なヘルパー、他の #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10341,7 +10349,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10364,28 +10372,28 @@ msgstr "" "TH04のREAの元の16ビットDOSコードを点検して下さい。 " "アセンブリと回収されたC++に従って、弾丸のリングがどのように間隔をあけてプレイヤーに向けられているかを確認します。" -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "このページでは" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04弾丸パターンのケーススタディ" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "コピー TH04プロンプトの例" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "TH04固定および目的とした弾丸リング;小さな画面で水平にスクロールします" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10397,27 +10405,27 @@ msgstr "" "40のプレイヤーの方向を追加すると、すべての方向が同じ量だけ回転します。強調表示された最初の箇条書きは、プレイヤーに向かって指します。 " "どちらも16角度単位、つまり22.5度の間隔を保ちます。" -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "コピー TH04発射テンプレート" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "TH04の目的としたリング計算に従ってください" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "コピー TH04アセンブリの抜粋" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "コピー読み取り可能な目的のリング計算" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "ページ上部へ" @@ -10525,14 +10533,14 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "固定速度: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" "game check when rounded to three decimals." msgstr "復元されたルールを再生しました。 4つの値はすべて、小数点以下3桁に丸められたときに制御されたオリジナルゲームのチェックと一致します。" -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -10885,591 +10893,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "同じ間隔:256÷16=16角度単位=22.5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "事例" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "ブログ" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "はじめる" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "ガイド" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "ソースコード" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "MIT ライセンス" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "コミュニティに参加" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "X でフォロー" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA*選択したスクリプトソース" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "ソースコード" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "期待されるフォーマッタ出力" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "説明書" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "発信者" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "定数" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "C関数" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "ボタン" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "プリロードAPI" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSVファイル" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "あなたのかちりと言う音" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "キャプチャリクエスト" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "エクスポートスクリプト" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA結果·概要。ipc抜粋" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA命令の抜粋·0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA発信者の抜粋*0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REAバイトの結果·リトルエンディアンの倍精度として解釈されます" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "回収されたC*抜粋" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "REA の使い方を見る ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "ショーケース→" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "検査されたスクリプトから選択された設定" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "%ハンドラーの読み取り可能な要約" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA*選択されたオリジナルの指示" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "オペレーター Id·Microsoftのソース" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Xの@reatoolsに従ってください" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "エージェント→REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA→エージェント*選択された結果" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA→エージェント*メソッドと呼び出し元" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA*選択された逆コンパイルされたJava" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "読みやすい要約*エージェントの解釈" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA*generateOTP、完全なボディ" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "ダウンロードAegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Android分析プロバイダーをダウンロード" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "エージェント→REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA→エージェント*選択された結果" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA→エージェント*選択された指示" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "エージェント→REA*read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA→エージェント·セブンスエントリ" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "オリジナルの実行可能ファイル·SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "オリジナルの挑戦をダウンロード" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "ソルバーをダウンロード" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA結果*擬似コードの抜粋" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "エージェント→REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA→エージェント*命令抜粋" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA→エージェント*発信者の抜粋" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "エージェント→REA·2 {ph0} ご要望-ご要望" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REAバイト結果*ダブルとしてデコード" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "あなた自身のターゲットから始めて下さい" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "コードの生成" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "回復されたルール" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "調節可能な時計" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "バイナリ" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "コードの確認" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "方程式" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "正解!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "実行可能ファイル" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA調査結果" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "回収されたC" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "検証" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "パッケージ化されたアプリ" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "公開されたAPI" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "IPCラッパー" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "クリップボード" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "元のDOSコード" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA命令" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "角度計算" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "弾丸リング" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "公開されたページAPI" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "レンダラIPCコール" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "システムのクリップボードに送信されます" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Notionによってローカルに保存されます" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "マークダウン入力" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "構造化パーサー出力*抜粋" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "独自のアプリを分析する" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "エージェント→REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA→エージェント·選択されたフィールド" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "エージェント→REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA→エージェント*命令抜粋" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "同じ機能結果-目安抜粋" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "対応c++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "リングマクロ·TH04ブランチ、抜粋" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "角度と速度·ソース抜粋" @@ -11501,7 +11517,7 @@ msgstr "翻訳が更新されています。 今のところ英語でこのペ #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11518,7 +11534,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11538,7 +11554,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11558,7 +11574,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11576,7 +11592,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11594,7 +11610,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11604,14 +11620,14 @@ msgstr "" "{ph0}›{ph1}{ph2}REAを使用して検査する {ph3}. 私のためにこのウェブサイトを複製します。{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "復興 · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11620,7 +11636,7 @@ msgid "" msgstr "と {ph0} と npm 利用可能で、セットアップを実行し、コーディングエージェントを選択し、提案された変更を確認します。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -11629,7 +11645,7 @@ msgstr "提供された例*{ph0}とnpm*コーディングエージェント" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11647,7 +11663,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -11661,7 +11677,7 @@ msgstr "{ph0}ページ · {ph1}{ph2}{ph3}ノートのエクスポート{ph4}{ph5 #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11678,7 +11694,7 @@ msgstr "{ph0}橋 · {ph1}{ph2}{ph3}{ph4}{ph5}{ph6}名前付きメッセージを #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11689,7 +11705,7 @@ msgstr "" "そして、ファイルを書き込みます。{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -11704,7 +11720,7 @@ msgstr "{ph0} *8-12行目" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11716,7 +11732,7 @@ msgstr "" "{ph5} それを確認する。 予測と実際の出力を表示します。{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11725,7 +11741,7 @@ msgid "" msgstr "タイトルは引用符で囲まれた1つのフィールドにとどまり、各引用符は2倍になります。 これはフォーマッタを直接チェックします {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -11733,7 +11749,7 @@ msgstr "{ph0} · CSV フォーマッタ" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11741,7 +11757,7 @@ msgid "" msgstr "あなたが必要になります {ph0} 22 (22.19+), 24 (24.11+) または26+。 npmはと来ます {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -11749,7 +11765,7 @@ msgstr "持っていない {ph0}、またはわからない?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11761,7 +11777,7 @@ msgstr "" "古いバージョンまたは\"認識されません\"/\"コマンドが見つかりません\"を印刷する場合は、インストールします {ph1} 24LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -11775,7 +11791,7 @@ msgstr "{ph0} ·ソースの抜粋の例" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -11784,9 +11800,9 @@ msgid "" msgstr "{ph0}例を開きます{ph1} · {ph2}ダウンロード {ph3}{ph4} · {ph5}ダウンロード {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -11794,7 +11810,7 @@ msgstr "{ph0} ·ソースの例" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -11808,7 +11824,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11820,7 +11836,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -11833,7 +11849,7 @@ msgstr "例えば:{ph0}なぜ電卓で {ph1} を計算すると 220 になる #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11844,7 +11860,7 @@ msgstr "" "220を与えますか?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -11853,7 +11869,7 @@ msgstr "REA·ロード {ph0} *選択した行" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11870,7 +11886,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11888,7 +11904,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -11900,28 +11916,28 @@ msgstr "" "秒ごとに変わる理由を説明し、時刻を変更できる小さなデモを作ってください。{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0}-APIメンバー" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0}*IPCヘルパー" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "メイン/{ph0} *ハンドラーヘルパー" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -11931,12 +11947,1203 @@ msgstr "メイン/{ph0} *クリップボード受信機" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "はじめる {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "ライトモードに切り替える" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "ダークモードに切り替える" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"HTTP リクエストとレスポンスの本文を調べるには、{ph0}Fiddler Everywhere:SAZ " +"キャプチャ、MCP、公開スキル{ph1}を利用してください。SAZ ??? HAR 1.2 をエクスポートすれば REA でオフラインのキャプチャ " +"Evidence を取得できます。また、Everywhere の MCP サーバーを接続して、エージェントと一緒に記録済みの通信を調べることもできます。" + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "モデルの特化{ph0}エッセイ" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "リバースエンジニアリングに、より大きなモデルは必要か?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "Touhou の再構築を通じて考える、汎用モデル、特化モデル、そしてコンパイラのフィードバックから学ぶ方法。" + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "N0zoM1z0 著 · 2026 年 10 月 13 日" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "コンテンツにスキップ" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}ホーム{ph1} / {ph2}ブログ{ph3} / モデルとリバース エンジニアリング" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "エッセイ" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "リバースエンジニアリングに、より大きなモデルは必要か?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "N0zoM1z0 著 · 2026 年 10 月 13 日" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "要点" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}モデルの能力によって、エージェントが見つけられる仮説は変わる。{ph1} 後の作業では、それまで解決できなかった問題が解決された。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}使い慣れたコンパイラには、特化モデルが学べる具体的なパターンがある。{ph1} " +"完全一致の中には、細かな、再利用可能なソースコードのパターンに依存するものもある。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}リポジトリに蓄積した知識も、公平に比較したい。{ph1} 小さなモデルでも、適切に知識を検索できれば、作業を進めるのに十分かもしれない。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}次の有用な実験を選ぶ力を学習させ、その検証器も確かめる。{ph1} フィードバックの価値は、検証器が実際に何を確認しているかで決まる。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}検証を通った再構築の成果を、時間とコストと合わせて評価する。{ph1} エージェントのワークフロー全体で測りたいのは、その結果だ。" + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "この記事の内容" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}強いモデルで何が変わったか{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}なぜ特化を考えるのか{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}その経験はどこに蓄積すべきか?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}次の有用な実験を選ぶ力を学ぶ{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}リバース エンジニアリングと強化学習{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}検証器が間違っていたら{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}実行する価値のある比較{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}どんなエージェントが必要なのか?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "強いモデルで何が変わったか" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"2026年8月から、プログラムにアクセスし、自分の作業を検証できるエージェントが、どこまでリバースエンジニアリングを進められるかを探ってきた。私の経験は主にゲーム、特に" +" Touhou(東方)の再構築から得たものだ。モデルを変えるたびに、各セッションで何を復元できたかがリポジトリに残った。" + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"その多くは完全一致を目指す再構築だ。バージョンを固定した当時のツールチェーンで、保守しているソースをコンパイルし、対象の関数を再現できるか確かめる。後のモデルが以前の行き詰まりを解消したとき、ソースの変更を見ると、何が進歩を可能にしたかがわかる。" + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "一時的な値を同時に有効にしておく必要があった" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"TH09 " +"のある攻撃関数は、ロジックの大部分が復元済みだった。それでも、コンパイラが一時的な結果を格納する方法は原版と違っていた。残る問題は、その結果がいつまで有効であるべきか、そして格納領域をいつ再利用できるかだった。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"いくつかの通常のソースコード配置をテストした後、{ph0}GPT-6-Sol セッション レコード{ph1} でこの不一致が報告されました。 " +"{ph2}GPT-6.1-Sol がこの問題を再度調査したとき{ph3}、これらの一時変数の存続期間に関する有用な仮説が提案されました。" + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"この関数は一時的な結果を作り、アニメーションの位置にコピーする。C++ " +"の一時的な結果は、それを使う式が終わるまで生存する。実際の処理を一つの式にまとめると、結果の生存期間が重なり、コンパイラはすべての結果に同じ格納領域を使い回せなくなる。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"一つの結果だけは、後の衝突判定に使う値と領域を共有していた。その値に独立した生存期間を与えると、最後の重なりも解消された。いくつかの絞り込んだ実験の後、{ph0}クリーンビルドで関数全体の一致が確認された{ph1}。" + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"発見とテストがどのように相互にサポートし合っていたのかに興味があります。一時オブジェクトの存続期間に関する仮説は、AI " +"エージェントに新しい方向性を与えました。コンパイラーからのフィードバックにより、その仮説を改良して、一致するソースコードの配置を実現することができました。" + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "別の制御フロー グラフ" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"2 番目の TH09 関数は、その新しい方向が重要である理由を示しています。ここでの障害は、複数のブランチが最終的な作業をどのように共有するかでした。 " +"{ph0}GPT-6.1-Sol の以前の作業{ph1} " +"では、関数の一部が一致していましたが、分岐の結合方法は依然としてオリジナルとは異なっていました。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra が周囲の制御フロー グラフを変更しました{ph1}。メイン " +"パスは共有された最終更新と復帰につながりました。そのソース構造では、コンパイラはオリジナルと同じ方法でブランチを結合しました。完全な関数は一致しており、{ph2}別のリビルド" +" チェックでそれが確認されました{ph3}。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}表現を変えたことで、より有望な探索空間が開けた。{ph1} " +"この二つの例から、汎用モデルの能力は重要だと感じる。エージェントは局所的な変更を長く試した末に、周囲の処理を表すもっとよい方法を見つけることがある。" + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"ただし、後のセッションは、それまでのソースと失敗の記録を引き継いでいる。その蓄積も有利に働いた。履歴から発見と検証の過程は調べられるが、モデルの効果と引き継いだ経験の効果を分けるには、条件をそろえた比較が必要だ。" + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"これが私にとってこの質問が興味深い理由です。新しい表現を見つけることである程度の進歩が得られました。残りの作業の多くには、使い慣れたコンパイラに対してさまざまなソース" +" " +"コードの配置をテストすることが含まれていました。このうちどの程度の範囲で幅広い推論能力が必要でしょうか?モデルはそのコンパイラーとコードを繰り返し操作することでどれだけ学習できるでしょうか?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "特化モデルがうまく働く可能性は?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou には、経験の蓄積が役立つと考える具体的な理由がある。多くのゲームコードを ZUN " +"一人が書いているため、繰り返し現れる書き方を最初の仮説にできる。実際、リポジトリには、似たループや補助関数の構成が別のゲームの仮説につながった例がある。" + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"コンパイラを含めると、これらのソース " +"パターンがより具体的になります。特定のバージョンとオプションのセットでは、ソースに小さな変更を加えると、マシンコードに再現性のある差異が生じる可能性があります。これらの違いの中には、驚くほどわかりにくいものもあります。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"たとえば、TH095 では、{ph0}ローカル変数の名前であっても、VC7.1 " +"がそれを格納する場所に影響を与える可能性があります{ph1}。その宣言を移動してもストレージ " +"レイアウトは解決されませんでした。ただし、以前のバックグラウンド関数では、コンパイラの選択に影響を与える名前付けパターンが明らかになっていました。これは、{ph2}{ph3}{ph4}" +" を再構築するためのより有望な仮説を示唆しました。" + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "そのパターンをファイルサイズの変数に使うと、格納領域を増やさずに必要な配置が得られた。続いて関数全体が一致した。" + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"これは非常に具体的な詳細であり、汎用 AI " +"モデルが最初に問題に遭遇したときには認識できない可能性があります。このコンパイラに特化したモデルは、そのようなケースを多数確認し、どのソース " +"コードのバリエーションが最初にテストする価値があるかを学習できます。" + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"動作を理解したうえで最後の差分を詰める場面では、この可能性が特にはっきりする。問うのは、このコンパイラがどの通常の書き方を観測された命令に変換するかだ。特化した学習によって候補を効率よく出せるかもしれないが、どの仮説が正しいかは対象のプログラムが決める。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"ただし、パターンには適用条件を残す必要がある。TH08 は TH095 や TH09 より古い Visual C++ を使う。TH04 は DOS " +"時代の別のコンパイラを使い、{ph0}プレイヤーのコードの再構築{ph1}では、書き方や実行ファイルへのリンク順序について別の仮説が必要だった。同じ作者であることは手がかりになるが、適用できるかは各対象で確かめる。その区別も特化モデルが学ぶべきことだ。" + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "その経験はどこに蓄積すべきか?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"モデルの学習でこうしたパターンを覚えさせる前に、まずリポジトリに保存している知識を見たい。{ph0}前のエッセイ{ph1}では、リポジトリがプロジェクトの作業記憶になっていると書いた。そこにはコンパイラから学んだことと、それを裏付けるソースや失敗した実験が残っている。" + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"そのレコードを取得することで、エージェントは既知の結果から開始し、どのようにしてその結果に到達したかを検査できます。また、同じコンテキストですでに失敗した代替案を回避することもできます。モデルのトレーニング済みパラメーターを変更することなく、開始点が改善されます。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"TH09 の敵生成関数を再構築した{ph0}GPT-6-Luna-max のセッション{ph1}は、TH08 " +"の関連するソースから仮説を得た。以前のコードが、ループの構成と失敗時の処理の手がかりになった。TH09 " +"自体の証拠でゲーム固有の細部を補い、クリーンビルドで関数全体の一致を確認した。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}「モデルがそのコンパイラの癖を知らない」と「知っていても使えない」は別の問題だ。{ph1} " +"検索で前者を解決できても、知識を有用な候補にするには能力がいる。候補が失敗すれば、その結果が次の試みに何を意味するかも判断しなければならない。関連するパターンを知るのは、出発点にすぎない。" + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"だから比較には、知識を適切に検索できる小さな汎用モデルも加えたい。同じ経験のライブラリを与えれば、学習が何を加えるかを調べられる。候補を作る力なのか、フィードバック後の判断なのか、それとも両方なのか。" + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "次の有用な実験を選ぶ力を学ぶ" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"私が最も研究したいのは、フィードバック後の判断だ。エージェントによる再構築では、モデルが説明を提案し、プログラムに照らして検証する。候補が失敗しても、可能性を絞り、次の有用な実験を考える材料になる。" + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"一時的な結果の例をもう一度考えてみましょう。最終的なソースには、機能した配置が示されていますが、そのソースへのルートにはさらに多くの情報が含まれています。以下の各実験は、まだ変更する必要があるものを特定するのに役立ちました。" + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "実験" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "その結果が私たちに教えてくれたこと" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "別の方法で結果をコピーしてみてください" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "コピーのコードは変わったが、関数にはまだ差分がある。" + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "戻り値を直接使用する" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "コピーは元のパターンに従いますが、一時ストレージは依然として異なります。" + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "一時的な結果を同時に有効にしておく" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "これらは別々のストレージを取得しますが、1 つは、後で衝突チェックに使用される値と依然として重複します。" + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "衝突判定の値を独立させる" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "ソースからクリーンに再コンパイルすると、完全に一致していることが確認されます。" + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "上記の攻撃関数の再構築から選択した実験を、教えられた内容ごとにグループ化しました。" + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"この順序を維持したトレーニング記録は、最終的なソースだけよりも多くのことを教えることができます。提案された各変更を観察された結果と次の決定に結び付けます。効果のないバリエーションを維持することも重要です。バリエーションは、後のエージェントに、そのコンテキストでどの仮説がすでにテストされているかを伝えます。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}モデルにはフィードバックの使い方を学んでほしい。{ph1} " +"結果が変わらなければ、その変更を考え直す理由になる。差分が変われば、別の原因が見えてくるかもしれない。局所的な編集から情報が得られなくなったら、全体の書き方を見直したり、証拠を再確認したりできるべきだ。" + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"これらの選択を行うことを学ぶには自主性が必要です。場合によっては、別の編集をコンパイルするのではなく、別の呼び出し元を検査することが次のステップとして役立つ場合があります。必要な書き換えを厳密に繰り返すと、モデルに学習させたい動作の一部とともに、その選択肢が削除されてしまいます。" + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "リバースエンジニアリングが強化学習にとって興味深い理由" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"範囲を定めた再構築は、こうした判断を研究するための実用的な環境になる。対象とコンパイラのバージョンを固定すれば、多くのソースの実験で素早く再現可能なフィードバックを得られる。エージェントは候補をコンパイルし、差分を調べ、次の行動を選べる。" + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"強化学習なら、得られたフィードバックからこの判断を学習できるかもしれない。定義された検証を通った候補は具体的な成果になり、試行の記録から、そこに至るまでの労力も調べられる。" + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"この方向を支える研究はすでにある。{ph0}LLM4Decompile{ph1}は逆コンパイルに特化したモデルを研究している。{ph2}AutoDecompiler{ph3}はコンパイルと実行のフィードバックを使って複数ターンの改善を学習する。両者が扱うのは機能の復元だ。私はそこを出発点に、当時のコンパイラの出力に一致するソースを探すという関連した課題を研究したい。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"ただし、このように明確に定義されたタスクに到達するには、まず関数が所有するリソースを確立するか、実行中のプログラムの状態や振る舞いを観測する新しい方法を考案する必要があるかもしれません。たとえば、TH08" +" " +"では、{ph0}衝突の違いにより、元のプログラムでの浮動小数点計算の処理方法が問題になりました{ph1}。エージェントが有用な補正をテストする前に、何を測定するかを決定する必要がありました。" + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"ここから、幅広い能力を持つモデルのもう一つの役割が見える。まず問題を検証可能にすることだ。検証方法ができて初めて、学習した探索方針がどこまで進めるかを調べられる。" + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "検証器が間違っていたら" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"その検証を使って学習すると、検証範囲も学習環境の一部になる。私はこうした参照基準や検証器を oracle " +"と呼んでいる。答えが再現可能でも、それが何を確認した答えなのかを理解する必要がある。" + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 " +"では、検証範囲の外に問題が隠れていた。誤った浮動小数点定数を使っていても、完全一致の比較を通る関数があった。比較器は命令を確認する前に再配置されたアドレスを調整するが、そのアドレスが指す値まで確認するのは、検証対象として明示的に登録された場合だけだった。ほかの定数への参照は、値を調べずに通ってしまう可能性があった。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"このギャップに対処するために、{ph0}広範な監査{ph1}により、すでに検証に合格した関数内に不正な定数が見つかりました。ある計算では、再構成されたソース" +" コードでは {ph2} が追加されましたが、元のコードでは {ph3} が追加されました。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}古い検証結果で報酬を与えれば、モデルは誤った再構築を学習してしまうかもしれない。{ph1} この検証器で RL " +"モデルを訓練したわけではない。観測したのは検証そのものの不具合だ。ただ、それを報酬に使えば、同じ盲点が学習環境に入ることになる。" + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"機能テストにも同様の盲点がある可能性があります。 {ph0}LLM " +"デコンパイラで差分ファジングを使用した研究{ph1}では、提供されたテスト以外の動作の違いが見つかりました。したがって、合格したテストを、実行されるケースの観点から理解する必要があります。同様に、命令の一致は、検証されるバイトとデータの観点から理解する必要があります。" + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"どちらの種類の検証チェックも報酬として使用する前に、意図的に間違った結果でテストします。また、最終的な承認は、AI エージェントが編集できるソース " +"コードとは別にしておきます。モデルはプログラムを正しく再構築することで検証に合格する必要があります。そうしないと、ターゲットからバイト配列をコピーするだけで、有用なソース" +" コードを回復せずに、単純なスコアリング システムを騙してしまう可能性があります。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}学習するモデルの改善と、その検証器の改善は同じ研究課題だ。{ph1} " +"モデルが与えられたフィードバックを上手に最適化するほど、そのフィードバックを理解することも重要になる。" + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "実行する価値のある比較" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"これらのチェックを実施したら、固定の VC7.1 タスク ファミリで比較を開始します。まず、強力な汎用 AI モデルと小規模な AI " +"モデルのベースラインを確立します。リポジトリの知識をより小さなモデルに追加すると、取得によってどのような変化が生じるのかがわかります。そこから、教師付き特殊化と" +" RL でトレーニングされたバージョンを使用して、トレーニングによって追加される内容を検証できるようになります。" + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"これらの比較を有益なものにするために、各モデルは同じターゲットの証拠とツールを受け取ります。トレーニング固有の比較の場合、基本モデルと利用可能な知識も固定したままにします。試行を繰り返すことは、信頼できる検索戦略と偶然成功した候補ソリューションを区別するのに役立ちます。" + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"二つの出発点も分けたい。命令から関数を再構築する場合と、保守しているソースの最後の差分を詰める場合だ。特化モデルが後者に優れていても、そこまでの作業の多くは汎用モデルが担っているかもしれない。別々に測れば、その分担が見える。" + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"どちらのタスクも、トレーニングと取得から除外されたテスト例が必要です。関連する Touhou ゲームはエンジン コードを共有します。トレーニングから 1" +" つのゲームを除外しても、トレーニング セットにほぼ同じ機能が残る可能性があります。代わりに、関連するソース " +"コードのグループ全体を除外し、検証済みの回答をトレーニング データと検索ライブラリの両方から除外します。" + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"測る成果は、関数全体が独立した検証を通って一致したことだ。候補数やコンパイル回数の予算をそろえれば探索の質を比べられる。コンパイルを含む総時間と総費用を測れば、それが効率的なワークフローにつながるかがわかる。学習費用は別に計上したい。" + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"どちらの測定値も重要です。安価な提案により、有用な情報を提供しないコンパイルが増加すると、ワークフローが高価になる可能性があります。逆に、有用な実験がすぐに見つかった場合、遅いモデルの方が経済的になる可能性があります。比較にはこれらのコストも含める必要があります。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"受け入れられた結果をカウントすることで、中間の進捗状況も把握できます。 1 つの TH09 " +"{ph0}再生保存候補{ph1}は、コンパイルされた関数が予想どおりのサイズを持っていたため有望に見えましたが、完全な比較では依然として大きな違いが見つかりました。コンパイラが命令を配置する方法を変更すると、根本的な問題が解決されずに、候補がより近くに見える可能性もあります。このような診断は次の実験を導くことができますが、私は「近づく」ことに対する報酬を完全な受け入れチェックと照らし合わせて検証します。" + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"結果全体にどんな傾向があるかを知りたい。特化モデルが使い慣れたコンパイラで優れていても、ツールチェーンを変えた後にその強みは残るだろうか。両方が十分に知識を検索できるとき、学習はどれだけ価値を加えるのか。答えは、各モデルをどこで使うべきかを考える助けになる。" + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "どんなエージェントが必要なのか?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"モデルが段階ごとに違う強みを持つなら、汎用エージェントが特化モデルを呼び出せる構成が役立つかもしれない。問題が慣れたコンパイラでの探索になったら、特化モデルに候補を求める。結果が納得できなくなったら、汎用エージェントが対象の証拠や測定そのものを調べ直す。" + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "この構成では、特化モデルは調査の進み方に応じて選べる道具になる。エージェントには、以前の突破口を可能にした方向転換の自由が残る。" + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"これは、前回のエッセイで説明した産業の変化から自然に生じます。さらに多くの実験を実行できるようになると、作業の組織化の方法が変わります。また、どの決定には広範な判断が必要なのか、どの決定は特定の技術での繰り返しの経験によって改善されるのかを尋ねる理由も得られます。" + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"今のところ、未解決のまま残されていた問題を解決することで、最強の汎用 AI " +"モデルが私のワークフローにその地位を獲得しました。これらの成功により、私はこの作業をさらに詳しく調べてみたいと思うようになりました。どの程度がモデルの範囲に依存しているのか、また、この特定の種類の再構成でトレーニングされたモデルでどの程度の処理が可能でしょうか?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "{ph0}リポジトリは、質問をテストする方法を提供します。{ph1}その記録を使用して比較を構築し、何が分かるかを確認したいと思います。" + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "証拠とモデルの帰属" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"この例では、リンクされたコミットに記録された関数レベルの比較の履歴について説明します。ゲーム全体のランタイム " +"チェックは別のマイルストーンです。ソースと一致する記録は 2026 年 10 月 13 日に確認されました。" + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"TH09 ラベル {ph0} は GPT-6-Astra を意味します。 {ph1} " +"に関連付けられたモデルは時間の経過とともに変化したため、ラベルだけでは特定の実行で使用されたモデルを識別できません。他の引用されたコミット内の明示的なモデル名は、記録された帰属を示します。これらの履歴には、実行ごとのコストや労力の一貫した測定値は含まれていません。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 一時オブジェクトの有効期間:{ph1} {ph2}以前のコンテキスト " +"レビュー{ph3}と、{ph4}ソースからのクリーンな再コンパイルによって検証された完全な再構築{ph5}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front コールバック:{ph1} {ph2}一致しなかった診断領域{ph3}、{ph4}Astra の新しい制御フロー " +"グラフ{ph5}、およびその {ph6}受け入れられた再コンパイル チェック{ph7}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}コンパイラーの知識:{ph1} {ph2}TH095 識別子バケットの動作の再利用{ph3}、{ph4}TH04 プレーヤーのソース " +"コードとリンカーの順序{ph5}、および {ph6}Luna による TH09 の敵作成関数の完全な再構築{ph7}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}チェックと診断:{ph1} {ph2}TH08 浮動小数点定数監査{ph3}、{ph4}TH08 数値調査{ph5}、および " +"{ph6}TH09 リプレイ保存再構築{ph7}。" + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"特化モデルと RL " +"の比較は、これから行いたい実験だ。プロジェクトの履歴がその動機になっているが、このエッセイで学習済みの特化モデルを評価したわけではない。" + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "リバースエンジニアリングに、より大きなモデルは必要か? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "Touhou の再構築から考える、汎用モデルと特化モデル、そしてコンパイラのフィードバックからよりよい仮説を学ぶ可能性。" + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "このページでは" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "モデルとリバース エンジニアリングのエッセイ" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "厳選された復元実験" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "ページ上部へ" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "{ph0}詳しい証拠の記録{ph1}には、比較結果と実験の背景をまとめている。" + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "N0zoM1z0 著 · 2026年10月13日 · レビュー用草稿" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "セットアップガイド" diff --git a/website/locales/ko/messages.po b/website/locales/ko/messages.po index 457998e02..3d0354df4 100644 --- a/website/locales/ko/messages.po +++ b/website/locales/ko/messages.po @@ -8,76 +8,77 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "개인정보보호정책" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}홈{ph1} /블로그" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "블로그" -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "리버스 엔지니어링에 대한 생각." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "게임 재구성{ph0}에세이" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "리버스 엔지니어링의 산업 혁명" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " "agents, verification and knowledge that compounds across projects." msgstr "어떤 매뉴얼 다시고 재구성TH08,TH095및TH04에 대해 가르쳐 에이전트,검증 및 지는 화합물에 걸쳐 프로젝트입니다." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "기사 읽기" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "여N0zoM1z0·10 월 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -96,6 +97,8 @@ msgid "" msgstr "리버스 엔지니어링에 대한 생각,실제 경험을 바탕으로 REA 그리고 인공지능 요원들도" #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -129,112 +132,117 @@ msgid "" "agent." msgstr "REA -소프트웨어가 어떻게 작동하는지 알아보십시오. 코딩 에이전트로 리버스 엔지니어링." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "REA 홈" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "주 메뉴" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "GitHub에서 REA 보기" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "REA Discord 참여" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "X에서 REA 팔로우" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -243,35 +251,35 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}홈{ph1} / {ph2}블로그{ph3} /동방 재건" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "에세이*동방 재건" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "리버스 엔지니어링의 산업 혁명." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "여N0zoM1z0·10 월 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "핵심 요점" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -283,7 +291,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -296,7 +304,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -308,7 +316,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -320,7 +328,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -329,65 +337,65 @@ msgid "" msgstr "" "{ph0}우리는 산업혁명의 초기 단계에 있습니다.{ph1} 그 방법들은 여전히 형성되고 있습니다. 탐험 할 것이 많이 남아 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "어떻게 경험 화합물" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}인간의 방향{ph1} *목표 및 수용 기준" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "자율성" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "에이전트" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "실험을 선택하십시오.{ph0}가설을 제안합니다." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "검증" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "검증 기준" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "에 대한 테스트{ph0}구체적인 참조." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "저장소" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "작업 기억" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -396,7 +404,7 @@ msgstr "코드,증거,{ph0}수표 및 수업." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -405,40 +413,40 @@ msgstr "불일치{ph0}{ph1}가설 수정{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "더 나은{ph0}{ph1}시작 지점{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "재사용" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}패스{ph1} *결과 및 증거 유지" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " "fixing the checks when we discover a gap." msgstr "각 프로젝트는 더 나은 출발점으로 다음 프로젝트를 떠납니다. 그것은 우리가 간격을 발견할 때 체크를 고치는 포함한다." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "이 기사 에서" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -446,7 +454,7 @@ msgstr "{ph0}2026 년 8 월{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -454,7 +462,7 @@ msgstr "{ph0}TH08:계속{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -462,7 +470,7 @@ msgstr "{ph0}두 가지 접근법{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -470,7 +478,7 @@ msgstr "{ph0}TH095:합성{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -478,7 +486,7 @@ msgstr "{ph0}TH04:아키텍처 전반에 걸쳐{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -486,7 +494,7 @@ msgstr "{ph0}정확한 것부터 읽을 수있는 것까지{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -494,18 +502,18 @@ msgstr "{ph0}산업 변화{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}가능한 것{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "2026 년 8 월에 변경된 사항" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -518,7 +526,7 @@ msgstr "" " 할 것입니다. 더 얻는 것은 다음 기능에 내 자신의 시간을 더 많이 보내는 것을 의미했습니다. 그것은 또한 내 머리 속에 점점 더 큰 " "그림을 유지하는 것을 의미했습니다." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -530,7 +538,7 @@ msgstr "" "문서의 뒤에 경험이다. 이 방법은 다른 곳에서 유용 할 수 있지만 각 필드는 신뢰할 수있는 참조에 대해 확인할 수있는 것을 " "설정해야합니다." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -541,7 +549,7 @@ msgstr "" "8 월 2026 에서 에이전트 중심의 재를 진지하게 탐구하기 시작했습니다. 나는 에이전트가 프로그램 및 일반 개발 도구에 액세스 할 " "수있는 방법을 멀리보고 싶었다. 동방 재건은 저에게 알아낼 수 있는 상당한 프로젝트를 주었습니다." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -555,7 +563,7 @@ msgstr "" "함수로 보낼 수 있습니다. 그것은 작은 진단을 작성하고 그 결과를 사용하여 다음에 무엇을 시도할지 결정할 수 있습니다. 그 자유를 주는 " "것은 변화를 가져왔습니다.저는 프로젝트의 방향과 그 수표가 신뢰할 수 있는지에 더 많은 관심을 기울일 수 있었습니다." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -565,7 +573,7 @@ msgstr "" "속도는 먼저 내 관심을 얻었다. 그런 다음 현재 프로젝트를 넘어 생존 할 것이 무엇인지 궁금해하기 시작했습니다. 다음 게임은 우리가 방금" " 배운 모든 것에서 이익을 얻을 수 있습니까?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08:건물에서 인간의 작업" @@ -574,7 +582,7 @@ msgstr "TH08:건물에서 인간의 작업" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -586,7 +594,7 @@ msgstr "" "{ph0}TH08{ph1},불멸의 밤,의 연속으로 시작 {ph2}GensokyoClub의 재건{ph3}. 그들의 공개 소스는 나에게 " "상당한 기초를 주었다. 그것은 건물의 지식과 내가 계속에서 보존 한 기여의 역사와 함께 왔습니다." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -596,7 +604,7 @@ msgstr "" "수입된 역사는 8 월 10 일 공공 검문소에서 끝납니다. 나의 독립적 인 연속은 8 월 13 일에 시작되었습니다. 8 월 19 " "일까지,원장은 1,107 개의 확인된 게임 기능에 대한 소스를 기록했습니다." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -606,7 +614,7 @@ msgstr "" "재생 가능한 Linux 재건 항구는 계속이 시작된 지 약 11 일 후인 8 월 24 일에 착공되었다. 웹 에디션이 이어졌습니다. 원주민 " "Linux 64 비트 릴리스는 8 월 30 일에 도착했다." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -620,7 +628,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -635,12 +643,12 @@ msgstr "" "함수가 원래의 명령어를 재현하는지 알 수 있습니다. 런타임 검사는 실행된 경로가 예상 상태에 도달하는지 여부를 알려줍니다. 에이전트는 " "설명을 제안하고 테스트합니다.불일치로 인해 조사할 수 있는 특별한 것이 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "잘못된 상수와 정확히 일치" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -649,7 +657,7 @@ msgstr "오라클은 누군가가 쓴 소프트웨어입니다. TH08 그 소프 #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -660,7 +668,7 @@ msgstr "" "9 월,다운스트림 스위치 포트에서 보고된 버그로 인해 아이템 자동 수집이 다시 시작되었습니다. 재구성된 소스는 플레이어의 힘을 " "{ph0}. 원래 사용 {ph1},최대 전력 임계값." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -673,13 +681,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}그러나 함수는 이미 정확한 비교를 통과했습니다.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -692,7 +700,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -707,7 +715,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -719,7 +727,7 @@ msgstr "" "그 {ph0}9 월 2 일 수정{ph1} 소스를 수정하고 비교 확인 참조 상수의 실제 바이트를했다. A {ph2}더 넓은 감사{ph3} " "그런 다음 1,548 개의 부동 소수점 상수 참조를 조사했습니다. 5 개의 허용된 함수에서 12 개의 잘못된 참조를 발견했습니다." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -731,7 +739,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -739,7 +747,7 @@ msgid "" "repairing the game." msgstr "{ph0}검증 참조(오라클)도 재구성해야 했습니다.{ph1} 그것을 수리하는 것은 게임 수리의 일부였습니다." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -754,7 +762,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -768,7 +776,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -776,7 +784,7 @@ msgid "" " for the next batch.{ph1}" msgstr "{ph0}성공적인 일괄 처리는 복구 된 코드와 다음 일괄 처리를위한 더 나은 환경을 모두 제공했습니다.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "재건에 대한 두 가지 다른 아이디어" @@ -785,7 +793,7 @@ msgstr "재건에 대한 두 가지 다른 아이디어" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -796,7 +804,7 @@ msgstr "" "GensokyoClub의 {ph0}공개 추가 정보{ph1} 이런 종류의 작업에 대한 의견이 분분합니다. 이 통지서는 추가 개발이 완료될 " "때까지 사적으로 이루어질 것이라고 발표합니다. 한 구절은 이렇게 말합니다.:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -805,7 +813,7 @@ msgstr "" "우리의 작업에서 가져온 이 공간에서의 사기꾼(인공지능 디컴파일화 및 포트)의 부상은 미래의 디컴파일화 노력에 대한 나쁜 이미지를 " "그립니다…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -819,7 +827,7 @@ msgstr "" " 그들은 어려운 일에 자유 시간을 투자했고,그 일은 제 계속을 가능하게 했습니다. 나는 그 뒤에 노력을 존중. 제가 논의하고 싶은 의견 " "불일치는 재건이 어떻게 진행되어야 하는지,그리고 기여가 어떻게 판단되어야 하는지에 관한 것입니다." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -830,7 +838,7 @@ msgstr "" "내가 알고 있던 수동 작업 흐름에서 함수에 대한 이해를 개발하고 재구성하는 것은 보통 같은 사람에게 떨어졌습니다. 프로젝트는 그 사람의 " "전문성에 크게 의존했습니다. 기여자에 대한 신뢰는 중요했습니다.왜냐하면 그들이 일하는 동안 많은 추론이 일어났기 때문입니다." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -840,7 +848,7 @@ msgstr "" "기존 프로젝트는 이미 소스에 대한 지식을 보존하고 도구를 구축합니다. 나를 위해 변경 한 것은 에이전트가 그 지식을 사용하여 다음 조사를" " 독자적으로 수행 할 수 있다는 것입니다." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -852,7 +860,7 @@ msgstr "" "나의 계속안에,나는 결과를 받아들이기를 위해 목적 그리고 기준을 결정한다. 에이전트는 조사할 자유가 넓습니다. 제안된 재건은 관련 " "검사에서 살아남아야 합니다. 에이전트가 대부분의 작업을 수행하더라도 다른 사람이 구현을 선택한 이유를 검토 할 수 있기를 바랍니다." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -863,7 +871,7 @@ msgstr "" "이것은 어려운 전환이 될 수 있습니다. 수년간의 신중한 작업이 훨씬 더 빨리 움직이는 연속의 기초가 될 수 있습니다. 즉 신용에 대한 " "실제 질문을 제기한다. 또한 유지 관리자가 기여를 수락하기 전에 알아야 할 사항을 변경합니다." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -876,7 +884,7 @@ msgstr "" " 기술이 필요한 곳에서 변합니다. 누군가는 여전히 프로세스를 설계하고 출력이 잘못되었을 때 인식해야합니다. 다른 지역 사회는 그들이 " "원하는 변화의 양을 선택할 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -899,7 +907,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -910,14 +918,14 @@ msgstr "" "출처: GensokyoClub의 {ph0}추가 정보 공지{ph1} 2026 년 10 월 10 일에 확인된 {ph2}기여 정책{ph3}. " "이 인용구는 줄여진 인용구입니다. TH08의 {ph4}신용 및 출처{ph5} 연속 경계를 기록하십시오." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095:경험이 시작되는 합성의" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -930,7 +938,7 @@ msgstr "" "시작되었으며,레저에 확인된 게임 기능이 없습니다. 우리는 여전히 게임을 배워야 했습니다. 그러나 우리는 이미 재건을 시작하는 방법과 " "그것을 계속 움직이는 방법에 대해 훨씬 더 많이 알고 있었습니다." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -942,7 +950,7 @@ msgstr "" " 전체 프로그램은 9 월 9 일에 연결되었습니다. 그 Windows 초기화 후 약 12 일 후인 9 월 10 일에 재생 가능한 것으로 " "표시되었다." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -952,7 +960,7 @@ msgstr "" "나는 이것이 첫 번째 프로젝트의 속도보다 더 흥미 진진하다고 생각했습니다. 새로운 타겟은 다른 게임에서 수행된 작업에서 이익을 얻을 수 " "있습니다. 이 경험은 이미 도구와 프로젝트 조직 방식에 존재했습니다." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -965,7 +973,7 @@ msgstr "" "고립된 비교는 중요한 질문을 열어두고 있습니다. 우리는 그들이 함께 일하는 것을 볼 필요가 있습니다. 그 교훈은 우리가 어떻게 접근했는지" " 형성하는 데 도움이되었습니다 TH095전체 프로그램 구축입니다." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -976,7 +984,7 @@ msgstr "" "내 머리 속에 남아있는 교훈은 내가 거기있는 동안 유용합니다. 일단 다른 세션이 실행될 수 있는 체크가 되면,제가 이사를 한 후에도 계속" " 도움을 줄 수 있습니다. 다음 에이전트는 결과로 이어진 조사를 반복하지 않고 결과를 사용할 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -989,7 +997,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1000,7 +1008,7 @@ msgstr "" "{ph0}이 방법은 다음 게임의 시작 자료의 일부가됩니다.{ph1} 우리는 다음 프로젝트의 노력을 목표에 대해 실제로 새로운 것에 더 " "많이 쓸 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1011,7 +1019,7 @@ msgstr "" "나중에 가입하는 사람들도 같은 혜택을 받을 수 있습니다. 그들은 결정을 검사하고 작업을 계속하기 전에 확인을 다시 실행할 수 있습니다. " "그들은 프로젝트의 전체 역사를 재구성해서 왜 소스가 그렇게 보이는지 알아낼 필요가 없습니다." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04:워크플로는 다른 아키텍처에서 살아남습니다." @@ -1020,7 +1028,7 @@ msgstr "TH04:워크플로는 다른 아키텍처에서 살아남습니다." #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1034,7 +1042,7 @@ msgstr "" "환경이었습니다. 하드웨어 동작을 이해하려면 Windows 게임. 기존 {ph2}레크 98 일{ph3} 여기에도 귀중한 지식과 자료를 " "제공했습니다." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1045,7 +1053,7 @@ msgstr "" "이제 도스 재건이 진행되고 있습니다. 내 수동 테스트에서,나는 그들의 엔딩을 통해 완전한 정상 경로를 재생하고 저장을 확인했다. 현재 " "작업은 네이티브 64 비트 포트입니다. 작업 도스 버전을 먼저 설정하면 해당 통신 포트에 참조가 제공됩니다." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1056,7 +1064,7 @@ msgstr "" "건축물은 우리가 조사해야 할 것을 바꾸었습니다. 그것은 또한 우리가 우리의 작업을 확인하는 컴파일러와 런타임을 변경했습니다. 그러나 " "에이전트는 여전히 결과를 통해 질문을 따라 그 결과가 다음 실험을 안내 할 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1069,7 +1077,7 @@ msgstr "" "알아야합니다. 그것은 우리가 도스 제품에 대해 조사 할 수있는 것입니다. 한 번의 증거이며 검사를 사용할 수 있는 에이전트를 통해 작업 " "할 수 있습니다 질문을 많이 그랬던 것처럼에Windows제목입니다." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1079,7 +1087,7 @@ msgstr "" "이것이 바로 TH04 인수에 문제. 상당한 플랫폼 변화는 우리가 새로운 작업 방식으로 다시 시작하도록 강요하지 않았습니다. 아키텍처가 " "문제를 정의했고,워크플로우는 여전히 문제를 해결하는 방법을 제공했습니다." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1095,7 +1103,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1105,19 +1113,19 @@ msgstr "" "2026 년 10 월 10 일 현재 프로젝트 상태: {ph0}도스 재구성 및 수동 테스트{ph1} · {ph2}64 비트 포트{ph3}." " 항구는 개발 중입니다." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "정확한 코드에서 읽을 수있는 코드로" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "일단 재건이 이루어지면 다른 사람이 그것을 이해할 수 있기를 바랍니다." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1130,7 +1138,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1144,7 +1152,7 @@ msgstr "" "수있을 때까지 게임이 그것을 사용하는 방법을 따릅니다. 그런 다음 우리는 그것을 의미있는 이름과 증거에 맞는 유형을 줄 수 있습니다. " "다음 사람이 그 해석이 어디서 왔는지 볼 수 있도록 우리는 출처와 추론을 유지합니다." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1157,14 +1165,14 @@ msgstr "" "객체가 그 상태를 소유해야 하는지 결정하는 데 거의 도움이 되지 않습니다. 동작을 안전하게 이동하려면 이전 메모리 액세스 뒤에 있는 " "관계를 복구해야 합니다." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "내가 지금 사용하는 순서는:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1178,7 +1186,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1192,7 +1200,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1206,7 +1214,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1219,7 +1227,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1233,7 +1241,7 @@ msgstr "" " 소스가 여전히 관련 원본 코드와 데이터를 재생하는지 확인합니다. 두 번째는 재구성된 프로그램이 우리가 실행하는 경로를 따라 여전히 " "빌드되고 올바르게 동작하는지 확인합니다." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1244,7 +1252,7 @@ msgstr "" "그들은 다른 실수를 잡습니다. 형식 변경은 생성된 명령어를 변경할 수 있습니다. 소유권 변경은 다른 상태 복사본을 사용하여 게임의 두 " "부분을 남길 수 있습니다. 두 검사를 모두 사용할 수 있도록 유지하면 에이전트가 리팩터를 더 수행하기 전에 조사하지 않을 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1260,7 +1268,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1276,7 +1284,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1286,12 +1294,12 @@ msgstr "" "{ph0}정확한 재구성은 우리에게 참조를 제공합니다. 의미적 재구성은 회복된 지식을 사용할 수 있게 해줍니다.{ph1} 포트는 둘 다에 " "구축 할 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "이 산업 변화를 만드는 것" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1302,7 +1310,7 @@ msgstr "" "이 프로젝트들은 제가 관심을 기울인 곳에서 바뀌었습니다. 에이전트가 앞으로 조사의 대부분을 수행 할 수 있으면,자신의 작업 환경을 " "개선하는 것은 내가 할 수있는 가장 유용한 것들 중 하나가되었다. 더 나은 도구는 나중에 필요한 모든 기능을 도울 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1313,7 +1321,7 @@ msgstr "" "여기서 자율성이 중요합니다. 유용한 다음 단계는 실패한 실험 후에 만 명확 해집니다. 에이전트는 예상치 못한 곳에서 그 결과를 따라갈 수" " 있는 충분한 자유가 필요합니다. 만약 제가 각 단계를 처방할 때까지 기다려야 한다면,많은 작업이 제 관심에 묶여 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1325,7 +1333,7 @@ msgstr "" "실패한 검사는 다시 시도할 만큼 실수를 잘 이해하는 데 도움이 됩니다. 나는 여전히 축적 된 증거가 프로젝트 이정표를 지원하는지 여부를 " "결정해야합니다." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1338,7 +1346,7 @@ msgstr "" "프로젝트는 컴파일러와 자체 참조 검사를 제공합니다. 에이전트는 그것을 사용하여 제안된 출처를 테스트하고 그 설명이 어디에 있는지 볼 수 " "있습니다." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1353,7 +1361,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1370,7 +1378,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1384,7 +1392,7 @@ msgstr "" "설계된 것보다 더 빨리 이동할 수 있으므로 프로세스는 그들과 함께 개발해야합니다. 공유 도구에서 결함이 발견되면 이를 복구하고 영향을 " "받은 결과를 다시 검토해야 합니다. 다음 프로젝트는 더 강력한 도구를 상속 할 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1398,7 +1406,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1409,7 +1417,7 @@ msgstr "" "그 {ph0}동방 재건 공장{ph1} 그 필요에서 성장했습니다. 이 프로젝트는 앞으로 자신의 검사와 교훈을 수행 할 수있는 공유 방법을 " "제공합니다. 한 게임에 대한 작업은 다른 게임의 시작 조건을 개선 할 수 있습니다." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1419,12 +1427,12 @@ msgstr "" "이것이 산업적 비유를 저에게 의미 있게 만드는 것입니다. 경험은 다른 사람들이 사용할 수 있는 도구의 일부가 되기 시작합니다. 이러한 " "도구를 개선하면 다음 사람 또는 다음 에이전트가 얼마나 많은 작업을 수행 할 수 있는지 변경됩니다." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "우리가 지금 고려할 수있는 프로젝트" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1434,7 +1442,7 @@ msgstr "" "이 시작 결정을 변경하기 때문에 속도 문제. 게임은 리버스 엔지니어링에 매혹적 일 수 있으며 현실적으로 줄 수있는 것보다 내 자신의 " "관심을 더 많이 요구할 수 있습니다. 많은 프로젝트가 아이디어를 유지합니다." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1449,7 +1457,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1459,7 +1467,7 @@ msgstr "" "나는 지금 익숙하지 않은 프로그램을보고 묻는다: {ph0}어떤 액세스,피드백 및 축적 된 지식으로 에이전트가이 작업을 안정적으로 수행 할" " 수 있습니까?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1469,12 +1477,12 @@ msgstr "" "그 질문은 내가 이전에 혼자 남겨 두었을 프로젝트를 고려하게합니다. 각자는 우리가 다음에 접근하는 방식을 향상시킬 수 있습니다. 나는 " "그것이 우리를 얼마나 멀리 데려 갈 수 있는지 계속 탐구하고 싶다." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "프로젝트 이정표 및 출처" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1506,7 +1514,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1540,7 +1548,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1557,7 +1565,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1580,7 +1588,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1601,7 +1609,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1617,7 +1625,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1638,7 +1646,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1652,7 +1660,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1672,27 +1680,27 @@ msgstr "" "N0zoM1z0 에 반영한 설명서 리버스 엔지니어링,동방으로 재건 AI 에이전트,그리고 지식이 어떻게 화합물 전 " "TH08,TH095PC-98TH04." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "프로젝트 간 경험" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "동방 재건 에세이" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -1701,18 +1709,18 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}홈{ph1}{ph2}/{ph3}공룡 속도 연구소" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "검사→다시 작성→변경" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "공룡의 속도 규칙을 다시 작성하십시오." @@ -1721,7 +1729,7 @@ msgstr "공룡의 속도 규칙을 다시 작성하십시오." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1732,15 +1740,15 @@ msgstr "" "게임의 가속을 재현하려면 먼저 속도를 제어하는 규칙을 찾으십시오. {ph0}REA 실행 중인 스크립트를 반환했습니다;{ph1} 우리는이 " "미니 게임을 구축하기 위해 규칙을 사용 {ph2}조정 가능한 속도.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "이 페이지에" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1748,7 +1756,7 @@ msgstr "{ph0}재생 및 속도 변경{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1756,7 +1764,7 @@ msgstr "{ph0}복구 된 규칙 읽기{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1764,18 +1772,18 @@ msgstr "{ph0}재건 확인{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}분석 시도{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "재생 및 속도 변경" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1785,54 +1793,54 @@ msgstr "" "재생을 누른 다음 선인장을 뛰어 넘습니다. 속도 슬라이더를 움직여 더 느리거나 빠른 게임을 시도하세요. 복구 된 규칙을 선택하여 6 에서" " 시작하고 점차적으로 다시 가속하십시오." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "재구성한 게임 플레이" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "시작" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "점프 ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "다시 시작" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "속도" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "복구된 가속 규칙 사용" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "원래 규칙:6 에서 시작한 다음 13 으로 늘립니다." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "자신의 속도를 설정하는 슬라이더를 이동합니다. 공간 또는 점프는 선인장을 지 웁니다." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "사용JavaScript을 재생하는 재건. 위의 코드와 설명은 읽을 수 있습니다." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "스크립트 읽기 REA 반환" @@ -1840,7 +1848,7 @@ msgstr "스크립트 읽기 REA 반환" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1854,7 +1862,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1862,18 +1870,18 @@ msgid "" "update without a collision." msgstr "설정은 다음과 같습니다 {ph0}, {ph1} 그리고 {ph2}. 이 게임은 충돌 없이 업데이트에서 이 브랜치를 실행합니다." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "새로운 게임에서 동일한 규칙을 사용" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "복사" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -1888,18 +1896,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}속도 규칙 다운로드{ph1} · {ph2}게임 코드 읽기{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "재건 확인" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -1908,27 +1916,27 @@ msgid "" msgstr "" "우리는 장애물과 자동 예약이 비활성화 된 원래 게임의 업데이트 기능을 불렀습니다. 기록 된 속도를 복구 된 규칙의 재생과 비교하십시오." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "업데이트" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "원래 게임" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "재구성된 규칙" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "속도 검사 실행" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -1936,14 +1944,14 @@ msgid "" msgstr "" "값은 세 개의 소수로 반올림. 분기는 더하기 전에 확인합니다.그래서 최종 인크림트는 13 을 조금 넘는 속도를 낼 수 있습니다." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "직접 분석해 보세요" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -1952,14 +1960,14 @@ msgstr "{ph0}설정 REA{ph1} 코딩 에이전트와 함께." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "따라 {ph0}브라우저 연결 단계{ph1},사용 {ph2} 페이지" -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -1974,7 +1982,7 @@ msgstr "에이전트에 페이지 및 로컬 디버깅 끝점을 지정한 다 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -1986,7 +1994,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1999,7 +2007,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2012,7 +2020,7 @@ msgstr "후속 조치 요청: {ph0}\"점프 높이는 어디에서 계산됩니 #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2035,64 +2043,64 @@ msgid "" "speed and play." msgstr "공룡 게임의 속도 규칙을 읽으십시오 REA,다시 만든 다음 속도를 바꾸고 재생하십시오." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "공룡 속도 재구성" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "공룡 미니 게임. 게임이 집중되는 동안 점프 버튼을 누르거나 공간을 사용합니다." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "재구성된 속도 규칙 복사" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "복사 공룡 분석 프롬프트" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "개인정보보호정책" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}홈{ph1} /자주하는 질문" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA자주 묻는 질문에 있습니다." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "설정,업데이트,분석 및 문제 해결." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "주제" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2100,7 +2108,7 @@ msgstr "{ph0}설정 및 업데이트{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2108,7 +2116,7 @@ msgstr "{ph0}분석{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2116,31 +2124,31 @@ msgstr "{ph0}문제 해결{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}데이터 및 공유{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "설정 및 업데이트" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "REA는 어떻게 설치하나요?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "터미널*에이전트 설정" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "복사" @@ -2148,7 +2156,7 @@ msgstr "복사" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2160,13 +2168,13 @@ msgstr "" "설정 명령은 REA의 MCP 연결을 등록하고 분석 스킬을 설치합니다. 완료되면 에이전트를 다시 시작한 뒤 분석할 파일 경로와 질문을 " "전달하세요. 필요한 환경과 첫 분석 방법은 {ph0}설정 가이드{ph1}에서 확인할 수 있습니다." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "어떤 코딩 에이전트가 사용할 수 있습니까 REA?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2181,32 +2189,32 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}코딩 에이전트 연결{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "REA는 어떻게 업데이트하나요?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " "npm:" msgstr "REA 버그 수정을 포함하여 자주 출시됩니다. 당신이 설치 한 경우 CLI 함께 npm:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "터미널·설치CLI" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2214,14 +2222,14 @@ msgid "" "agent through {ph0}, run:" msgstr "업데이트가 출력하는 설정 갱신 명령을 실행하세요. {ph0}로 에이전트를 설정했다면 다음 명령을 사용하세요:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "터미널*에이전트 설정 새로 고침" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2232,7 +2240,7 @@ msgstr "" "변경 내용을 확인하고 에이전트를 다시 시작하세요. REA 연결 설정은 특정 패키지 버전을 사용하므로 설정 명령을 다시 실행해야 새 버전이" " 적용됩니다. CLI를 한 번 실행할 때는 {ph0} 뒤에 원하는 명령을 붙이세요." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "에서 기술을 설치 skills.sh 충분히?" @@ -2240,7 +2248,7 @@ msgstr "에서 기술을 설치 skills.sh 충분히?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2251,17 +2259,17 @@ msgstr "" "스킬은 에이전트에게 분석 방법을 알려줍니다. {ph0}REA 설정{ph1}을 실행해 MCP 서버를 연결하고 스킬을 설치하세요. 도구를 " "사용하려면 에이전트를 다시 시작해야 합니다." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "분석" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "무엇을 분석 할 수 있습니까 REA?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "당신이 가지고있는 소프트웨어의 종류로 시작:" @@ -2269,7 +2277,7 @@ msgstr "당신이 가지고있는 소프트웨어의 종류로 시작:" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2279,7 +2287,7 @@ msgstr "{ph0}네이티브 실행 파일과 라이브러리{ph1}: 함수, 어셈 #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2289,7 +2297,7 @@ msgstr "{ph0}JavaScript 그리고 Electron 앱{ph1}:모듈,수입,아이피씨 #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2298,7 +2306,7 @@ msgstr "{ph0}브라우저 페이지{ph1}:스크립트,요청 및 런타임 관 # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2309,13 +2317,13 @@ msgstr "" "REA는 .NET 등의 관리형 어셈블리, Android APK, 펌웨어, 패키지 리소스도 분석합니다. 실제 분석 과정은 {ph0}사례 " "소개{ph1}에서 확인하세요." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "내가 필요합니까 Hopper, Ghidra 또는 IDA?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2327,7 +2335,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2338,20 +2346,20 @@ msgstr "" "기존 Ghidra나 IDA를 연결하세요. 또는 설정 명령으로 Hopper를 찾아 설치 계획을 확인할 수 있습니다. 사용할 수 있는 분석 " "도구는 운영체제와 대상에 따라 달라집니다. {ph0}네이티브 분석 설정{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "내가 사용할 수 있습니까 REA 코딩 에이전트가 없다면?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " "Electron app:" msgstr "네. CLI에서도 같은 분석 흐름을 사용합니다. 로컬 JavaScript 또는 Electron 앱은 다음처럼 분석합니다:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "터미널*정적 애플리케이션 분석" @@ -2359,7 +2367,7 @@ msgstr "터미널*정적 애플리케이션 분석" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2368,13 +2376,13 @@ msgid "" msgstr "경로를 압축 해제한 앱 폴더나 ASAR 파일로 바꾸세요. 설치 방법은 {ph0}CLI 사용 안내{ph1}를 참고하세요." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA는 어떤 코드를 반환하나요?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2389,7 +2397,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2400,13 +2408,13 @@ msgstr "" "에이전트는 분석 결과로 동작을 설명하거나 구현을 작성하고 테스트합니다. {ph0}DX-Ball 계산{ph1}과 {ph2}CTF flag " "검사기{ph3}에서 그 과정을 볼 수 있습니다." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "에이전트에게 무엇을 물어보면 되나요?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2421,7 +2429,7 @@ msgstr "로컬 대상과 조사할 동작 하나를 알려주세요. JavaScript #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2430,7 +2438,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2439,19 +2447,19 @@ msgid "" msgstr "" "경로를 분석할 대상으로 바꾸세요. {ph0}가이드{ph1}에는 네이티브 프로그램, Electron, 브라우저용 예시 프롬프트가 있습니다." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "문제 해결" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "왜 내 에이전트가 볼 수 없습니까 REA 도구?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2459,7 +2467,7 @@ msgid "" " {ph0}; for Codex:" msgstr "설정 후 에이전트를 다시 시작하거나 다시 연결하세요. {ph0}로 REA 등록 상태를 확인할 수 있습니다. Codex의 예:" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "터미널*하나의 클라이언트 확인" @@ -2468,7 +2476,7 @@ msgstr "터미널*하나의 클라이언트 확인" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2478,7 +2486,7 @@ msgstr "" "{ph0}를 {ph1} 또는 {ph2} 같은 클라이언트 ID로 바꾸세요. 등록이 없거나 오래되었다고 나오면 해당 클라이언트의 설정을 다시" " 실행하세요:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "터미널*한 클라이언트의 설정을 복구" @@ -2486,7 +2494,7 @@ msgstr "터미널*한 클라이언트의 설정을 복구" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2497,7 +2505,7 @@ msgstr "" "변경 계획을 확인하고 클라이언트를 다시 시작하세요. 등록은 정상이지만 도구가 보이지 않으면 클라이언트의 MCP 연결 오류를 확인하세요. " "{ph0}추가 설정 진단{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "내가 시작해야합니까 Hopper 먼저?" @@ -2505,7 +2513,7 @@ msgstr "내가 시작해야합니까 Hopper 먼저?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2516,7 +2524,7 @@ msgstr "" "REA는 작업에 필요할 때 Hopper를 실행합니다. macOS에서는 자동 분석 전에 첫 실행 화면에서 데모 모드나 라이선스 활성화를 " "선택해야 합니다. {ph0}네이티브 분석 도구 설정{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "버그가 발생하면 어떻게 하나요?" @@ -2524,7 +2532,7 @@ msgstr "버그가 발생하면 어떻게 하나요?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2537,7 +2545,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2548,25 +2556,25 @@ msgstr "" "문제가 계속되면 REA 버전, 운영체제, 대상 종류, 재현 방법, 오류 출력을 포함해 {ph0}이슈를 등록하세요{ph1}. 네이티브 분석" " 문제라면 분석 도구 이름도 알려주세요." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "데이터 및 공유" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "않습니다 REA 내 앱을 업로드 하시겠습니까?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " "its model provider's data policy applies to those results." msgstr "REA는 사용자의 컴퓨터에서 대상을 분석합니다. 결과는 에이전트가 받으므로 해당 모델 제공자의 데이터 정책이 적용됩니다." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "예를 공유하거나 기여할 수 있는 방법은 무엇입니까?" @@ -2576,7 +2584,7 @@ msgstr "예를 공유하거나 기여할 수 있는 방법은 무엇입니까?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2591,7 +2599,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2612,91 +2620,91 @@ msgid "" "coding agents, troubleshooting and sharing examples." msgstr "REA의 설치, 업데이트, 분석 도구, 코딩 에이전트, 문제 해결, 사례 공유에 관한 자주 묻는 질문." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "자주 묻는 질문들에 대한REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "복사REA설정 명령" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "복사REAupdate 명령" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "에이전트 설치 복사 새로 고침 명령" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "복사REACLI분석 명령" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "예제 분석 프롬프트 복사" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "클라이언트 진단 복사 명령" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "범위 설정 복사 명령" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "개인정보보호정책" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}홈{ph1} /첫 번째 조사" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "어디 찾기{ph0}내 보낸 노트는 이동합니다." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" " detail yourself." msgstr "사용 REA 작은 응용 프로그램을 검사하려면 내보내기 노트 버튼을 따라 하나의 세부 사항을 직접 확인하십시오." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "이 연습에서" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2704,7 +2712,7 @@ msgstr "{ph0}1. 설정{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2712,7 +2720,7 @@ msgstr "{ph0}2. 수출에 대해 문의{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2720,7 +2728,7 @@ msgstr "{ph0}3. 답을 따라{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2728,13 +2736,13 @@ msgstr "{ph0}4. 예측 확인{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. 다른 질문{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. 에이전트에 연결 REA" @@ -2747,43 +2755,43 @@ msgstr "1. 에이전트에 연결 REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "복사" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "또는 터미널에서 이 명령을 실행하십시오:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " "connected? Continue below." msgstr "계획을 검토하고 설정을 승인한 다음 에이전트를 다시 시작하십시오. 이미 연결되어 있습니까? 아래 계속." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. 해CSV기록" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2794,7 +2802,7 @@ msgstr "" "예는 6 개의 파일입니다. Electron 와 응용 프로그램 {ph0}노트 내보내기{ph1} 버튼. 에이전트는 설치 또는 실행 없이 해당" " 코드를 검사할 수 있습니다 Electron." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2804,14 +2812,14 @@ msgstr "에이전트가 파일을 다운로드하고 압축을 푼 폴더를 REA #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}다운로드 예제 우편 번호{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2820,12 +2828,12 @@ msgid "" msgstr "" "에이전트가 파일을 다운로드할 수 없는 경우 이 아카이브의 압축을 직접 풉니다. 그 길을 {ph0} 폴더 및 동일한 내보내기 질문." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. 답을 따라 코드로 돌아갑니다" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "파일 및 줄 참조와 함께 간단한 설명을 찾으십시오:" @@ -2834,7 +2842,7 @@ msgstr "파일 및 줄 참조와 함께 간단한 설명을 찾으십시오:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2845,19 +2853,19 @@ msgstr "" "이 버튼은 {ph0} 메시지 주요 프로세스는 노트를 다음과 같이 포맷합니다. CSV 그리고 글을 쓰죠. {ph1} 사용자의 다운로드 " "폴더에 있습니다. 열은 {ph2} 그리고 {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "버튼에서 파일 작성기로" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" " read from code." msgstr "REA정적 분석은 메시지와 핸들러를 결합합니다. 대상은 코드에서 읽습니다." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -2868,37 +2876,37 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}전체 코드 추적 및 기록보기 REA 결과{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. 예측 확인" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " "contains a comma or quotation marks?" msgstr "쉼표로 구분 CSV 열. 메모 제목 자체에 쉼표나 따옴표가 있으면 어떻게 됩니까?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "직접 확인 실행" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "압축을 푼 터미널을 엽니 다 {ph0} 폴더:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -2906,24 +2914,24 @@ msgid "" msgstr "" "이 명령은 여기 문서 지원 셸을 사용합니다. 귀하의 에이전트는 동일한 실행할 수 있습니다 JavaScript 플랫폼의 쉘에서." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. 다른 질문" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "동일한 대화에서 후속 조치를 시도하십시오:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "파일을 작성할 수 없는 경우 어떻게 됩니까? 오류를 따라 페이지로 돌아갑니다." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -2934,7 +2942,7 @@ msgstr "또는 에이전트에게 자신의 앱을 제공하고 하나의 버튼 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2946,7 +2954,7 @@ msgstr "{ph0}어떻게 Notion 텍스트 복사{ph1}{ph2}패키지에서 클립 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2958,7 +2966,7 @@ msgstr "{ph0}어떻게 DX-Ball 사운드 패닝 계산{ph1}{ph2}원래 지침과 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2978,113 +2986,113 @@ msgid "" "go, and check the CSV formatter with a sample title." msgstr "시도해봐 REA 작은 메모 앱에. 당신의 에이전트를 설정,내 보낸 노트가 어디로 물어,그리고 확인 CSV 샘플 제목 포맷터." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "귀하의 첫 번째REA조사" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "복사REA설치 프롬프트" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "설치 명령 복사" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "복사 노트 조사 프롬프트" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "복사 CSV 확인 프롬프트" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "복사 포맷터 검사 명령" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "개인정보보호정책" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}홈{ph1} /시작" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "설정REA." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "연결 REA 코딩 에이전트에,또는 터미널에서 로컬 응용 프로그램을 검사합니다." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "터미널을 열고 확인:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "터미널" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "복사" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0}Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3095,7 +3103,7 @@ msgstr "약관 동의를 요청하면 Y를 입력하세요. PowerShell을 닫았 #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3105,17 +3113,17 @@ msgstr "" "나중에 {ph2}을 실행할 때 PowerShell에 {ph0}\"running scripts is disabled on this " "system\"{ph1}(스크립트 실행이 비활성화됨) 메시지가 나오면, 다음 명령을 한 번 실행하고 다시 시도하세요." -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "당신이 사용하는 경우 Homebrew:" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "그렇지 않으면:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "터미널을 닫고 다시 연 다음:" @@ -3123,7 +3131,7 @@ msgstr "터미널을 닫고 다시 연 다음:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3133,7 +3141,7 @@ msgstr "설치 프로그램 요구 사항 {ph0} 그리고 {ph1} (데비안/우 #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3143,7 +3151,7 @@ msgstr "배포판 자체 {ph0} 패키지는 종종 22.19 보다 오래된,그래 #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3151,14 +3159,14 @@ msgid "" "{ph0}nodejs.org{ph1}." msgstr "일반 설치 프로그램을 선호? 다운로드 {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "설정 옵션" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3166,7 +3174,7 @@ msgstr "{ph0}코딩 에이전트 연결{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3174,7 +3182,7 @@ msgstr "{ph0}사용 CLI{ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3182,18 +3190,18 @@ msgstr "{ph0}기계 코드 프로그램 분석 설정{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}도움 받기{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "코딩 에이전트 연결" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3203,12 +3211,12 @@ msgstr "" "설치 프로그램을 실행하여 연결 REA 코딩 에이전트에. 고객 선택은 Claude Code, Codex, Cursor, Gemini " "CLI, Windsurf, Grok Build,및 기타 지원 MCP 고객. Grok Bot의 커넥터는 채팅에서 추가됩니다." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "코딩 에이전트에 새로운?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3218,7 +3226,7 @@ msgstr "" "코딩 에이전트는 브라우저 탭이 아닌 컴퓨터에서 작동하는 인공지능 보조자입니다. 파일을 읽고 명령을 실행할 수 있으며 변경하기 전에 " "묻습니다. REA그것을 리버스 엔지니어링 도구입니다." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3228,7 +3236,7 @@ msgstr "당신은 아직 하나가없는 경우,하나를 선택,그 설치 페 #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3239,7 +3247,7 @@ msgstr "{ph0}{ph1}Claude Code{ph2}{ph3} 에 의해 Anthropic. 유료 필요 Clau #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3250,7 +3258,7 @@ msgstr "{ph0}{ph1}Codex{ph2}{ph3} 에 의해 OpenAI. 귀하의 계정으로 로 #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3258,7 +3266,7 @@ msgid "" "your choice." msgstr "{ph0}{ph1}OpenCode{ph2}{ph3},오픈 소스. 원하는 모델 공급자를 연결합니다." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3274,18 +3282,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "또는 직접 설치 실행" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "터미널은 어떻게 열 수 있나요?" @@ -3294,7 +3302,7 @@ msgstr "터미널은 어떻게 열 수 있나요?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3308,7 +3316,7 @@ msgstr "{ph0}Windows:{ph1} 시작 메뉴를 열고 {ph2}PowerShell{ph3}을 입 #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3320,7 +3328,7 @@ msgstr "{ph0}macOS:{ph1} 프레스 {ph2} {ph3},유형 {ph4}터미널{ph5} 를 #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3333,7 +3341,7 @@ msgstr "{ph0}Linux:{ph1} 프레스 {ph2} {ph3} {ph4} 대부분의 데스크톱 #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3343,7 +3351,7 @@ msgstr "" "명령 붙여넣기 {ph0} {ph1} (macOS: {ph2} {ph3}; Linux 터미널: {ph4} {ph5} {ph6})를 누른 " "다음 엔터를 누릅니다." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3353,12 +3361,12 @@ msgstr "" "클라이언트를 선택하고 설치 계획을 검토합니다. REA추가MCP연결와 일치하는 조사 기술,유지 백업 기존의 구성이 있습니다. 변경 사항을 " "적용하기 전에 묻습니다." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "설치가 완료되면 클라이언트를 다시 시작합니다." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "내 클라이언트를 다시 시작하려면 어떻게 합니까?" @@ -3367,7 +3375,7 @@ msgstr "내 클라이언트를 다시 시작하려면 어떻게 합니까?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3382,7 +3390,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3391,7 +3399,7 @@ msgid "" msgstr "" "{ph0}터미널 에이전트{ph1} (Claude Code, Codex, Gemini CLI):세션을 종료하고 다시 시작합니다." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3401,7 +3409,7 @@ msgstr "" "있습니다:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3410,12 +3418,12 @@ msgid "" msgstr "" "봐 {ph0} 그리고 데이터를 내보내는 방법을 찾으십시오. 검색 결과에 대한 소스 위치와 관련된 진입 점,통화 및 종속성을 표시합니다." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "경로를 로컬 대상으로 바꿉니다." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "폴더의 전체 경로를 어떻게 얻을 수 있습니까?" @@ -3424,7 +3432,7 @@ msgstr "폴더의 전체 경로를 어떻게 얻을 수 있습니까?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3438,7 +3446,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3450,7 +3458,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3458,31 +3466,31 @@ msgid "" "appears." msgstr "{ph0}모든 시스템:{ph1} 폴더를 터미널 창으로 드래그하면 해당 경로가 나타납니다." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "터미널에서 공백이 포함된 경로 주위에 따옴표를 넣습니다." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "사용CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " "running the app:" msgstr "분석JavaScript또는Electron응용 프로그램 폴더 또는ASAR보관없이 응용 프로그램을 실행:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "정적 애플리케이션 분석" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3490,13 +3498,13 @@ msgid "" "Windows, a path such as {ph1} works here." msgstr "경로를 추출된 앱 디렉터리로 바꾸거나 {ph0} 파일 시작 Windows,같은 경로 {ph1} 여기서 작동합니다." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "어디 응용 프로그램의 찾을 수 있습니까.아사르 파일?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3507,7 +3515,7 @@ msgstr "Electron 응용 프로그램은 일반적으로 그것을 유지 {ph0} #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3519,7 +3527,7 @@ msgstr "{ph0}Windows:{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3530,20 +3538,20 @@ msgstr "{ph0}macOS:{ph1} {ph2} (앱을 마우스 오른쪽 버튼으로 클릭 #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0}Linux:{ph1} 종종 {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "일부 앱은 다른 곳에 설치됩니다. 에 대한 응용 프로그램의 폴더를 검색 {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3552,43 +3560,43 @@ msgid "" msgstr "결과는 앱을 식별하고 모듈 간의 연결을 표시하며 소스 위치를 제공합니다. 연결 REA 확인할 수 없습니다 결과에 표시됩니다." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "만약 당신이 영구 {ph0} 쉘의 명령:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "설치CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}계속 JavaScript 신청 가이드{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "기계 코드 프로그램 분석 설정" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " "then give REA your executable or library." msgstr "네이티브 바이너리에는 로컬 분석 도구가 필요합니다. 선택하고 아래 하나를 구성,다음 제공 REA 실행 파일 또는 라이브러리." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "도구 선택: Ghidra, Hopper 또는 IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3599,17 +3607,17 @@ msgstr "" "비트 설치 및 64 비트 설치 Linux 또는 macOS,64 또는 팔 64 에. 당신의 Ghidra 설치에는 호스트 아키텍처를 위한 " "기본 디컴파일러가 필요합니다. 설치 프로그램을 실행하기 전에 경로 설정:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "당신의 연결 Ghidra 설치" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra연결·macOS/Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3619,12 +3627,12 @@ msgstr "" "두 경로를 기존 설치로 바꿉니다. 설치 프로그램은 이를 확인하고 선택한 클라이언트에 대한 유효한 설정을 기록합니다. 시작 Linux 팔 " "64,당신은 구축해야 할 수도 있습니다 Ghidra네이티브 디컴파일러입니다." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "연결 Ghidra 시작 Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3634,18 +3642,18 @@ msgstr "" "Windows 1000 개 이상의 웹 사이트에서 다운로드 할 수 있습니다. 기존 사용 Ghidra 12.1.64 비트 설치 및 64 비트" " 설치 및 64 비트 설치 및 64 비트 설치 및 64 비트 설치 및 64 비트 설치:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra연결·WindowsPowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "두 경로를 설치로 바꾼 다음 설치 계획을 검토합니다." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3653,14 +3661,14 @@ msgid "" msgstr "" "에 연결Hopper에macOS또는Linux. 위의 설치 명령을 실행;그것은 기존의 설치를 감지하거나 승인을 위해 설치 계획을 제공합니다." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " "activation before an unattended analysis." msgstr "에macOS,완전한Hopper's first-실행 선택의 데모 모드 또는 라이센스를 활성화하기 전에 무인 분석이다." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3670,7 +3678,7 @@ msgstr "" "검증된 IDA 설정 사용 Windows,기존의 MCP 첨부 된 데이터베이스 또는 헤드리스 데이터베이스에 대한 등록. Linux 그리고 " "macOS 헤드리스 분석은 아직 확인되지 않았습니다." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "기존 연결 IDA MCP 등록" @@ -3680,7 +3688,7 @@ msgstr "기존 연결 IDA MCP 등록" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3691,13 +3699,13 @@ msgstr "" "업스트림 서버의 작동 유지 {ph0}, {ph1} 그리고 선택 {ph2} 제슨 파일에 기존 {ph3} 객체 {ph4} 입장도 허용됩니다." " 포인트 REA 설정 전에 해당 파일에서:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA 연결 · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3713,7 +3721,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3724,29 +3732,29 @@ msgstr "" "줘 REA 원래 실행 경로, {ph0} 에 CLI 쿼리 에이전트의 경우 다음을 포함합니다 {ph1} 그 안에 REA 등록 환경 및 선택 " "IDA 바이너리를 열 때." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "기존의 Ghidra 설치,기능 검사:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "기능 분석" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "교체 {ph0} 검사할 함수 이름 또는 주소를 사용합니다." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "기계 코드 프로그램 세션의 분석 작동 방식" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3758,7 +3766,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3766,18 +3774,18 @@ msgid "" "leads to a recovered calculation." msgstr "{ph0}기계 코드 프로그램 분석 예제를 따르십시오{ph1} 함수 결과가 어떻게 복구된 계산으로 이어지는지 확인합니다." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "도움 받기" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "에이전트가 표시되지 않는 경우 REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3785,27 +3793,27 @@ msgid "" "{ph0}; for Codex:" msgstr "설치 후 클라이언트를 다시 시작하거나 다시 연결합니다. 그 확인 REA 연결 {ph0};를 위해 Codex:" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "한 클라이언트 확인" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "공급자가 주의를 필요로 하는 경우" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "사용 중인 공급자를 확인하십시오. 에 대한Ghidra:" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "하나의 공급자 확인" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "이 보고서는 실패한 확인 및 제안 된 다음 단계를 제공합니다." @@ -3814,7 +3822,7 @@ msgstr "이 보고서는 실패한 확인 및 제안 된 다음 단계를 제공 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3825,7 +3833,7 @@ msgstr "{ph0}REA 제품소개{ph1}{ph2}업데이트,에이전트 및 분석에 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3837,7 +3845,7 @@ msgstr "{ph0}조사 가이드 선택{ph1}{ph2}바이너리에 대한 작업 예 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3849,7 +3857,7 @@ msgstr "{ph0}GitHub 문제{ph1}{ph2}명령 및 진단 문제를 보고합니다. #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3871,112 +3879,112 @@ msgstr "" "에 연결REA를 코딩의 에이전트 또는 검사 지역JavaScript또는Electron에서 응용 프로그램 터미널도 있습니다. 설정,첫 번째 " "질문 및 기본 공급자 가이드." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "복사Node.js버전을 확인" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "복사 Node.js 설치 명령 Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "복사 PowerShell 실행 정책 명령" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "복사 Homebrew Node.js 설치 명령" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "설치 명령 복사 macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "복사 Node.js 24 에 대한 명령 macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "설치 명령 복사 Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "복사 Node.js 24 에 대한 명령 Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA시작 안내" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "복사REA설치 프롬프트" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "에이전트 설정 복사 명령" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "복사JavaScript분석 명령" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "복사CLI설치 명령" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "macOS 및 Linux용 Ghidra 연결 명령 복사" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "복사Ghidra연결WindowsPowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "복사 IDA 에 대한 연결 Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "기본 함수 분석 복사 명령" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "클라이언트 진단 복사 명령" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "공급자 진단 복사 명령" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -3985,34 +3993,34 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}홈{ph1} / {ph2}가이드{ph3} /브라우저 관찰" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "무슨 일이 일어나는지 봐{ph0}당신이 클릭 할 때." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " "JavaScript that builds a download." msgstr "작은 브라우저 앱을 사용하여 작업,네트워크 요청 및 JavaScript 즉,다운로드를 빌드합니다." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "이 가이드에서" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4020,7 +4028,7 @@ msgstr "{ph0}예{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4028,7 +4036,7 @@ msgstr "{ph0}브라우저 열기{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4036,7 +4044,7 @@ msgstr "{ph0}당신의 에이전트를 물어{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4044,13 +4052,13 @@ msgstr "{ph0}에서 캡처 CLI{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}요청 및 스크립트 읽기{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "내보내기를 클릭하면 어떻게 되나요?" @@ -4060,7 +4068,7 @@ msgstr "내보내기를 클릭하면 어떻게 되나요?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4071,7 +4079,7 @@ msgstr "" "그 {ph0}참고 브라우저 예{ph1} 이 {ph2}노트 내보내기{ph3} 버튼. 그것을 클릭하면 로드 {ph4},두 음을 다음과 같이 " "포맷합니다. CSV,그리고 다운로드를 시작합니다." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "에서 클릭하CSV다운로드" @@ -4082,7 +4090,7 @@ msgstr "에서 클릭하CSV다운로드" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4098,7 +4106,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4115,7 +4123,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4125,52 +4133,52 @@ msgstr "" "{ph0}03*귀하의 에이전트{ph1}{ph2}내보내기 코드 읽기{ph3}{ph4}관찰된 요청에 연결 {ph5} 그 안에 " "{ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "메모 내보내기를 클릭하기 전에 캡처를 시작합니다." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "오픈 Chrome 원격 디버깅" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " "debugging port. On Linux:" msgstr "별도의 브라우저 프로필과 로컬 디버깅 포트를 사용하여 호스팅 노트 예제를 엽니다. 시작 Linux:" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "예제 브라우저 시작" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "복사" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " "replace the page URL with another page you want to inspect." msgstr "사용된 브라우저의 실행 파일 경로에macOS또는Windows. 페이지를 검사할 다른 페이지로 바꿀 수 있습니다." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" " the action, and close the browser when finished." msgstr "REA연결하는 이러한 기존 브라우저입니다. 당신은 페이지의 제어를 유지 작업을 수행하고 완료되면 브라우저를 닫습니다." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "에이전트에게 한 가지 작업을 시청하도록 요청" @@ -4183,7 +4191,7 @@ msgstr "에이전트에게 한 가지 작업을 시청하도록 요청" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4195,7 +4203,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4206,7 +4214,7 @@ msgstr "" "내장?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4214,7 +4222,7 @@ msgid "" "URL. Let it start the capture before you click." msgstr "예 프롬프트. 에이전트에 디버깅 끝점 제공, {ph0} 그리고 페이지 당신이 클릭하기 전에 캡처를 시작하자." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4224,23 +4232,23 @@ msgstr "" "에이전트가 페이지 대상을 검색하고 관찰 창을 시작한 다음 결과 증거를 읽습니다. 그런 다음 내보내기 뒤에 스크립트를 검사 할 수 " "있습니다." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "또는 터미널에서 캡처" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "페이지의 대상 아이디 찾기:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "페이지 찾기" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4248,14 +4256,14 @@ msgid "" "ID, then run:" msgstr "참고 예제와 함께 대상을 선택합니다. 교체 {ph0} 그 아이디 아래,다음 실행:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "다음 10 초 캡처" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4264,7 +4272,7 @@ msgid "" msgstr "" "명령을 몇 초 동안 연결한 다음 을 클릭합니다 {ph0}노트 내보내기{ph1} 그 브라우저에서. 결과는 관찰 창이 끝난 후에 도착합니다." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4272,49 +4280,49 @@ msgid "" "this capture." msgstr "캡처된 결과에는 선택한 페이지,해당 창 중 네트워크 활동 및 응답 모양이 포함됩니다. 이전 요청은 이 캡처 외부에 있습니다." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "요청 및 내보내기 스크립트 읽기" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "녹음된 REA 4.1.0 로컬 노트 예제" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "캡처 된 사실" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "값" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "요청" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "응답" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "요청 시작자" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} *스크립트" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "응답 구조" @@ -4322,19 +4330,19 @@ msgstr "응답 구조" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} 함께 {ph1} 그리고 {ph2} 필드" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "로드된 스크립트 읽기" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4344,7 +4352,7 @@ msgstr "" "요청은 데이터 원본을 식별하고 REA 기록 {ph0} 그 시작자로서 캡처된 스크립트 원본을 읽고 데이터 사용 방법을 확인합니다:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4356,7 +4364,7 @@ msgstr "" "것을 설정합니다 {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4366,7 +4374,7 @@ msgstr "요청하는 스크립트 찾기 {ph0}. 쉼표 또는 따옴표가 포 #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4387,102 +4395,102 @@ msgid "" "inspect the request and follow the export script." msgstr "함께 노트 내보내기 관찰 REA:브라우저 페이지를 선택,클릭을 캡처,요청을 검사하고 내보내기 스크립트를 따르십시오." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "브라우저 관찰" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "복사 예제 브라우저 시작" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "예제 프롬프트 복사" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "복사 페이지 찾기" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "다음 10 초 캡처 복사" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "로드 된 스크립트 읽기 복사" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "개인정보보호정책" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}홈{ph1} /가이드" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA가이드에 있습니다." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " "guide includes a prompt, code and results." msgstr "네이티브 함수를 분석하면 Electron 내보내기 또는 브라우저 요청. 각 가이드에는 프롬프트,코드 및 결과가 포함됩니다." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "첫 번째 조사" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "설정REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "코딩 에이전트 연결 또는 사용 REA 터미널에서" -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "시작 REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "기계 코드 프로그램" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "왼쪽/오른쪽 사운드 위치 계산 복구" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4490,22 +4498,22 @@ msgid "" msgstr "" "로 시작 Windows 게임 실행 파일. 지시 사항을 검사하고,호출하는 함수를 따르고,숫자 상수를 읽고 복구 된 것을 확인하십시오." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "기계 코드 프로그램 분석 가이드" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "따라CSV내보내기" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4513,37 +4521,37 @@ msgid "" msgstr "" "작은 노트 앱은 렌더러,프리로드 및 메인 프로세스에 하나의 기능을 분산시킵니다. 사용REA연결하 API,IPC 채널 파일 작가입니다." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript&Electron가이드" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "더 큰 패키지 앱의 경우 다음을 수행합니다 {ph0}Notion클립보드 브리지의{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "브라우저 동작" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "클릭 관찰" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " "that turns its response into a download." msgstr "작업 노트 예제를 열고 내보내기 요청을 캡처한 다음 응답을 다운로드로 전환하는 코드를 찾습니다." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "브라우저 관찰 가이드" @@ -4560,12 +4568,12 @@ msgid "" "CSV export and a browser request." msgstr "학습 REA 짧은 작업 예제를 통해:네이티브 계산, Electron CSV 내보내기 및 브라우저 요청." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -4574,34 +4582,34 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}홈{ph1} / {ph2}가이드{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "추적 Electron{ph0}CSV 수출." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " "file writer." msgstr "따라 버튼을 클릭에서 페이지의 API 를 통해ElectronIPC 을CSV파일 작가입니다." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "이 가이드에서" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4609,7 +4617,7 @@ msgstr "{ph0}예{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4617,7 +4625,7 @@ msgstr "{ph0}당신의 에이전트를 물어{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4625,7 +4633,7 @@ msgstr "{ph0}내보내기 코드 추적{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4633,20 +4641,20 @@ msgstr "{ph0}예제 시도{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}검사 CSV 작가{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"노트 내보내기\"는 어디로 갑니까?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4658,7 +4666,7 @@ msgstr "" "기본 프로세스로 넘어가면서 이 페이지에서는 기본 프로세스로 넘어가면서 이 페이지에서는 기본 프로세스로 넘어가면서 CSV. 이 동작은 여러" " 파일에 분산되어 있습니다." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "이CSV내보내기 전Electron프로세스" @@ -4672,7 +4680,7 @@ msgstr "이CSV내보내기 전Electron프로세스" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4687,7 +4695,7 @@ msgstr "{ph0}렌더러→프리로드{ph1}{ph2}{ph3}{ph4}{ph5}{ph6} 에 의해 #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4702,7 +4710,7 @@ msgstr "{ph0}프로세스 간{ph1}{ph2}{ph3}{ph4}{ph5}기본 프로세스에 대 #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4713,13 +4721,13 @@ msgstr "{ph0}주요 과정{ph1}{ph2}내보내기 처리기{ph3}{ph4}{ph5} 그 #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} 메모의 형식을 지정합니다. {ph1} 글쓰기 {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -4729,14 +4737,14 @@ msgstr "" "REA치 리터럴 IPC 함수 호출 핸들러를 식별하고 노출된 API 를 사용합니다. 경로는 코드에서 추론됩니다.런타임 캡처는 실행되는 것을" " 확인할 수 있습니다." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "에 대해 물어 CSV 수출" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4752,14 +4760,14 @@ msgstr "{ph0}에이전트에 연결 REA{ph1} 그리고 그것을 응용 프로 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "복사" @@ -4770,7 +4778,7 @@ msgstr "복사" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4781,7 +4789,7 @@ msgstr "" "생성?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4789,7 +4797,7 @@ msgid "" "{ph0}." msgstr "예 프롬프트. 응용 프로그램 폴더에 대한 절대 경로를 포함하거나 {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -4799,17 +4807,17 @@ msgstr "" "REA 응용 프로그램 파일을 읽고 엔트리 포인트,모듈 및 프로세스 경계의 맵을 작성합니다. 에이전트가 해당 맵을 사용하여 조사 범위를 " "내보내기 기능으로 좁힙니다." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "내보내기 코드 추적" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "이 페이지는 작은 파일을 호출합니다." -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -4818,7 +4826,7 @@ msgstr "페이지는 메소드 이름을 알고 있습니다. 구현은 사전 #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4828,7 +4836,7 @@ msgstr "REA 기록 {ph0} 그리고 문자 그대로의 채널 {ph1}. 이 호출 #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4838,14 +4846,14 @@ msgstr "" "핸들러를 읽으면 원래 질문에 답합니다: {ph0} 메모의 형식을 지정하고 주요 프로세스는 씁니다 {ph1} 사용자의 다운로드 폴더에 " "넣습니다." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " "accompany the API, channel and handler findings." msgstr "녹음된 REA 4.1.0 아래 다운로드 가능한 예제에서. 소스 위치는 채널 및 핸들러 검색 결과와 함께 제공됩니다." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "예제를 직접 분석하십시오" @@ -4853,25 +4861,25 @@ msgstr "예제를 직접 분석하십시오" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}다운로드 예제 우편 번호{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "여섯 소스 파일을 찾아" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "정적 애플리케이션 분석" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4880,7 +4888,7 @@ msgid "" msgstr "" "경로를 압축을 푼 폴더로 바꿉니다. 하나의 채널 및 하나의 일치하는 핸들러를 찾아야합니다. {ph0}. 소스 위치는 {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -4890,13 +4898,13 @@ msgstr "" "자신의 앱의 경우 디렉터리와 동일한 명령을 사용하거나 ASAR 경로. 에이전트는 다음과 같이 리터럴 문자열,이름 또는 채널을 따를 수 " "있습니다 REA기능 추적 도구입니다." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "검사CSVwriter" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4904,7 +4912,7 @@ msgid "" "happens if writing the file fails?" msgstr "팔로우 {ph0} 그 담당자에게 어떤 입력들이 CSV 작성자,그리고 파일 작성이 실패하면 어떻게됩니까?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -4918,7 +4926,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4932,7 +4940,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4944,7 +4952,7 @@ msgstr "{ph0}브라우저 내보내기 관찰{ph1}{ph2}실제 클릭을 캡처 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4967,32 +4975,32 @@ msgstr "" "추적 NotesCSV수출을 통해 렌더러 API,미리 로드하고 IPC 처리기REA. 다운로드 가능한 예제 파일과 검증 된 분석 결과를 " "포함합니다." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "예제 프롬프트 복사" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "정적 애플리케이션 분석 복사" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -5001,34 +5009,34 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}홈{ph1} / {ph2}가이드{ph3} /기계 코드 프로그램 분석" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "복구 DX-Ball의{ph0}사운드 팬 계산." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " "check the recovered C." msgstr "원래 명령어를 검사하고 입력 및 상수를 식별 한 다음 복구 된 C을 확인하십시오." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "이 가이드에서" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5036,7 +5044,7 @@ msgstr "{ph0}예{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5044,7 +5052,7 @@ msgstr "{ph0}당신의 에이전트를 물어{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5052,7 +5060,7 @@ msgstr "{ph0}읽기 REA 결과{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5060,18 +5068,18 @@ msgstr "{ph0}복구 및 확인{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}자신의 바이너리 사용{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "왼쪽/오른쪽 스테레오 사운드 위치 계산" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5080,7 +5088,7 @@ msgstr "그 안에 DX-Ball,벽돌 타격은 수평 화면 위치를 제공합니 #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5091,7 +5099,7 @@ msgstr "" "시작 기능, {ph0},짧은 디컴파일러 결과가 있습니다. {ph1}. REA 또한 지시 사항과 호출자를 반환합니다.이는 에이전트에게 " "누락된 계산을 조사하는 방법을 제공합니다." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "이 약관에 새로운?" @@ -5100,7 +5108,7 @@ msgstr "이 약관에 새로운?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5111,7 +5119,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5123,7 +5131,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5134,7 +5142,7 @@ msgstr "{ph0}호출자:{ph1} 이 함수를 호출하는 함수입니다. 어떤 #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5144,7 +5152,7 @@ msgstr "{ph0}주소:{ph1} 프로그램에서 16 진수로 작성된 위치 {ph2} #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5152,7 +5160,7 @@ msgid "" "and decoded." msgstr "{ph0}상수:{ph1} 프로그램에 저장된 고정 번호는 원시 바이트로 읽고 디코딩." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "세 가지 증거,하나의 계산" @@ -5163,7 +5171,7 @@ msgstr "세 가지 증거,하나의 계산" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5179,7 +5187,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5196,7 +5204,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5206,14 +5214,14 @@ msgstr "" "{ph0}03*데이터 바이트{ph1}{ph2}숫자 상수{ph3}{ph4}참조된 바이트는 {ph5}, {ph6} 그리고 스케일 " "값.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " "interprets them together." msgstr "REA 명령어,호출 관계 및 바이트를 제공합니다. 에이전트는 그들을 함께 해석합니다." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "행동에 대해 물어보십시오" @@ -5222,7 +5230,7 @@ msgstr "행동에 대해 물어보십시오" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5232,19 +5240,19 @@ msgstr "" "그 후 {ph0}연결 REA 당신의 대리인에게{ph1} 그리고 {ph2}기본 분석 도구 설정{ph3},로컬 실행 파일 및 질문을 " "제공합니다:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "어떤 분석 도구를 사용해야합니까?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA 기본 프로그램을 읽기 위해 이들 중 하나가 필요합니다:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5257,7 +5265,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5269,7 +5277,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5278,7 +5286,7 @@ msgstr "{ph0}IDA{ph1} (Windows):기존의 IDA 설치 MCP 등록." #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5292,14 +5300,14 @@ msgstr "보시다시피 {ph0}기계 코드 프로그램 분석 설정{ph1} 단 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "복사" @@ -5310,7 +5318,7 @@ msgstr "복사" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5320,7 +5328,7 @@ msgstr "" "{ph0}›{ph1}{ph2}사용 REA 방법을 찾으려면 DX-Ball 사운드 패닝을 계산합니다. 계산을 설명하고 코드를 " "보여줍니다.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5330,7 +5338,7 @@ msgstr "" "예 프롬프트. 너의 대리인에게 너의 지방 주민에 경로를 주십시요 DX-Ball 1.07 실행 파일. REA 포함하지 않습니다 DX-" "Ball,그래서 당신 신 사,또는 다른 대 문 같 류 Windows 당신이 가진 프로그램." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "파일의 전체 경로를 어떻게 얻을 수 있습니까?" @@ -5339,7 +5347,7 @@ msgstr "파일의 전체 경로를 어떻게 얻을 수 있습니까?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5353,7 +5361,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5365,7 +5373,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5373,30 +5381,30 @@ msgid "" "appears." msgstr "{ph0}모든 시스템:{ph1} 파일을 터미널 창으로 드래그하면 해당 경로가 나타납니다." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "읽REA결과" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "입력 읽기" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " "arithmetic. This is the input absent from the first pseudocode view." msgstr "명령은 정수 인수를 로드하고 부동 소수점 계산으로 변환합니다. 이것은 첫 번째 유사 코드 뷰에서 없는 입력입니다." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "호출하는 함수 팔로우" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5405,24 +5413,24 @@ msgid "" msgstr "" "REA 브릭 히트 호출자를 식별합니다. 이전 명령은 타일 좌표에 30 을 곱합니다. {ph0} (20)벽돌의 화면 위치를 제공합니다." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "참조된 상수 읽기" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " "actual values; the instruction order tells the agent how they are used." msgstr "산술은 이러한 주소를 참조합니다. 바이트를 읽으면 실제 값이 제공되며,명령 순서는 에이전트에 어떻게 사용되는지 알려줍니다." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "복구 된 기능 작성 및 확인" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5432,7 +5440,7 @@ msgstr "" "눈금이 1.0 인 경우 화면 위치 0,320 및 640 은 정수 변환 전에 -500,0 및 500 으로 매핑됩니다. 계산은 화면의 중심을" " 스테레오 필드의 중앙에 놓습니다." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5443,20 +5451,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}전체 조사 및 어셈블리 간 비교를 참조하십시오{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "자신의 바이너리 그것을 시도" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5468,20 +5476,20 @@ msgstr "" "{ph0}기계 코드 프로그램 공급자의 분석을 연결{ph1},그런 다음 에이전트에 로컬 실행 파일 또는 라이브러리와 조사 할 기능을 " "제공하십시오. 유용한 시작 질문에는\"이 파일은 어떻게 분석됩니까?\"또는\"이 메뉴 동작을 처리하는 기능은 무엇입니까?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " "terminal. For a configured Ghidra installation:" msgstr "함수 이름 또는 주소를 이미 알고 있는 경우 터미널에서 쿼리할 수 있습니다. 구성된 Ghidra 설치:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "기능 분석" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5493,7 +5501,7 @@ msgstr "" "대상 경로를 대체하고 {ph0} 자신의 함수 이름 또는 주소로. 각 CLI 호출은 바이너리를 가져오고 분석 한 다음 세션을 닫습니다. " "귀하의 에이전트의 MCP 쿼리는 해당 세션이 열려 있는 동안 가져온 바이너리를 다시 사용합니다." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5513,50 +5521,50 @@ msgid "" "caller, read constants and check reconstructed C." msgstr "기본 계산 복구 REA:지시 사항을 검사하고,호출하는 함수를 따르고,상수를 읽고 재구성 된 것을 확인하십시오." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "기계 코드 프로그램 분석" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "예제 프롬프트 복사" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "복사 함수 분석" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "개인정보보호정책" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "설정REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5564,7 +5572,7 @@ msgstr "{ph0}설정 REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5572,7 +5580,7 @@ msgstr "{ph0}다시 무엇입니까?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5580,7 +5588,7 @@ msgstr "{ph0}REA가 돕는 방법{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5588,7 +5596,7 @@ msgstr "{ph0}공룡 게임{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5596,7 +5604,7 @@ msgstr "{ph0}계산기{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5604,7 +5612,7 @@ msgstr "{ph0}시도해봐 REA{ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5612,7 +5620,7 @@ msgstr "{ph0}더 깊이 알아보기{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5620,25 +5628,25 @@ msgstr "{ph0}도움말 및 피드백{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}커뮤니티{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "코딩 에이전트와 함께 리버스 엔지니어링" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "소프트웨어가{ph0}어떻게 작동하는지 알아보세요." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5647,7 +5655,7 @@ msgstr "REA는 코딩 에이전트가 프로그램을 조사하고 동작을 설 #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5655,13 +5663,13 @@ msgstr "이미 다시 알고? {ph0}분석 가이드로 건너뛰기.{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "더 깊이 가고 싶습니까? {ph0}블로그 읽기→{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "이 프롬프트를 코딩 에이전트에 붙여 넣으세요:" @@ -5674,38 +5682,38 @@ msgstr "이 프롬프트를 코딩 에이전트에 붙여 넣으세요:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "복사" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "터미널에서 직접 실행할 수도 있습니다:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "설정 변경 계획을 확인하고 승인한 뒤 에이전트를 다시 시작하세요." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "리버스 엔지니어링이란?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5718,7 +5726,7 @@ msgstr "{ph0}프로그램 자체를 조사해서{ph1} 소프트웨어의 작동 #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5728,7 +5736,7 @@ msgstr "목표:충분히 기능을 이해 {ph0}그것을 설명{ph1}, {ph2}변 #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -5736,7 +5744,7 @@ msgstr "REA 사용 전 · {ph0}직접{ph1} 조사합니다" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -5744,7 +5752,7 @@ msgstr "{ph0}01{ph1} 분기 디코딩" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -5752,7 +5760,7 @@ msgstr "{ph0}02{ph1} 추적 호출" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -5762,20 +5770,20 @@ msgstr "{ph0}03{ph1} 규칙 복구" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}원본 64*선택한 지침{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01*어떤 지점?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5783,29 +5791,29 @@ msgid "" "these?”" msgstr "“{ph0}? -그래?{ph1} 같은 장소에 두 점프. 이들은 어떤 연산자입니까?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "명령 아이디를 조회 한 다음 브랜치에 레이블을 지정하십시오." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "분÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "곱하기×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · 호출된 함수는 무엇을 하나요?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5813,24 +5821,24 @@ msgid "" "value goes in?{ph1}”" msgstr "100 은 분명하다. 전화는 단지 주소 일뿐입니다. {ph0}어느 쪽이 나눌까요? 어떤 값이 들어가나요?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "도우미 함수를 검사하고 저장된 값을 추적합니다." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "나누기" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03*규칙은 무엇입니까?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5838,19 +5846,19 @@ msgid "" "after +.”" msgstr "\"이 경로는 다른 입력으로 곱합니다. 그래서 {ph0}10%는 200 의 10%를 의미합니다.{ph1} +후”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "피연산자의 이름을 지정하고 두 연산자 경로를 모두 확인하십시오." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "예시 전문가 추론" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5860,20 +5868,20 @@ msgstr "{ph0}당신은 명령을 디코딩 함수 호출을 따라 계산을 재 #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "REA 사용 시 · {ph0}에이전트{ph1}에게 묻습니다" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "프롬프트 하나면 됩니다." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -5887,49 +5895,49 @@ msgstr "에이전트에게 {ph0}일상적인 말로{ph1} 질문하세요." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}예제 프롬프트*계산기" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "예제 답변·결과에 따라" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "+후,%버튼이 걸립니다 {ph0}첫 번째 숫자의 백분율.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA가 제공하는 정보" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "핸들러의 명령,디 컴파일 된 코드 및 호출." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "에이전트가 설명하는 내용" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "어떤 분기가 적용되는지,무엇을 계산하고 다시 작성하는 방법." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5939,7 +5947,7 @@ msgstr "설치된 계산기에서 선택한 어셈블리. 생각과 대답은 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5947,37 +5955,37 @@ msgid "" "Calculator and rebuild its % button." msgstr "{ph0}두 가지 예를 들어 보겠습니다.{ph1} 게임의 속도를 변경 한 다음 계산기로 돌아가서%버튼을 다시 작성하십시오." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "예 01·Chrome's 룡 게임" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "공룡은 왜 점점 빨라질까요?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "목표" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "와 게임을 다시 {ph0}조정 가능한 속도.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "왜 그것을 리버스 엔지니어링합니까?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5985,61 +5993,61 @@ msgid "" "game{ph1}: how fast it starts, how much it increases and when it stops." msgstr "가속도를 재현하려면 {ph0}실행중인 게임의 규칙{ph1}:얼마나 빨리 시작,얼마나 증가하고 멈출 때." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "재구성한 게임 플레이" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "시작" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "점프 ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "다시 시작" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "속도" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "복구된 가속 규칙 사용" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "원래 규칙:6 에서 시작한 다음 13 으로 늘립니다." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "자신의 속도를 설정하는 슬라이더를 이동합니다. 공간 또는 점프는 선인장을 지 웁니다." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "사용JavaScript을 재생하는 재건. 위의 코드와 설명은 읽을 수 있습니다." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA가 반환한 결과" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6057,7 +6065,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6069,7 +6077,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}예제 프롬프트*공룡 게 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6082,7 +6090,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6094,7 +6102,7 @@ msgstr "검사 대상: {ph0}와이우의 Chromium-파생 브라우저 에디션{ #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6103,12 +6111,12 @@ msgid "" msgstr "" "{ph0}시작 6.{ph1} 추가 {ph2}0.001{ph3} 충돌없이 각 업데이트,속도가 아래에있는 동안 {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "스피드 랩을 엽니다." -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "각 부분이 하는 일" @@ -6119,7 +6127,7 @@ msgstr "각 부분이 하는 일" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6135,7 +6143,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6151,7 +6159,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6160,13 +6168,13 @@ msgid "" msgstr "" "{ph0}03*당신{ph1}{ph2}속도 변경 및 재생{ph3}{ph4}원래 가속을 시도한 다음 자신의 페이스를 선택하십시오.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "스크립트,검사 및 분석 시도 방법을 참조하십시오" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6176,7 +6184,7 @@ msgstr "" "REA 로컬 디버깅 연결을 통해 <URL> 브라우저 버전을 검사하고 로드된 버전을 반환했습니다. {ph0},그 원천과 다이제스트를 " "포함합니다." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6188,7 +6196,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6203,7 +6211,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6219,26 +6227,26 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" "{ph0}Inspected speed code{ph1} · {ph2}Chromium Authors · BSD license{ph3}" msgstr "{ph0}검사된 속도 코드{ph1} · {ph2}Chromium 저자*비스 디 라이센스{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "예 02·Windows계산기" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "계산기의 % 버튼을 재현해 봅니다." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6247,7 +6255,7 @@ msgstr "처리하는 작은 계산기를 구축 {ph0}+및 2018 년 11 월 13 일 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6257,29 +6265,29 @@ msgstr "" "같은 버튼 사용 {ph0}+및 2019 년 이후의 다른 규칙.{ph1} 우리는 비율이 적용되는 번호를 찾기 위해 설치된 응용 프로그램을 " "검사합니다." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "계산 시도" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "초기화" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10%의 200=20. 그런 다음 200+20=220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "검사된 백분율 규칙의 대화형 그림입니다." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6291,7 +6299,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6305,7 +6313,7 @@ msgstr "이 예제에서는, {ph0} 그리고 {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6319,7 +6327,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}예제 프롬프트*%단추 다 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6330,7 +6338,7 @@ msgstr "" "{ph0}›{ph1}{ph2}사용 REA 검사 Windows 계산기의%버튼. +와 200 이후의 규칙을 복구 한 다음 둘 다 사용하는 " "작은 계산기를 만듭니다.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "+와 함께" @@ -6338,13 +6346,13 @@ msgstr "+와 함께" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}첫 번째 숫자의 10%를 가져 가라.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "와×" @@ -6352,13 +6360,13 @@ msgstr "와×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}10%를 0.1 로 바꿉니다.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "설치된 앱에서 작동%버튼으로" @@ -6370,7 +6378,7 @@ msgstr "설치된 앱에서 작동%버튼으로" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6387,7 +6395,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6398,12 +6406,12 @@ msgstr "" "{ph0}03*당신의 에이전트는 그것을 해석{ph1}{ph2}규칙 설명 및 재현{ph3}{ph4}마이크로 소프트의 소스와 지점을 교차 " "검사 한 다음 위의+및 200 을 시도하십시오.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "실제 코드 및 답변 확인 방법 보기" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6423,7 +6431,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6431,29 +6439,29 @@ msgid "" "{ph4}Native setup guide{ph5}" msgstr "{ph0}백분율 구현{ph1} · {ph2}마이크로소프트의 테스트 케이스{ph3} · {ph4}기본 설정 가이드{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "첫 번째 조사" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "시도해봐 REA 작은 응용 프로그램에." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " "input." msgstr "우리의 노트 예제를 다운로드,그 추적 CSV 수출,하나의 변경된 입력을 확인합니다." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "가이드 예제를 사용해보십시오" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "더 깊이 알아보고 싶나요?" @@ -6462,7 +6470,7 @@ msgstr "더 깊이 알아보고 싶나요?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6481,13 +6489,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}프롬프트 예*웹 사이트" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "예,이 하나." @@ -6500,7 +6508,7 @@ msgstr "예,이 하나." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6513,7 +6521,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}예제 프롬프트*게임 재 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6526,69 +6534,69 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}보 DX-Ball 사례 연구→{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "설정 및 분석 단계에서 대상을 선택합니다:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "기계 코드 프로그램" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" " and libraries." msgstr "실행 파일 및 라이브러리에서 함수,문자열,참조 및 함수 호출 관계를 검사합니다." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "기계 코드 프로그램 분석 가이드" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " "or ASAR archive." msgstr "응용 프로그램 폴더에서 모듈,경로 및 기본 종속성을 매핑하거나 ASAR 아카이브" -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "애플리케이션 워크플로" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "브라우저 및 런타임 활동" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " "across runs." msgstr "선택한 브라우저 또는 프로세스 활동을 캡처 한 다음 여러 실행에서 결과를 비교합니다." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "브라우저 관찰 가이드" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "궁금한 점이 있나요?" @@ -6599,7 +6607,7 @@ msgstr "궁금한 점이 있나요?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6609,12 +6617,12 @@ msgstr "" "{ph0}자주 묻는 질문 읽기{ph1}, {ph2}에 우리와 함께 채팅 Discord{ph3},또는 {ph4}오픈 GitHub " "문제{ph5} 버그 및 기능 요청." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "커뮤니티 참여" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -6635,64 +6643,64 @@ msgstr "" "코딩 에이전트를 사용하여 앱,바이너리 및 브라우저 동작을 리버스 엔지니어링합니다. 명확한 가이드를 따라 대화 형 예제를 사용해보십시오 " "REA." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "복사REA설치 프롬프트" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "설치 명령 복사" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "수동 계산기 분석을 따르십시오" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "복사 계산기 백분율 질문" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "공룡 미니 게임. 게임이 집중되는 동안 점프 버튼을 누르거나 공간을 사용합니다." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "복사 공룡 분석 프롬프트" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "계산 선택" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "복사 계산기 분석 프롬프트" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "웹 사이트 프로젝트 프롬프트 복사" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "복사 게임 재건 프롬프트" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -6701,25 +6709,25 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}홈{ph1} / {ph2}쇼케이스{ph3} /안드로이드" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "사례 연구·Aegis인증" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "인증자는 어떻게{ph0}로그인 코드를 생성 하시겠습니까?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -6728,17 +6736,17 @@ msgstr "" "6 자리 코드는 30 초마다 변경됩니다. 사용 REA 안드로이드에서 계산을 찾으려면 APK,그리고 당신이 제어할 수 있는 시계로 다시 " "만들죠." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis3.4.3·안드로이드·공식 출시APK·6.9MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "보기 Aegis 시작 GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "에서APK코드를 재현할 수 있습니다" @@ -6749,7 +6757,7 @@ msgstr "에서APK코드를 재현할 수 있습니다" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6766,7 +6774,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6783,7 +6791,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6794,14 +6802,14 @@ msgstr "" "{ph0}03*재 구축 및 확인{ph1}{ph2}시계를 변경하십시오. 코드를 보세요.{ph3}{ph4}새로운 브라우저 데모는 규칙을 " "재현하고 공개 참조 사례에 대해 확인합니다.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "이 사례 연구에서" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -6809,7 +6817,7 @@ msgstr "{ph0}당신의 에이전트를 물어{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -6817,7 +6825,7 @@ msgstr "{ph0}코드 생성기 사용해보기{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -6825,7 +6833,7 @@ msgstr "{ph0}코드 찾기 REA{ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -6833,7 +6841,7 @@ msgstr "{ph0}계산 읽기{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -6841,20 +6849,20 @@ msgstr "{ph0}재건 확인{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}검사 APK 너 자신{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "당신의 에이전트를 물어" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6872,14 +6880,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "복사" @@ -6887,7 +6895,7 @@ msgstr "복사" # Reviewed for concrete meaning, software terminology and readable sentences. #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6897,7 +6905,7 @@ msgstr "" "다운로드한 APK를 분석하는 예시 프롬프트입니다. 먼저 REA의 Android 분석 환경을 설정하세요. {ph0}APK와 분석 설정 받기" " ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "코드 생성기 사용해보기" @@ -6905,7 +6913,7 @@ msgstr "코드 생성기 사용해보기" # Reviewed for concrete meaning, software terminology and readable sentences. #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6916,33 +6924,33 @@ msgstr "" "앱은 시간을 {ph0}30초 단위로 나눕니다.{ph1} 시간 구간 번호와 계정 키를 결합해 코드를 생성합니다. 같은 키와 같은 시간 " "구간이면 같은 코드가 나옵니다." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "60 초에 걸쳐 시계를 이동" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "시간" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "초" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "우리의 조정 가능한 예제 시계" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30 초 블록" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "블록" @@ -6951,35 +6959,35 @@ msgstr "블록" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 초{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "생성된 코드" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "계정 키+블록 6 자리 숫자" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "예제 시간(초)" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 초" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 초" @@ -6988,7 +6996,7 @@ msgstr "60 초" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6999,7 +7007,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7007,25 +7015,25 @@ msgid "" "the calculation recovered from the APK." msgstr "키는 고정,공개 {ph0}6238 테스트 데이터{ph1}. 데모에서 복구 된 계산을 구현 APK." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " "clock." msgstr "다이어그램은 59 초에 결과를 보여줍니다. 활성화 JavaScript 시계를 바꾸기 위해서." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "코드를 찾으로REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "좁은 APK 세 가지 클래스" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7034,14 +7042,14 @@ msgid "" msgstr "" "{ph0} 계산 후보입니다.다른 두 개는 진행률 표시줄과 가져온 계정에 관한 것입니다. TOTP 시간 기반 일회성 암호를 의미합니다." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "생성기를 앱의 디스플레이에 연결" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7052,7 +7060,7 @@ msgstr "" "{ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7060,14 +7068,14 @@ msgid "" "{ph0} prefix." msgstr "요청은 단축된 입력 경로를 표시합니다. 결과 클래스 이름은 공통 클래스를 생략합니다. {ph0} 사전" -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "계산 읽기" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7080,7 +7088,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7088,7 +7096,7 @@ msgstr "{ph0}01{ph1} 시간 차단" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7096,7 +7104,7 @@ msgstr "{ph0}02{ph1} 키+블록" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7104,7 +7112,7 @@ msgstr "{ph0}03{ph1} 여섯 자리" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7115,7 +7123,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7128,7 +7136,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7142,7 +7150,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7151,7 +7159,7 @@ msgid "" msgstr "" "여러 검사 방법에서 발췌,디스플레이 라인 포장. 오른쪽 패널은 설명 요약입니다. {ph0}Aegis 코드는 다음과 같습니다.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "발전기 내부" @@ -7160,7 +7168,7 @@ msgstr "발전기 내부" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7170,7 +7178,7 @@ msgstr "" "석방 된 사람 들 APK 풋 {ph0} 그 안에 {ph1}. REA 에서 함수 호출를 다음과 {ph2} 그리고 이 몸을 반환합니다.원래의" " 소스는 도우미를 호출합니다. {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7185,20 +7193,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}일치하는 릴리스 소스와 비교{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "재건 확인" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7209,29 +7217,29 @@ msgstr "" "우리는 선택한 것을 조립했습니다 REA-작은 테스트 프로그램에서 자바 메소드를 반환했습니다. 그들의 출력은 독립적인 재구성과 " "일치했습니다. {ph0}133 테스트 케이스{ph1} 시간 블록 경계와 0 으로 시작하는 코드를 포함합니다." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "예제 시간" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "6 자리 코드" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 초" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 초" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7241,38 +7249,38 @@ msgstr "" "발전기는 또한 6 개의 발표된 것과 일치합니다. SHA-1 참조 사례 {ph0}6238{ph1}. 그들에 대한 브라우저 구현을 " "확인하십시오:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "참조 검사 실행" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "데모 계산 읽기" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" "digit results." msgstr "참조 케이스는 8 자리 숫자를 사용합니다. 이 검사는 또한 6 자리 결과를 확인합니다." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " "was inspected statically." msgstr "검증은 추출 된 자바 메소드와 새로운 데모를 실행합니다. 안드로이드APK검열되었으로 합니다." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "검사 APK 너 자신" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7284,7 +7292,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7292,18 +7300,18 @@ msgid "" "{ph1}. This case used JDK 21." msgstr "안드로이드 분석은 전체 17 이상 필요합니다. 함께 선택 {ph0} 또는 {ph1}. 이 사건은 21 번을 사용했습니다." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "포인트 REA 공급자 파일에서 검사 APK:" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7315,7 +7323,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7323,7 +7331,7 @@ msgid "" "different time interval?{ph1}" msgstr "다음 질문: {ph0}계정이 8 자리 또는 다른 시간 간격을 사용할 때 어떤 일이 발생합니까?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "출처" @@ -7339,7 +7347,7 @@ msgstr "출처" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7351,13 +7359,13 @@ msgstr "{ph0}공식 Aegis 3.4.3 릴리스{ph1} · {ph2}일치하는 소스 커 #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}6238 참조 사례{ph1} · {ph2}데모 테스트 데이터{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7379,37 +7387,37 @@ msgid "" "calculation and try a reconstruction with an adjustable clock." msgstr "검사Aegis안드로이드APK와REA,복 그 자리에 로그인 코드 계산 하고 재건을 가진 조정가능한 시계입니다." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "AegisAPK사례 연구" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "복사 Aegis 프롬프트 예" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "로그인 코드 계산을 따르십시오" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "복사APK명령 검사" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -7418,26 +7426,26 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}홈{ph1} / {ph2}쇼케이스{ph3} /" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "사례 연구*2023 년" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "깃발 찾기{ph0}바이너리." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7445,17 +7453,17 @@ msgid "" "find an input that makes the original program print {ph0}." msgstr "사용 REA 작은 플래그 검사기를 검사하려면 규칙을 방정식으로 바꾸고 원래 프로그램을 인쇄하는 입력을 찾으십시오 {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "크 사각형 국기 검사기·조명·Linuxx86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "원래 도전 보기" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "바이너리에서 체크된 답으로" @@ -7466,7 +7474,7 @@ msgstr "바이너리에서 체크된 답으로" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7483,7 +7491,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7500,7 +7508,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7511,20 +7519,20 @@ msgstr "" "{ph0}03*해결 및 실행{ph1}{ph2}복구 된 플래그가 올바른지 확인하십시오!{ph3}{ph4}파이썬 스크립트는 방정식을 " "해결합니다. REA 결과를 받아들이는 원래 프로그램을 캡처합니다.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "이 도전은 조셉의 작품으로,다운더크의 공식 저장소에 출판되었습니다." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "이 사례 연구에서" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7532,7 +7540,7 @@ msgstr "{ph0}검사 코드 찾기{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7540,7 +7548,7 @@ msgstr "{ph0}하나의 마스크 읽기{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7548,7 +7556,7 @@ msgstr "{ph0}읽을 수있는 코드로 어셈블리{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7556,7 +7564,7 @@ msgstr "{ph0}방정식 풀기{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7564,20 +7572,20 @@ msgstr "{ph0}답변 확인{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}그것을 자신을 시도{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "검사 코드 찾기" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7595,17 +7603,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "복사" @@ -7616,7 +7624,7 @@ msgstr "복사" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7627,33 +7635,33 @@ msgstr "" "{ph0}›{ph1}{ph2}사용 REA 그리고 플래그를 찾을 수 있습니다. 검사가 어떻게 작동하는지 설명 한 다음 원래 프로그램으로 " "답을 확인하십시오.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " "native analysis provider connected." msgstr "다운로드 한 도전을 로컬에서 사용할 수 있고 기계 코드 프로그램 분석 제공자가 연결된 예제 프롬프트." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "입력 프롬프트를 따라 해당 기능을 수행합니다" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " "executable's original function names have been removed." msgstr "이 참조는 실행 파일의 원래 함수 이름이 제거되었음에도 불구하고 에이전트에게 조사할 장소를 제공합니다." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "검사기 및 두 도우미 읽기" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7664,7 +7672,7 @@ msgstr "" "첫 번째 루프는 36 자 코드를 복사합니다. 검사 루프는 마스크를 해독하고 선택한 코드를 합산하고 결과를 저장된 번호와 비교합니다. " "그것의 {ph0}-바이트 단계 {ph1} 바이트는 26 개의 마스크를 제공합니다." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -7673,12 +7681,12 @@ msgstr "" "이들은 신선한 결과에서 선택된 결과입니다. REA 분석. 로컬 대상 경로는 표시를 위해 단축됩니다.주소는 다음을 참조합니다. REA가져온" " 이미지입니다." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "한 번 확인하면 한 명의 캐릭터가 나타납니다." -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -7690,13 +7698,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "일곱 번째 검사는 하나의 위치를 선택합니다. {ph0}열린 그림{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "바이너리에서 마스크 및 대상 읽기" @@ -7705,7 +7713,7 @@ msgstr "바이너리에서 마스크 및 대상 읽기" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7716,12 +7724,12 @@ msgstr "" "지시 {ph0} 마스크 바이트를 부호있는 값으로 읽습니다. 이것이 바로 {ph1} -21 을 의미합니다. 목표는 작은 엔디안 정수입니다." " 이 바이트는 에이전트에게 {ph2},그래서 그 캐릭터는 {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "지시 사항부터 읽을 수 있는 검사까지" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -7730,7 +7738,7 @@ msgstr "합산 도우미와 해당 호출 함수를 동일한 규칙에 연결 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -7738,7 +7746,7 @@ msgstr "{ph0}01{ph1} 시작" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -7746,7 +7754,7 @@ msgstr "{ph0}02{ph1} 선택" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -7754,7 +7762,7 @@ msgstr "{ph0}03{ph1} 추가" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -7762,18 +7770,18 @@ msgstr "{ph0}04{ph1} 사전" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} 비교" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA·선택한 원래의 지침" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "읽기 쉬운 씨*원 체크 요약" @@ -7781,7 +7789,7 @@ msgstr "읽기 쉬운 씨*원 체크 요약" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -7789,7 +7797,7 @@ msgstr "{ph0}01*0 에서 시작합니다.{ph1} {ph2} 실행 금액을 보유합 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7799,7 +7807,7 @@ msgstr "{ph0}02*마스크 셀을 확인합니다.{ph1} 0 값은 문자를 건너 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7809,7 +7817,7 @@ msgstr "{ph0}03*문자 코드를 추가합니다.{ph1} 같은 오프셋에 있 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7822,7 +7830,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7830,19 +7838,19 @@ msgid "" "in {ph2}. A mismatch jumps to {ph3}." msgstr "{ph0}05*저장된 대상과 비교.{ph1} 호출 함수는 {ph2}. 불일치가 {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " "explanatory summary with descriptive names and a flattened 36-cell loop." msgstr "지침은 합산 도우미 및 호출 함수에서 제공됩니다. 다 설명 요약 설명 이름과 평평한 36 셀 루프." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "26 방정식 풀기" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -7852,13 +7860,13 @@ msgstr "" "대부분의 마스크는 여러 셀을 선택합니다. 예를 들어,첫 번째 검사는 16 개의 문자 코드를 추가하고 총 1441 개가 필요합니다. 겹치는" " 선택은 작은 파이썬 스크립트가 함께 풀 수 있는 방정식을 제공합니다." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "파이썬*솔버 발췌" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7870,19 +7878,19 @@ msgstr "" "지 3 이 방정식을 만족시키는 값을 찾는 솔버입니다. 이 발췌문은 추출 된 검사를 사용하고 다음을 가정합니다 {ph0} 문자,숫자,밑줄 " "및 중괄호가있는 플래그. 전체 다운로드에는 26 개의 마스크와 타겟이 모두 포함되어 있습니다." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "전체 해결사 다운로드" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "원래 프로그램으로 답을 확인" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7893,59 +7901,59 @@ msgstr "" "REA'프로세스 캡처'는 해결된 플래그를 받아들이는 원래 실행 파일을 기록합니다. 에서 선택한 문자 하나를 변경 {ph0} 에 {ph1}" " 첫 번째 합계를 만든다 1440 대신 1441,프로그램은 그것을 거부." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "입력" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "관찰된 산출" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "종료 코드" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "솔버의 깃발" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "한 문자 변경" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "복구된 플래그 및 캡처된 출력 표시" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA·원래 출력 프로그램" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "플래그 복사" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " "challenge metadata, checked after solving the binary." msgstr "복구된 값은 또한 조직자의 게시된 챌린지 메타데이터의 플래그와 일치하며,바이너리를 해결한 후 확인됩니다." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "출처,대상 신원 및 분석 세부 정보" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -7955,7 +7963,7 @@ msgstr "" "신선한 분석 및 두 개의 프로세스를 캡처에서 8 월 2026 를 사용하여,REA4.1.0 와Ghidra12.1.4 에Linuxx64. " "바이너리는 86-64 엘프,15,248 바이트입니다." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -7975,7 +7983,7 @@ msgstr "문자열 참조,함수 및 상수는 조직자의 소스 또는 솔루 #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7984,12 +7992,12 @@ msgid "" msgstr "" "{ph0}주최자의 출처와 비교{ph1} · {ph2}챌린지 메타데이터 및 플래그{ph3} · {ph4}REA 증거 노트{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "그것을 자신을 시도" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -7997,13 +8005,13 @@ msgid "" msgstr "" "하나의 폴더에 원래의 도전과 솔버를 다운로드합니다. 위의 프롬프트를 사용하여 에이전트와 함께 조사하거나 포함된 스크립트를 실행합니다." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "터미널*해결 및 실행" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8014,7 +8022,7 @@ msgstr "" "이 스크립트는 후보 플래그를 인쇄;프로그램의 프롬프트에 붙여 넣습니다. 해결은 파이썬과 {ph0}. 원래 실행 파일 실행 필요 Linux" " 86-64 번" -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "설정 REA 코딩 에이전트와 함께" @@ -8034,27 +8042,27 @@ msgstr "" "사용REA를 해결하 DownUnderCTF 마스크의 사각형 국기 검사기입니다. 검사 기능을 찾아 마스크를 추출하고 복구 된 플래그를 원래" " 프로그램과 비교하십시오." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "플래그 검사기 사례 연구" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "예제 프롬프트 복사" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "작은 화면에서 가로로 스크롤" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8064,42 +8072,42 @@ msgstr "" "일곱 번째 마스크는 21 개의 셀을 건너 뛰고 위치 21 을 선택한 다음 14 를 건너 뜁니다. 그 셀만이 합에 기여합니다. 필요한 문자" " 코드는 55 입니다.즉,문자는 7 입니다." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "클릭률 확인을 따르십시오" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "어셈블리 복사" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "읽을 수 있는 클릭률 확인 복사" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "복사 클릭률 솔버 발췌" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "복구 된 플래그 복사" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "명령 복사" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -8108,26 +8116,26 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}홈{ph1} / {ph2}쇼케이스{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "사례 연구·DX-Ball1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "재건 DX-Ball{ph0}실행 파일에서." # Reviewed for concrete meaning, software terminology and readable sentences. -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8136,14 +8144,14 @@ msgstr "" "목표는 1996년에 나온 Windows 게임을 유지보수 가능한 C 코드로 재구성하는 것입니다. REA는 에이전트가 원본 함수를 하나씩 " "분석하도록 돕습니다." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windowsi386·C·REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8154,14 +8162,14 @@ msgstr "" "하나의 기능,실행 파일에서 확인 된 C. REA 지침,호출자 및 데이터 읽기를 제공하고 재구성 프로젝트는 결과를 구현하고 테스트합니다. " "{ph0}열린 그림{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "이 사례 연구에서" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8169,7 +8177,7 @@ msgstr "{ph0}프로젝트{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8177,7 +8185,7 @@ msgstr "{ph0}사운드 팬{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8185,23 +8193,23 @@ msgstr "{ph0}결과 확인{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}작업을 계속{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "유지 된 기능" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "원본 코드와 비교" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "컴파일된 바이트가 일치하는 함수" @@ -8212,7 +8220,7 @@ msgstr "컴파일된 바이트가 일치하는 함수" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8220,12 +8228,12 @@ msgid "" "coverage{ph3}" msgstr "프로젝트 체크 포인트:2026 년 10 월 7 일. {ph0}진행 원장{ph1} · {ph2}테스트 범위{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "지금까지의 프로젝트" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8237,12 +8245,12 @@ msgstr "" "복구 된 코드는 보드 및 리소스 처리,벽돌 히트,애니메이션,입자 및 보너스 생산을 포함합니다. 현재 빌드는 검사 유틸리티와 분석 " "라이브러리를 제공합니다. 재생 가능한 게임에 대한 작업은 공 및 패들 물리학,파워 업 처리 및 Windows 통합." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "왼쪽/오른쪽 사운드 위치 계산 찾기" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8260,17 +8268,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "복사" @@ -8281,7 +8289,7 @@ msgstr "복사" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8291,7 +8299,7 @@ msgstr "" "{ph0}›{ph1}{ph2}사용 REA 방법을 찾으려면 DX-Ball 사운드 패닝을 계산합니다. 계산을 설명하고 코드를 " "보여줍니다.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8300,7 +8308,7 @@ msgid "" msgstr "로컬 실행 파일을 사용할 수 있는 코딩 에이전트에 대한 예제 프롬프트입니다. 아래의 조사는 REA 답변 뒤에 쿼리 및 증거." # Reviewed for concrete meaning, software terminology and readable sentences. -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8313,7 +8321,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8325,30 +8333,30 @@ msgstr "" "에 대한 함수의 첫 번째 분석 결과 {ph0} 포함 된 의사 코드 선언 {ph1} 그리고 전화 {ph2}. 명령어 뷰는 스택 입력과 부동" " 소수점 연산을 보여주었습니다. 그 불일치로 인해 에이전트는 계속 조사해야 할 구체적인 이유를 얻었습니다." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "첫 번째 디 컴파일러 뷰" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " "the input and the calculation feeding that call." msgstr "출력은 전환 호출을 보여줍니다. 아래의 지침을 읽는 것은 입력 및 통화 공급 계산을 알 수있다." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "세 가지 질문에 대한 답변 REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "누락된 입력 복구" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8357,14 +8365,14 @@ msgid "" msgstr "" "함수 결과에는 의사 코드 및 호출 함수와 함께 명령어가 포함됩니다. 여기, {ph0} 디컴파일러 보기에서 누락된 정수 입력을 노출합니다." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "호출하는 함수를 따라 입력 내용을 파악합니다" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8374,24 +8382,24 @@ msgstr "" "REA 첫 번째 결과에서 이 호출자를 식별했습니다. 이전 명령어 스케일 {ph0} 30 으로;20 을 더하면 벽돌의 화면 좌표가 " "나옵니다, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "메모리 주소 뒤에 있는 값 읽기" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " "scale. The agent now has the values needed for the C expression." msgstr "반환된 바이트는 두 개의 산술 상수와 초기 팬 스케일을 설정합니다. 이제 에이전트에 필요한 값이 있습니다." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "에서REA's 결과 C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8400,7 +8408,7 @@ msgstr "아래의 다섯 단계를 따르십시오. 각 선택 항목은 원래 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8408,7 +8416,7 @@ msgstr "{ph0}01{ph1} 입력" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8416,7 +8424,7 @@ msgstr "{ph0}02{ph1} 곱하기" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8424,7 +8432,7 @@ msgstr "{ph0}03{ph1} 빼기" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8432,18 +8440,18 @@ msgstr "{ph0}04{ph1} 규모" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} 반환" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "원본 86*발췌" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "재구성된" @@ -8453,7 +8461,7 @@ msgstr "재구성된" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8471,7 +8479,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8487,7 +8495,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8504,7 +8512,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8520,7 +8528,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8531,7 +8539,7 @@ msgstr "" "{ph0}05*정수를 반환합니다.{ph1} 함수 호출 {ph2} 도달 {ph3},확인된 REA수신자 결과입니다. 결과는 다음과 같습니다 " "{ph4};원본-86 비교 반환 된 값을 확인합니다." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -8540,23 +8548,23 @@ msgid "" msgstr "" "어셈블리 발췌는 입력,산술 및 반환 지침을 선택합니다. 아래의 전체 목록에는 중간 저장소와 기능 설정 및 정리가 포함되어 있습니다." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "전체 조립 및 지원 증거" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA결과·0x406400–0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "호출하는 함수가 제공하는 것" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8564,54 +8572,54 @@ msgid "" "then pushes it before the call:" msgstr "브릭 히트 함수 {ph0} 타일 좌표의 크기를 30 으로 조정하고 20 을 추가 한 다음 호출 전에 푸시합니다:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "데이터 읽기 설정" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA바이트를 읽고,디코딩으로 little-endian 복식" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "주소" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "값" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "를 위해 사용하는" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "첫 번째 곱셈" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "빼기" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} 처음에는" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "저장된 팬 스케일" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -8625,7 +8633,7 @@ msgstr "녹음된 REA 4.1.0 해시 고정 DX-Ball 1.07 목표. 관련 조사 메 #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8633,24 +8641,24 @@ msgid "" "references{ph3}" msgstr "{ph0}유지 소스{ph1} · {ph2}조사 노트 및 증거 참조{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "복구 된 기능 확인" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " "original, and its compiled bytes match the executable." msgstr "복구된 함수는 두 가지 검사를 통과합니다.반환 값은 원본과 일치하고 컴파일된 바이트는 실행 파일과 일치합니다." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3,205 행동 사례" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -8658,12 +8666,12 @@ msgid "" "five pan scales: 0, 0.5, 1, 20 and −1." msgstr "0,0.5,1,20 및 -1:그들은 다섯 팬 스케일에서 0 에서 640 까지의 모든 정수 위치를 커버합니다." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 일치하는 바이트" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -8673,7 +8681,7 @@ msgstr "" "이 함수는 고정 된 툴체인을 사용하여 컴파일됩니다. 컴파일러 재생은 검토된 재배치를 적용하고 참조된 상수를 확인한 후 전체 함수와 " "일치합니다." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -8687,18 +8695,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}컴파일러 재생 세부 정보 읽기{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "조사 계속" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -8708,7 +8716,7 @@ msgstr "" "입자 업데이트,폭발 대기열 및 보너스 생성에도 동일한 접근법이 사용되고 있습니다.관련 기능을 검사하고,상태와 의존성을 복구한 다음,구현을" " 원본과 비교합니다." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -8717,7 +8725,7 @@ msgstr "" "사운드 팬 기능을 직접 검사하려면 다음을 수행하십시오 DX-Ball 프로젝트의 설치 지침 및 일치하는 원래 대상을 제공합니다. 그런 다음" " 실행:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "에DX-Ball체크아웃" @@ -8726,7 +8734,7 @@ msgstr "에DX-Ball체크아웃" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8738,7 +8746,7 @@ msgstr "{ph0}DX-Ball 저장소{ph1}{ph2}현재 소스,진행 및 로컬 설정.{ #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8753,7 +8761,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8773,13 +8781,13 @@ msgid "" "maintained C, original-x86 tests and matching compiled function bytes." msgstr "따라 DX-Ball 재건에서 바이너리 분석을 통해 REA 을 유지되 C,원래-86 테스트와 일치하는 컴파일된 기능이다." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ball 사운드 팬 조사;작은 화면에서 수평으로 스크롤" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -8791,87 +8799,87 @@ msgstr "" "딕스볼EXE 기능 0x00406400 검사와REA. 명령어 로드 엑스,1.5625 곱하기,500.0 빼기,팬 스케일을 적용하고 정수를 " "반환합니다. 3,205 개의 경우에서 63 바이트와 일치하는 4.0 컴파일러 재생에 의해 원본 86 에 대해 독립적으로 검사됩니다." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball재건축 사례 연구" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "예제 프롬프트 복사" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "왼쪽/오른쪽 사운드 위치의 계산을 따르십시오" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "원본 어셈블리 발췌문 복사" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "복사 사운드 팬 기능" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "복사 전체 사운드 팬 어셈블리" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "복사DX-Ball분석 명령" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "개인정보보호정책" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}홈{ph1} /쇼케이스" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA 사례 연구." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" " results." msgstr "안드로이드,게임,Electron및 CTF 도전으로,코드,그림 및 검사 결과입니다." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "안드로이드·APK분석" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "인증자가 로그인 코드를 생성하는 방법" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -8881,22 +8889,22 @@ msgstr "" "찾기 Aegis6 자리 코드 계산은 APK. 생성 방법을 추적 REA,다음 코드가 30 초마다 변경 이유를 확인하기 위해 데모 시계를 " "이동합니다." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "안드로이드 사례 연구 읽기" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "기계 코드 프로그램 분석" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "플래그 검사기 해결" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -8906,22 +8914,22 @@ msgstr "" "쉬운 다운 언더크트 도전을 검사합니다. REA. 그 검사 기능을 찾아 방정식으로 마스크와 합계를 설정 한 다음 원래 프로그램으로 해결 " "플래그를 확인합니다." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "공정거래위원회 사례 연구 읽기" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "기본*재건" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball's 운 팬 계산" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -8931,22 +8939,22 @@ msgstr "" "1996 년 사운드 팬 계산 복구 Windows 게임. REA명령어,호출자 참조,숫자 상수는 작은 함수로 이어집니다.원래의 동작과 63 " "개의 컴파일된 바이트에 대해 확인됩니다." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "읽DX-Ball사례 연구" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron·기능 추적" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "어떻게 Notion 텍스트 복사" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -8956,22 +8964,22 @@ msgstr "" "추적 페이지의 API 를 통해Notion's 패키지JavaScript. 시스템 클립 보드에 래퍼를 따라 다음 작은 마커가 복사본에 연결된" " 풍부한 블록 데이터를 유지하는 방법을 참조하십시오." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "읽Notion사례 연구" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98DOS·재건" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "어떻게 TH04 총알의 반지를 목표로" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -8981,24 +8989,24 @@ msgstr "" "원래 16 비트 각도 도우미를 검사하십시오. REA. 그 곱하기,나누기 및 좌표 연산을 읽을 수있는 C++에 일치시킨 다음 플레이어를 " "겨냥한 링을 어떻게 생성하는지 확인하십시오." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "읽TH04사례 연구" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "단계별 가이드" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " "browser request. Each starts with a prompt and a concrete target." msgstr "가이드는 기본 계산을 통해 Electron 내보내기 및 브라우저 요청. 각 프롬프트와 구체적인 대상으로 시작합니다." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "가이드 읽기" @@ -9016,12 +9024,12 @@ msgid "" msgstr "" "팔로우 REA 코드,그림 및 데모를 통한 조사:안드로이드 인증 자, DX-Ball, Notion, TH04 그리고 하향식 플래그 검사기." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -9030,37 +9038,37 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}홈{ph1} / {ph2}쇼케이스{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "사례 연구·Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "어떻게 Notion 사본{ph0}텍스트." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " "process, to Electron's clipboard writer." msgstr "클립보드 호출 추적 Notion사전 로드 및 주요 프로세스를 통해 Electron클립보드 작가입니다." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion데스크탑 7.6.1·JavaScript·REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "다리 내부에Notion's 패키지 데스크톱" @@ -9072,7 +9080,7 @@ msgstr "다리 내부에Notion's 패키지 데스크톱" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9088,7 +9096,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9103,7 +9111,7 @@ msgstr "{ph0}02*예압 래퍼{ph1} {ph2}{ph3}{ph4} {ph5}래퍼는 채널 및 인 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9119,7 +9127,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9129,13 +9137,13 @@ msgstr "" "{ph0}04*시스템 클립 보드{ph1} {ph2}{ph3}{ph4} {ph5}Electron 제공된 텍스트를 씁니다.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "한 채널이 양쪽을 연결합니다: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9143,14 +9151,14 @@ msgid "" msgstr "" "패키지 코드는 사전 로드 및 기본 프로세스에서 동일한 채널을 사용합니다. 래퍼를 해결하면 Electron 그 이름 뒤에 함수 호출." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "이 사례 연구에서" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9158,7 +9166,7 @@ msgstr "{ph0}클립보드 브리지 따르기{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9166,19 +9174,19 @@ msgstr "{ph0}블록 구조 유지{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}더 많은 예와 출처{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "복사 작업은 어디로 갑니까?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9197,17 +9205,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "복사" @@ -9218,7 +9226,7 @@ msgstr "복사" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9228,19 +9236,19 @@ msgstr "" "{ph0}›{ph1}{ph2}사용 REA 추적 방법 Notion 시스템 클립보드에 텍스트를 복사합니다. 각 단계에서 코드를 " "표시합니다.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " "coding agent." msgstr "다음과 같은 예제 프롬프트 Notion코딩 에이전트가 사용할 수있는 로컬 응용 프로그램 패키지입니다." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA 읽기 시작 위치 찾기" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9249,13 +9257,13 @@ msgid "" msgstr "" "탭 사전 로드 분석 REA 페이지 및 요청을 보내는 호출을 찾습니다. 두 결과 모두 축소 된 번들의 소스 범위와 함께 제공됩니다:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA 연구 결과→두 가지 장소를 오픈" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9268,7 +9276,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9280,25 +9288,25 @@ msgstr "" "에이전트는 이러한 위치를 열고 어셈블리에서 클립보드 멤버를 찾아 읽습니다 {ph0}. 그것의 외침 위치 공급 {ph1}. 그 이름은 " "에이전트에게 주요 번들에서 찾을 수 있는 정확한 것을 제공합니다. 아래 네 부분 은 그 길 이 연결 되는 길 을 보여 준다." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "네 개의 짧은 코드 조각" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " "Unrelated members are omitted." msgstr "패키지에서 단순화 JavaScript,읽을 수 있는 변수 이름. 관련 없는 멤버는 생략됩니다." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "페이지에 노출된" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9306,13 +9314,13 @@ msgid "" "how the request leaves the page's process." msgstr "이 멤버는 채널 이름을 제공합니다. 의 구현 {ph0} 요청이 페이지의 프로세스를 종료하는 방법을 알려줍니다." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "사전 로드의 래퍼 해결" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9320,14 +9328,14 @@ msgid "" "response IPC. We can now look for {ph0} on the main-process side." msgstr "반환된 함수는 인수를 Electron요청 및 응답 우리는 지금 찾을 수 있습니다 {ph0} 메인 프로세스 측면에서." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "수신기가 등록되는 방법 확인" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9335,12 +9343,12 @@ msgid "" "receiver for that channel." msgstr "주요 프로세스는 다른 래퍼를 사용합니다. 그것의 {ph0} 메소드는 {ph1} 해당 채널의 수신기." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "쓰기 및 보낸 사람 확인 찾기" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9350,13 +9358,13 @@ msgstr "" "이 목적지입니다. 보낸 사람을 확인한 후 처리기는 제공된 데이터를 Electron클립보드입니다. 채널과 두 개의 해결된 래퍼는 노출된 " "메서드를 이 호출에 연결합니다." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "복사 된 블록은 어떻게 구조를 유지합니까?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9366,56 +9374,56 @@ msgstr "" "Notion의 웹 편집기는 텍스트를 전송합니다. {ph0}. 그것은 로컬 블록 데이터를 유지하고 그들을 연결하기 위해 복사 한에 아이디를" " 넣습니다." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "저장된 블록 데이터에 대한 링크" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "읽기" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "동일한 로컬 아이디 찾기" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "복원Notion블록 데이터" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " "when IDs match; a stale entry returns only text and HTML." msgstr "설명 텍스트 및 아이디. 기록 된 모듈 테스트는 식별자가 일치 할 때 블록 데이터를 복원합니다." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." " Matching IDs restore the block data." msgstr "붙여넣기, Notion 저장한 사본에 대하여 검사한다. 일치하는 신분증은 블록 데이터를 복원합니다." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "2026 년 7 월 13 일에 캐시된 웹 자산에서 기록된 클립보드 형식." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "더 많은 예와 출처" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "또 다른 예:마크 다운 테이블" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -9423,25 +9431,25 @@ msgid "" msgstr "" "Notion 마크다운을 블록 데이터로 구문 분석합니다. 이 예제에서는 테이블이 머리글 및 데이터 행이 되는 방법을 보여 줍니다." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "테이블을 통해Notion's Markdown parser" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " "and cells." msgstr "추출 된 마크 다운 파서에서 기록 된 출력. 테이블은 행과 셀이 됩니다." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "다른 경로:오프라인 스카이라이트 연결" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9453,14 +9461,14 @@ msgstr "" "Notion렌더러 요청 {ph0} 2018 년 11 월 기본 프로세스는 메시지 채널을 생성하고 한 포트를 렌더러에 제공하고 다른 포트를 " "렌더러 유틸리티 프로세스에 제공합니다. 후속 문 배치 및 결과는 해당 포트를 통해 이동합니다." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " "tracing only the initial IPC request misses the later conversation." msgstr "이 핸드오프에 따라 데이터베이스 작업이 실행되는 위치와 초기 요청만 추적하면 나중에 대화가 누락되는 이유를 설명합니다." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "출처 및 발췌문 읽기 방법" @@ -9468,7 +9476,7 @@ msgstr "출처 및 발췌문 읽기 방법" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9484,7 +9492,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9498,7 +9506,7 @@ msgstr "" "{ph1}, {ph2} 그리고 {ph3}. 이러한 자산에는 자체 버전이 있습니다. 저장된 프로브는 추출된 모듈과 작은 하네스를 " "실행했습니다." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -9510,7 +9518,7 @@ msgstr "" "작업을 수행하려면 다음을 수행하십시오. 클립보드 멤버와 일치하는 수신기는 패키지에서 래퍼 구현을 읽음으로써 연결됩니다." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9526,7 +9534,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9538,7 +9546,7 @@ msgstr "{ph0}JavaScript 신청 가이드{ph1}{ph2}작은 따라 Electron 응용 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9559,52 +9567,52 @@ msgid "" "format." msgstr "팔로우 Notion클립보드를 통해 Electron짧은 코드 발췌와 풍부한 클립보드 형식을 살펴볼 수 있습니다." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "NotionElectron사례 연구" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "복사 Notion 분석 프롬프트" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "복사Notion미리 발췌문" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "복사Notioninvoke wrapper 발췌문" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "복사Notion처리기 wrapper 발췌문" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "복사Notion클립보드 receiver 발췌문" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "붙여 넣기에 풍부한 클립 보드 데이터 복원" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "맨 위로" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "개인정보보호정책" @@ -9613,42 +9621,42 @@ msgstr "개인정보보호정책" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}홈{ph1} / {ph2}쇼케이스{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "사례 연구*동방 4:로터스 랜드 스토리" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "재구성 TH04의{ph0}총알 패턴." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " "the original DOS function, then follow its instructions into readable C++." msgstr "총알의 고리는 짧은 각도 계산으로 시작됩니다. 사용 REA 원래 도스 함수를 검사하려면 해당 지침을 따라 읽을 수 있습니다." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 ·16 비트 도스*C++및 어셈블리" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "보TH04재건" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "원본 지침에서 확인 된 소스까지" @@ -9659,7 +9667,7 @@ msgstr "원본 지침에서 확인 된 소스까지" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9674,7 +9682,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9691,7 +9699,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9705,7 +9713,7 @@ msgstr "{ph0}03*읽기 C++{ph1}{ph2}공간→목표→회전{ph3}{ph4}유지 재 #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9716,21 +9724,21 @@ msgstr "" "{ph0}04*소스 확인{ph1}{ph2}2,139 일치하는 바이트{ph3}{ph4}기록된 컴파일러 검사는 이 도우미가 포함된 글머리 " "기호 생성 코드를 다룹니다.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " "supplies the maintained source and compiler checks." msgstr "REA 원본 코드와 해당 분석 증거를 반환합니다. 그 TH04 프로젝트는 유지되는 소스 및 컴파일러 검사를 제공합니다." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "이 사례 연구에서" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -9738,7 +9746,7 @@ msgstr "{ph0}총알 반지{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -9746,7 +9754,7 @@ msgstr "{ph0}무엇 REA 반환{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -9754,7 +9762,7 @@ msgstr "{ph0}어셈블리{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -9762,18 +9770,18 @@ msgstr "{ph0}소스 확인{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}전체 프로젝트{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "반지가 플레이어를 겨냥하는 방법" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -9791,16 +9799,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}코딩 에이전트" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "복사" @@ -9811,7 +9819,7 @@ msgstr "복사" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9821,7 +9829,7 @@ msgstr "" "{ph0}›{ph1}{ph2}사용 REA 방법을 찾으려면 TH04 총알 반지를 만들어 플레이어를 겨냥합니다. 계산을 설명하고 코드를 " "보여줍니다.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -9829,7 +9837,7 @@ msgid "" msgstr "로컬에서 사용할 수 있는 원래 실행 파일 및 재구성 체크아웃이 있는 예제 프롬프트입니다." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9842,7 +9850,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9850,12 +9858,12 @@ msgid "" "40 and template rotation 0. {ph0}Open figure{ph1}" msgstr "카운트에 대한 복구 각도 수학의 그림 16,플레이어 방향 40 템플릿 회전 0. {ph0}열린 그림{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "복구된 소스의 발사 템플릿" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "엘리의 반지 공격*출처 발췌" @@ -9864,7 +9872,7 @@ msgstr "엘리의 반지 공격*출처 발췌" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9872,13 +9880,13 @@ msgid "" "{ph0}Read the attack's source{ph1}." msgstr "이 선은 난이도와 성능 조정 전에 패턴을 선택합니다. {ph0}공격 소스 읽기{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "WhatREA환" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9889,19 +9897,19 @@ msgstr "" "우리는 검사 {ph0} 각 총알의 속도와 각도를 설정하는 함수입니다. REA 명령어,의사 코드 및 참조를 반환합니다. 그 결과의 세 " "부분이 패턴을 설명합니다." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "코드를 읽기 전에 도스 이미지를 확인하십시오" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " "executable. The path above is shortened for display." msgstr "이 검사는 로드된 코드와 재배치 레코드를 제공된 실행 파일에 연결합니다. 위의 경로는 표시를 위해 단축됩니다." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "링의 곱하기 및 나누기 읽기" @@ -9909,7 +9917,7 @@ msgstr "링의 곱하기 및 나누기 읽기" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9920,12 +9928,12 @@ msgstr "" "{ph0} 총알 인덱스를 보유하고 있습니다. 이 이동은 256 으로 곱하고,그 다음에는 이 분할에서 읽은 수를 사용합니다. {ph1}. " "유지 관리되는 소스 이름은 해당 필드입니다 {ph2}. 전체 순서는 아래에 나타납니다." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "패턴이 플레이어 쪽으로 향하는 위치 찾기" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -9936,12 +9944,12 @@ msgstr "" "명령 피연산자는 두 개의 좌표 차이와 방향 도우미를 노출합니다. 그것의 반환 값은 상대 링 각도에 추가됩니다. 소스 이름을 사용하면 해당" " 주소를 읽을 수 있습니다; REA 에이전트가 그 뒤에 있는 원래 작업을 확인할 수 있습니다." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "어셈블리에서 읽을 수있는 키++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -9953,7 +9961,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -9961,7 +9969,7 @@ msgstr "{ph0}01{ph1} 지수" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -9969,7 +9977,7 @@ msgstr "{ph0}02{ph1} 공간" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -9977,7 +9985,7 @@ msgstr "{ph0}03{ph1} 목표" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -9985,18 +9993,18 @@ msgstr "{ph0}04{ph1} 회전" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} 제품 정보" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA·기존 16 비트 지침" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "*조준 링 요약" @@ -10004,7 +10012,7 @@ msgstr "*조준 링 요약" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10018,7 +10026,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10032,7 +10040,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10046,7 +10054,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10060,7 +10068,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10072,7 +10080,7 @@ msgstr "" "{ph0}05*최종 각도를 1 바이트로 유지하십시오.{ph1} 가게가 쓴 글 {ph2} 스폰 각도 필드에. 값은 부호없는 바이트 캐스트와" " 마찬가지로 255 이후에 래핑됩니다. 주변 소스는 또한 이 각과 속도를 속도로 변환합니다." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10082,7 +10090,7 @@ msgstr "" "어셈블리는 조준 링 분기,조준 계산 및 최종 저장소를 선택합니다. 위의 C++는 읽을 수있는 요약입니다. 아래의 컴파일러 검사는 연결된 " "프로젝트의 유지되는 소스에 적용됩니다." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "유지 링 및 조준 소스 읽기" @@ -10099,7 +10107,7 @@ msgstr "유지 링 및 조준 소스 읽기" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10107,36 +10115,36 @@ msgid "" "representation{ph5}" msgstr "{ph0}링 매크로{ph1} · {ph2}조준 및 속도 소스{ph3} · {ph4}각도 표현{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "유지 관리 소스 확인" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " "including this helper, with its pinned Turbo C++ 4.0J toolchain." msgstr "그 TH04 프로젝트의 기록된 검사는 이 도우미를 포함한 총알 생성 코드를 컴파일합니다." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 일치하는 바이트" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " "original executable." msgstr "컴파일된 총알 생성 코드는 원래 실행 파일의 2,139 바이트 섹션과 일치합니다." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "두 개의 깨끗한 빌드" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10147,65 +10155,65 @@ msgstr "두 개의 별도 빌드는 동일한 일치하는 바이트를 생성 #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "2026 년 10 월 3 일에 기록된 {ph0}컴파일러 검사 읽기{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "대상 신원 및 분석 범위" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "원래 목표" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0},156,258 바이트" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "도우미 항목" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} 그 안에 REA로드 된 이미지" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "원본 파일 오프셋" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0},반환 {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "기록 된 코드 검사" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0·2026 년 10 월 7 일" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10215,7 +10223,7 @@ msgstr "" "비교합니다." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10228,7 +10236,7 @@ msgstr "" " 걸쳐 두 범위에서 503 개의 본문 바이트를 보고합니다.위의 선택된 명령은 보고된 범위에 있습니다." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10242,7 +10250,7 @@ msgstr "" " 신선한 REA 동일한 원래 대상의 검사. 제공된 게임의 신원은 저장소 매니페스트에 의해 고정되어 있으며 독립적인 원시 덤프 출처가 " "여전히 열려 있습니다." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10252,12 +10260,12 @@ msgstr "" "이 그림은 각도 계산을 보여줍니다. 전체 게임 컨트롤,타이밍 및 PC-98 하드웨어 동작에는 재구성 프로젝트에서 별도의 런타임 검사가 " "있습니다." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "전체TH04재건" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10269,7 +10277,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10281,7 +10289,7 @@ msgstr "{ph0}탐색 TH04 저장소{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10295,7 +10303,7 @@ msgstr "{ph0}총알 생성 소스{ph1}{ph2}전체 도우미,다른 패턴 유형 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10310,7 +10318,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10331,28 +10339,28 @@ msgid "" "player." msgstr "검사 TH04의 원래 16 비트 도스 코드 REA. 이 게임의 목표는 가능한 한 많은 적을 파괴하는 것입니다." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "이 페이지에" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04탄 패턴은 사례 연구" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "복사 TH04 프롬프트 예" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "TH04 고정 및 목표 총알 반지;작은 화면에서 수평으로 스크롤" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10363,27 +10371,27 @@ msgstr "" "16 총알 링의 두 다이어그램. 고정 링은 각도 0 에서 시작합니다. 40 의 플레이어 방향을 추가하면 모든 방향이 같은 양으로 " "회전합니다.강조된 첫 번째 총알은 플레이어를 가리킵니다. 둘 다 16 각 단위 또는 22.5 도의 간격을 유지합니다." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "복사TH04발사 템플릿" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "따라TH04을 목표로 링 계산" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "복사TH04어셈블리는 발췌문" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "읽을 수있는 목표 링 계산 복사" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "맨 위로" @@ -10491,14 +10499,14 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "조정 속도: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" "game check when rounded to three decimals." msgstr "복구된 규칙을 다시 재생했습니다. 4 개의 값 모두 3 개의 소수로 둥글게 하면 제어된 원래 게임 체크와 일치합니다." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -10851,591 +10859,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "같은 간격:256÷16=16 각도 단위=22.5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "사례" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "블로그" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "시작하기" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "가이드" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "소스 코드" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "MIT 라이선스" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "커뮤니티 참여" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "X에서 팔로우" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA *선택한 스크립트 소스" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "소스 코드" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "예상 포맷터 출력" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "지침" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "호출자" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "상수" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "C 기능" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "버튼" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "사전 로드" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "2015 년" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV 파일" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "클릭" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "캡처된 요청" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "스크립트 내보내기" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA결과·요약입니다.발췌" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA명령 발췌·0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA자 발췌·0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA바이트로 결합하는 것으로 해석 little-endian 복식" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "복구 된 C*발췌" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "REA 사용 방식 보기 ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "전시→" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "검사된 스크립트에서 선택한 설정" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "%처리기의 읽을 수 있는 요약" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA·선택한 원래의 지침" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "운영자의 신분증*마이크로 소프트의 소스" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "쨩챌쨔챈쨀" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "에이전트→REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA→에이전트·선택한 결과" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA→에이전트·방법과 호출하는 함수" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA·선택한 디컴파일된 Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "읽을 수있는 요약*에이전트의 해석" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA·generateOTP,완전한 신체" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "다운로드AegisAPK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "안드로이드 분석 공급자 다운로드" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "에이전트→REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA→에이전트·선택한 결과" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA→에이전트·선택 지침" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "에이전트→REA·read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA→agent·일곱 번째 항목" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "원 실행·SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "원래 도전 다운로드" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "다운로드 솔버" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA결과·의사 발췌문" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "에이전트→ REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA→에이전트·사용법 발췌문" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA→agent·호출하는 함수 발췌문" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "에이전트→ REA *두 {ph0} 요청" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA결과의 바이트·디코딩으로 복식" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "너의 자신의 표적에 시작" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "코드 생성" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "복구 된 규칙" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "조정 가능한 시계" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "이진" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "코드 확인" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "방정식" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "맞아요!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "실행 가능" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA결과" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "복구 된" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "유효성 검사" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "패키지 앱" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "노출" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "래퍼" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "클립보드" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "원래 도스 코드" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA지침" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "각도 계산" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "총알 반지" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "노출된 페이지" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "렌더러 호출" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "시스템 클립보드로 전송됨" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "로컬로 저장해Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "마크다운 입력" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "구조화된 파서 출력*발췌" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "자신의 앱 분석" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "에이전트→REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA→에이전트·선택된 분야" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "에이전트→ REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA→에이전트·사용법 발췌문" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "동일한 기능 결과*목표 발췌" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "해당 유지 관리 C++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "매크로 반지·TH04점,발췌" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "각도와 속도*소스 발췌" @@ -11468,7 +11484,7 @@ msgstr "번역이 업데이트되고 있습니다. 지금 이 페이지를 영 #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11485,7 +11501,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11505,7 +11521,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11525,7 +11541,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11543,7 +11559,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11561,7 +11577,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11570,7 +11586,7 @@ msgid "" msgstr "{ph0}›{ph1}{ph2}사용 REA 검사 {ph3}. 나를 위해이 웹 사이트를 복제.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" @@ -11578,7 +11594,7 @@ msgstr "재건 · {ph0}" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11587,7 +11603,7 @@ msgid "" msgstr "{ph0}와 npm을 준비한 뒤 설정 명령을 실행하세요. 사용할 코딩 에이전트를 선택하고 변경 계획을 확인하세요." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -11596,7 +11612,7 @@ msgstr "제공된 예·{ph0}및npm·코딩의 에이전트" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11614,7 +11630,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -11628,7 +11644,7 @@ msgstr "{ph0}페이지 · {ph1}{ph2}{ph3}노트 내보내기{ph4}{ph5}통화 {ph #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11645,7 +11661,7 @@ msgstr "{ph0}다리 · {ph1}{ph2}{ph3}{ph4}{ph5}{ph6}주 프로세스에 명명 #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11656,7 +11672,7 @@ msgstr "" "씁니다.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -11671,7 +11687,7 @@ msgstr "{ph0} *라인 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11683,7 +11699,7 @@ msgstr "" "{ph5} 그것을 확인합니다. 예측 및 실제 출력을 표시합니다.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11692,7 +11708,7 @@ msgid "" msgstr "제목은 하나의 인용 필드에 남아 있으며 각 인용 부호는 두 배로 표시됩니다. 이것은 포맷터를 직접 확인합니다. {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -11700,7 +11716,7 @@ msgstr "{ph0}·CSV포맷터" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11708,7 +11724,7 @@ msgid "" msgstr "당신이 필요합니다 {ph0} 22 (22.19+), 24 (24.11+) 또는 26+. npm 함께 제공 {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -11716,7 +11732,7 @@ msgstr "이 없{ph0},또는 확신할 수 없으십니까?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11728,7 +11744,7 @@ msgstr "" "인쇄하는 경우 다음을 설치하십시오 {ph1} 24 리터:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -11742,7 +11758,7 @@ msgstr "{ph0} *예제 소스 발췌" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -11751,9 +11767,9 @@ msgid "" msgstr "{ph0}예제 열기{ph1} · {ph2}다운로드 {ph3}{ph4} · {ph5}다운로드 {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -11761,7 +11777,7 @@ msgstr "{ph0} *예제 소스" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -11775,7 +11791,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11786,7 +11802,7 @@ msgstr "처음 또는 누락 {ph0} 아니면 코딩 에이전트? {ph1}단계별 #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -11799,7 +11815,7 @@ msgstr "예를 들어: {ph0}계산기에서 {ph1}가 왜 220이 될까요?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11808,7 +11824,7 @@ msgid "" msgstr "{ph0}›{ph1}{ph2}사용 REA 검사 Windows 계산기 왜 {ph3} 220 줘?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -11817,7 +11833,7 @@ msgstr "REA *로드 {ph0} *선택한 라인" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11834,7 +11850,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11852,7 +11868,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -11864,28 +11880,28 @@ msgstr "" "뒤, 시간을 바꿔 볼 수 있는 작은 데모를 만들어 주세요.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "탭 _브라우저 _보기/{ph0} ·회원" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "탭 _브라우저 _보기/{ph0} ·아이피 도우미" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "주요/{ph0} *핸들러 도우미" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -11895,12 +11911,1254 @@ msgstr "주요/{ph0} *클립 보드 수신기" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "시작하기 {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "라이트 모드로 전환" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "다크 모드로 전환" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"HTTP 요청과 응답 본문을 살펴보려면 {ph0}Fiddler Everywhere: SAZ 캡처, MCP 및 공개 스킬{ph1}을 " +"사용하세요. SAZ ?? HAR 1.2로 내보내면 REA에서 오프라인 캡처 Evidence를 얻을 수 있으며, Everywhere의 " +"MCP 서버를 연결하여 에이전트와 함께 캡처된 트래픽을 살펴볼 수도 있습니다." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "전문 모델{ph0}에세이" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "리버스 엔지니어링에는 더 큰 모델이 필요할까?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "Touhou 재구축 경험을 바탕으로 범용 모델, 전문 모델, 컴파일러 피드백을 통한 학습을 생각해 봅니다." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "작성자: N0zoM1z0 · 2026년 10월 13일" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "개인정보보호정책" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}홈{ph1} / {ph2}블로그{ph3} / 모델 및 리버스 엔지니어링" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "에세이" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "리버스 엔지니어링에 더 큰 모델이 필요할까?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "작성자: N0zoM1z0 · 2026년 10월 13일" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "핵심 요점" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}모델 기능은 AI 에이전트가 제안할 수 있는 가설에 영향을 미칩니다.{ph1} 이후 세션에서는 이전 작업에서 해결되지 않은 " +"문제를 해결했습니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}익숙한 컴파일러는 특화 모델이 학습할 수 있는 구체적인 패턴을 제공합니다.{ph1} 일부 정확한 기계 코드 일치는 재사용 가능한" +" 특정 소스 코드 패턴에 따라 달라집니다." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}공정한 비교에 저장소 지식을 포함합니다.{ph1} 지식 검색이 좋은 소규모 모델은 이미 진행하기에 충분한 정보를 가지고 있을 수" +" 있습니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}다음 유용한 실험을 선택하도록 모델을 훈련시키고 검증 검사기를 테스트합니다.{ph1} 피드백은 검사기가 올바른 것을 검증하는 " +"정도까지만 유용합니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}시간 및 비용과 함께 검증된 재구성 결과를 평가합니다.{ph1} 이것이 제가 전체 AI 에이전트 워크플로에 대해 측정하고 싶은 " +"것입니다." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "이 기사 에서" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}더 강한 모델이 바꾼 것{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}전문화해야 하는 이유{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}이 경험은 어디에 저장되어야 합니까?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}다음 유용한 실험 학습{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}리버스 엔지니어링 및 강화 학습{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}검증체커가 잘못된 경우{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}실행할 가치가 있는 비교{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}어떤 에이전트가 필요할까?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "더 강한 모델이 바꾼 것" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"2026년 8월부터, 프로그램에 접근하고 자신의 작업을 검증할 수 있는 에이전트가 리버스 엔지니어링을 얼마나 수행할 수 있는지 탐구해 " +"왔다. 내 경험은 주로 게임, 특히 Touhou 재구성에서 나온다. 모델을 바꿔 가며 작업하는 동안 저장소에는 각 세션이 무엇을 " +"복원했는지 기록이 쌓였다." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"이 작업의 상당 부분은 정확한 재구성을 목표로 한다. 버전을 고정한 당시의 툴체인으로 유지 관리 중인 소스 코드를 컴파일하고, 대상 " +"함수가 재현되는지 확인한다. 이전에 막혔던 문제를 나중 모델이 해결하면, 소스 변경을 통해 무엇이 진전을 가능하게 했는지 살펴볼 수 " +"있다." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "임시 변수에는 수명이 겹치는 것이 필요했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"TH09 공격 함수의 논리 대부분은 이미 재구성되었지만 컴파일러는 여전히 원본과 다르게 임시 결과를 저장했습니다. 남은 문제는 해당 " +"결과를 유지하는 데 필요한 기간과 해당 저장소를 언제 재사용할 수 있는지였습니다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"여러 가지 일반적인 소스 코드 배열을 테스트한 후 {ph0}GPT-6-Sol 세션 레코드{ph1}에서 이러한 불일치를 보고했습니다. " +"{ph2}GPT-6.1-Sol이 문제를 다시 조사했을 때{ph3} 이러한 임시 변수의 수명에 대한 유용한 가설을 제안했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"이 함수는 임시 결과를 생성하고 이를 애니메이션 위치에 복사했습니다. C++에서 임시 결과는 이를 사용하는 표현식이 완료될 때까지 활성 " +"상태로 유지됩니다. 실제 작업을 하나의 표현식으로 그룹화하면 해당 결과가 함께 유지되므로 컴파일러는 더 이상 모든 작업에 대해 동일한 " +"저장소를 재사용할 수 없습니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"한 결과는 나중에 충돌 확인을 위해 사용되는 값으로 여전히 저장 공간을 공유합니다. 해당 값에 고유한 수명을 부여하면 나머지 중복이 " +"해결되었습니다. 여러 번의 대상 실험 후 {ph0}소스에서 깔끔하게 재컴파일하여 전체 함수가 {ph1}과 일치함을 확인했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"나는 발견과 테스트가 어떻게 서로를 지원하는지에 관심이 있습니다. 임시 개체 수명에 대한 가설은 AI 에이전트에 새로운 방향을 " +"제시했습니다. 컴파일러 피드백은 해당 가설을 일치하는 소스 코드 배열로 구체화하는 데 도움이 되었습니다." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "다른 제어 흐름 그래프" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"두 번째 TH09 함수는 새로운 방향이 중요한 이유를 보여줍니다. 여기서 장애물은 여러 지점이 최종 작업을 공유하는 방식이었습니다. " +"{ph0}GPT-6.1-Sol의 이전 작업{ph1}에서는 일치하는 함수의 일부를 얻었지만 분기는 여전히 원본과 다르게 결합되었습니다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra이 주변 제어 흐름 그래프{ph1}를 변경했습니다. 이제 주요 경로는 공유된 최종 업데이트 및 복귀로 " +"이어졌습니다. 해당 소스 구조에서 컴파일러는 원본과 동일한 방식으로 분기를 결합했습니다. 전체 함수이 일치했으며 {ph2}별도의 재구축 " +"검사를 통해 이를 확인했습니다{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}표현을 변경하면 보다 생산적인 검색 공간이 열렸습니다.{ph1} 두 경우 모두 일반 모델 기능을 진지하게 받아들여야 하는 이유가" +" 됩니다. 에이전트는 주변 작업을 표현하는 더 나은 방법을 찾기 전에 오랫동안 지역 변형을 계속 시도할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"다만 이후 세션은 이전 소스 코드와 실패 기록을 이어받았다. 그 축적도 이점의 일부였다. 이력에서 발견과 검증 과정을 확인할 수는 " +"있지만, 모델 자체의 효과와 물려받은 경험의 효과를 구분하려면 조건을 맞춘 비교가 필요하다." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"이것이 나에게 그 질문을 흥미롭게 만드는 이유이다. 새로운 표현을 찾는 과정에서 약간의 진전이 있었습니다. 나머지 작업의 대부분은 익숙한" +" 컴파일러에 대해 다양한 소스 코드 배열을 테스트하는 것과 관련되었습니다. 이 중 얼마나 폭넓은 추론 능력이 필요한가요? 해당 컴파일러와" +" 코드를 반복적으로 사용하여 모델이 얼마나 학습할 수 있습니까?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "특화된 AI 모델이 왜 좋은 성과를 낼 수 있을까요?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou은 그 경험이 도움이 될 것으로 기대하는 구체적인 이유를 제공합니다. 대부분의 게임 코드는 동일한 작성자인 ZUN에서 " +"제공되므로 반복되는 습관은 합리적인 시작 가정입니다. 저장소는 유용한 예를 통해 이를 뒷받침합니다. 관련 루프 및 도우미 배열은 게임 " +"전반에 걸쳐 가설을 제공했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"이러한 소스 패턴은 컴파일러를 포함하면 더욱 구체적이 됩니다. 특정 버전 및 옵션 세트에서는 소스의 작은 변경으로 인해 기계어 코드에 " +"반복 가능한 차이가 발생할 수 있습니다. 이러한 차이점 중 일부는 놀라울 정도로 모호합니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"예를 들어 TH095에서는 {ph0}로컬 변수의 이름도 VC7.1이 변수를 저장한 위치에 영향을 미칠 수 있습니다{ph1}. 선언을 " +"이동해도 스토리지 레이아웃이 해결되지 않았습니다. 그러나 이전 백그라운드 함수에서는 컴파일러의 선택에 영향을 미치는 명명 패턴이 " +"드러났습니다. 이는 {ph2}{ph3}{ph4} 재구성에 대한 더 유망한 가설을 제시했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"파일 크기 변수에 해당 패턴을 재사용하면 저장소를 추가하지 않고도 필요한 레이아웃이 생성되었습니다. 그런 다음 전체 함수이 일치했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"이는 범용 AI 모델이 처음 문제에 직면했을 때 알 수 없는 매우 구체적인 세부 사항입니다. 이 컴파일러에 특화된 모델은 이러한 사례를 " +"많이 확인하고 먼저 테스트할 가치가 있는 소스 코드 변형을 학습할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"우리가 이미 동작을 이해하고 있는 최종 매칭 문제에서 기회는 특히 분명합니다. 그런 다음 이 컴파일러가 관찰된 명령으로 변환하는 일반적인" +" 소스 코드 배열을 묻습니다. 전문화는 모델이 이러한 형태를 보다 효율적으로 제안하는 데 도움이 될 수 있으며, 목표는 여전히 어떤 " +"가설이 살아남는지 결정합니다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"유용한 패턴에는 적용 조건이 함께 남아야 한다. TH08은 TH095와 TH09보다 오래된 Visual C++ 버전을 사용한다. " +"TH04은 DOS 시대의 다른 컴파일러를 사용하며, {ph0}플레이어 코드 재구성{ph1}에는 소스 패턴과 실행 파일의 링크 방식에 관한" +" 다른 가설이 필요했다. 같은 저자라는 사실은 초기 가정을 제공하지만, 그것이 적용되는지는 각 대상에서 확인해야 한다. 이런 맥락을 " +"구별하는 것도 특화 모델이 배울 일이다." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "이 경험은 어디에 저장되어야 합니까?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"모델 훈련을 통해 이러한 패턴을 가르치기로 결정하기 전에 우리가 이미 저장소에 보관하고 있는 지식을 살펴보겠습니다. {ph0}이전 " +"에세이{ph1}에서는 그것이 프로젝트의 작업 메모리가 되는 것에 대해 썼습니다. 그 메모리에는 컴파일러 교훈과 이를 유용하게 만든 소스 " +"및 실패한 실험이 포함됩니다." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"에이전트는 해당 기록을 검색하여 알려진 결과로 시작하고 해당 기록에 어떻게 도달했는지 검사할 수 있습니다. 또한 동일한 맥락에서 이미 " +"실패한 대안을 피할 수도 있습니다. 모델의 훈련된 매개변수를 변경하지 않고도 시작점이 향상됩니다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"TH09의 적 생성 함수를 재구성할 때, {ph0}GPT-6-Luna-max 세션{ph1}은 TH08의 관련 소스 코드에서 가설을 " +"얻었다. 이전 코드는 루프의 구성과 내부 실패 처리에 대한 단서를 제공했다. TH09 자체의 증거로 게임별 세부 사항을 채웠고, 소스에서" +" 새로 빌드해 함수 전체의 일치를 확인했다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"모델이 컴파일러의 이상한 점을 몰랐습니다\"와 \"모델이 이를 사용할 수 없었습니다\"는 다른 문제입니다.{ph1} 검색을 " +"통해 첫 번째 문제를 해결할 수 있지만 해당 사실을 유용한 후보로 바꾸는 작업은 여전히 필요합니다. 그리고 후보 소스 코드가 실패하면 " +"모델은 다음 시도에서 결과가 무엇을 의미하는지 결정해야 합니다. 관련 패턴을 아는 것은 해당 프로세스의 시작일뿐입니다." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"그러한 이유로 저는 어떤 비교에서도 검색 성능이 좋은 더 작은 범용 AI 모델을 포함하겠습니다. 동일한 경험 라이브러리를 제공하면 교육이" +" 추가하는 것이 무엇인지 식별하는 데 도움이 됩니다. 즉, 더 나은 후보 코드 생성, 피드백 후 더 나은 결정 또는 둘 다입니다." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "다음 유용한 실험 학습" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"피드백 이후의 결정은 제가 가장 연구하고 싶은 것입니다. 에이전트 재구성에서 모델은 설명을 제안하고 이를 프로그램에 대해 테스트합니다. " +"후보 소스 코드가 실패하더라도 그 결과는 남은 가능성을 좁히고 보다 유용한 다음 실험을 제안할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"임시 결과 예제를 다시 고려해보세요. 최종 소스에는 제대로 작동한 배열이 표시되지만 해당 소스로의 경로에는 더 많은 정보가 포함되어 " +"있습니다. 다음 각 실험은 여전히 ​​변경해야 할 사항을 식별하는 데 도움이 되었습니다." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "실험" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "그 결과가 우리에게 가르쳐준 것" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "결과를 복사하는 다른 방법을 시도해 보세요." + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "복사 코드는 변경되지만 기능은 여전히 다릅니다." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "반환된 값을 직접 사용" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "복사는 원래 패턴을 따르지만 임시 저장소는 여전히 다릅니다." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "모든 임시 변수를 동시에 유효한 상태로 유지" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "별도의 저장소를 갖지만 하나는 나중에 충돌 검사에 사용되는 값과 여전히 겹칩니다." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "충돌 검사 값을 별도로 유지하십시오." + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "소스에서 완전히 재컴파일하면 완전한 일치가 확인됩니다." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "위의 공격 함수 재구성에서 선택한 실험을 우리에게 가르친 내용을 기준으로 그룹화했습니다." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"이 시퀀스를 유지하는 훈련 기록은 최종 소스보다 더 많은 것을 가르칠 수 있습니다. 이는 제안된 각 변경 사항을 관찰된 결과 및 다음 " +"결정에 연결합니다. 비효과적인 변형을 유지하는 것도 중요합니다. 이는 해당 맥락에서 어떤 가설이 이미 테스트되었는지 나중에 에이전트에게 " +"알려줍니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}모델이 피드백을 사용하는 방법을 배우기를 원합니다.{ph1} 중립적인 결과는 변화를 재고해야 하는 이유입니다. 변경된 불일치는 " +"다른 원인을 가리킬 수도 있습니다. 로컬 편집이 더 이상 정보를 제공하지 않으면 에이전트는 소스 표현을 다시 방문하거나 증거를 다시 " +"검사할 수 있어야 합니다." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"그러한 선택을 하는 방법을 배우려면 자율성이 필요합니다. 때때로 유용한 다음 단계는 다른 편집 내용을 컴파일하는 대신 다른 호출자를 " +"검사하는 것입니다. 필수 재작성의 엄격한 순서는 모델이 학습하기를 원하는 동작의 일부와 함께 해당 선택을 제거합니다." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "강화 학습에 리버스 엔지니어링이 흥미로운 이유" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"범위가 정해진 재구성은 이런 선택을 연구할 실용적인 환경을 제공한다. 대상과 컴파일러 버전을 고정하면 많은 소스 코드 실험에서 빠르고 " +"반복 가능한 피드백을 얻을 수 있다. 에이전트는 후보 코드를 컴파일하고 차이를 살펴본 뒤 다음 단계를 선택할 수 있다." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"강화 학습은 이런 피드백을 통해 의사 결정 과정을 훈련할 수 있다. 정의된 검증을 통과한 후보는 구체적인 결과가 되고, 시도 기록은 그 " +"결과에 도달하는 데 얼마나 많은 작업이 필요했는지 보여 준다." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"이미 이 방향을 뒷받침하는 연구가 있다. {ph0}LLM4Decompile{ph1}은 디컴파일에 특화된 모델을 연구한다. " +"{ph2}AutoDecompiler{ph3}는 컴파일과 실행 피드백으로 여러 차례 개선하는 과정을 학습한다. 이 연구들은 기능 복원에 " +"초점을 맞춘다. 나는 이를 출발점으로 삼아, 당시 컴파일러의 출력과 일치하는 소스 코드를 찾는 관련 과제를 연구하고 싶다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"그처럼 명확한 과제를 만들려면, 먼저 함수가 어떤 리소스를 책임지는지 확인하거나 실행 중인 프로그램의 동작을 관찰할 새로운 방법을 " +"설계해야 할 수 있다. TH08에서는 {ph0}충돌 판정의 차이를 추적하다가 원본 프로그램의 부동 소수점 계산 방식에 도달했다{ph1}." +" 에이전트는 유용한 수정을 검증하기 전에 무엇을 측정할지부터 알아내야 했다." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"이는 광범위하게 역량을 갖춘 모델의 또 다른 역할을 제시합니다. 즉, 우선 문제를 확인할 수 있도록 돕는 것입니다. 해당 검사가 존재하면" +" 학습된 검색 정책이 얼마나 멀리까지 도달할 수 있는지 조사할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "검증체커가 잘못된 경우" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"검증 결과를 학습에 사용하면 그 검증의 범위도 학습 환경의 일부가 된다. 나는 이런 참조 기준이나 검증기를 oracle이라고 부른다. " +"반복 가능한 답이라도, 실제로 무엇을 확인한 답인지 이해해야 한다." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08은 해당 적용 범위 외부에 얼마나 많은 것을 숨길 수 있는지 보여주었습니다. 재구성된 일부 함수는 잘못된 부동 상수와의 정확한 " +"비교를 통과했습니다. 비교기는 명령을 확인하기 전에 재배치된 주소를 조정했지만 확인을 위해 명시적으로 기록된 경우에만 해당 주소 뒤에 " +"있는 값을 확인했습니다. 다른 리터럴 참조는 해당 값을 검사하지 않고 통과할 수 있습니다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"이러한 격차를 해소하기 위해 {ph0}광범위한 감사{ph1}를 통해 이미 검증을 통과한 함수에서 잘못된 상수가 발견되었습니다. 한 " +"계산에서는 재구성된 소스 코드에 {ph2}가 추가된 반면 원본 코드에는 {ph3}가 추가되었습니다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}기존 검증으로 보상하면 모델이 잘못된 재구성을 학습할 수도 있다.{ph1} 이 검증기로 RL 모델을 훈련한 것은 아니다. 실제로" +" 관찰한 실패는 검증 자체의 오류였다. 하지만 이를 보상으로 사용했다면 같은 사각지대가 학습 환경에 들어갔을 것이다." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"기능 테스트에도 비슷한 사각지대가 있을 수 있습니다. {ph0}LLM 디컴파일러에서 차등 퍼징을 사용한 연구{ph1}에서는 제공된 테스트" +" 외부의 동작 차이를 발견했습니다. 그러므로 우리는 그것이 수행되는 사례의 관점에서 합격 테스트를 이해해야 합니다. 마찬가지로 명령어 " +"일치는 확인하는 바이트와 데이터 측면에서 이해되어야 합니다." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"어느 검증이든 보상으로 사용하기 전에는 의도적으로 틀린 결과를 넣어 시험해 보고 싶다. 최종 승인 기준도 에이전트가 수정할 수 있는 소스" +" 코드 밖에 두어야 한다. 올바르게 재구성해 검증을 통과하도록 해야 하기 때문이다. 그렇지 않으면 대상에서 복사한 바이트 배열이 유용한 " +"소스 복원 없이 단순한 채점 기준을 통과할 수 있다." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}학습 모델의 개선과 검증기의 개선은 같은 연구 문제다.{ph1} 모델이 우리가 주는 피드백을 더 잘 최적화할수록, 그 피드백 " +"자체를 이해하는 일도 중요해진다." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "실행할 가치가 있는 비교" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"이러한 점검을 마친 후 고정된 VC7.1 작업 계열에 대한 비교를 시작합니다. 첫째, 강력한 범용 AI 모델과 더 작은 모델에 대한 " +"기준선을 설정하겠습니다. 더 작은 모델에 저장소 지식을 추가하면 검색이 어떻게 변경되는지 확인할 수 있습니다. 거기에서 감독 전문화와 " +"RL 훈련 버전을 통해 훈련에 추가되는 것이 무엇인지 검토할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"이러한 비교를 유익하게 만들기 위해 각 모델은 동일한 대상 증거와 도구를 받게 됩니다. 훈련별 비교를 위해 기본 모델과 사용 가능한 " +"지식도 고정된 상태로 유지합니다. 반복적인 시도는 우연히 성공한 후보 솔루션과 신뢰할 수 있는 검색 전략을 구별하는 데 도움이 됩니다." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"그런 다음 두 가지 시작 조건을 분리합니다. 즉, 명령에서 함수를 재구성하는 것과 유지 관리되는 소스에서 마지막 몇 가지 차이점을 닫는 " +"것입니다. 특화 AI 모델은 두 번째 작업에 탁월할 수 있지만 범용 AI 모델은 두 번째 작업에 도달하는 데 필요한 많은 작업을 " +"수행합니다. 그것들을 개별적으로 측정하면 업무 분할이 드러날 것입니다." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"두 과제 모두 학습 데이터와 검색 자료에서 제외한 테스트 사례가 필요하다. 관련 Touhou 게임은 엔진 코드를 공유하므로, 게임 하나만" +" 제외해도 거의 같은 함수가 학습 데이터에 남을 수 있다. 대신 관련 소스 코드 계열 전체를 따로 남겨 두고, 검증된 정답을 학습 " +"데이터와 검색 라이브러리 양쪽에서 제외하겠다." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"측정할 결과는 완전하고 독립적으로 검증된 일치다. 후보 제안 수나 컴파일 횟수의 예산을 같게 하면 탐색 품질을 비교할 수 있다. 컴파일을" +" 포함한 총 시간과 비용은 그 품질이 효율적인 워크플로로 이어지는지 보여 준다. 학습 비용은 별도로 계산해야 한다." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"두 측정 모두 중요합니다. 유용한 정보를 제공하지 않는 컴파일이 더 많이 발생하면 값싼 제안으로 인해 비용이 많이 드는 작업 흐름이 " +"발생할 수 있습니다. 반대로, 유용한 실험을 더 빨리 발견하면 느린 모델이 더 경제적일 수 있습니다. 비교에는 이러한 비용이 포함되어야 " +"합니다." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"승인된 결과를 계산하면 중간 진행 상황을 관점에서 볼 수 있습니다. 하나의 TH09 {ph0}재생 저장 후보{ph1}는 컴파일된 함수의 " +"크기가 예상과 같았기 때문에 유망해 보였지만 전체 비교에서는 여전히 상당한 차이가 발견되었습니다. 컴파일러가 명령을 배열하는 방식을 " +"변경하면 근본적인 문제를 해결하지 않고도 후보가 더 가까워 보이게 만들 수도 있습니다. 이러한 진단은 다음 실험의 지침이 될 수 있지만 " +"전체 승인 확인에 대해 \"가까워지는\" 것에 대한 보상을 검증하겠습니다." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"나는 이러한 결과의 패턴에 관심이 있습니다. 전문화된 AI 모델이 친숙한 컴파일러 제품군 내에서 잘 작동한다면 툴체인 변경 후에도 해당 " +"장점이 유지됩니까? 두 AI 모델 모두 좋은 검색 결과를 얻은 후에도 훈련을 통해 얼마나 추가되나요? 답변은 각 모델 종류가 가장 유용한" +" 위치를 결정하는 데 도움이 됩니다." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "어떤 에이전트가 필요할까?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"모델이 여러 단계에서 도움이 되는 것으로 밝혀지면 특화 AI 모델에 액세스할 수 있는 광범위한 에이전트가 유용한 배열이 될 수 있습니다." +" 작업이 익숙한 컴파일러 검색이 되면 특화 AI 모델에 후보를 요청할 수 있습니다. 결과가 더 이상 이해되지 않는 경우 더 넓은 범위의 " +"에이전트는 대상 증거로 돌아가거나 측정 자체를 조사할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"이러한 배열에서 전문화는 조사가 진행됨에 따라 에이전트가 선택할 수 있는 도구가 됩니다. 에이전트는 이전의 돌파구를 가능하게 했던 방향을" +" 자유롭게 변경할 수 있습니다." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"이는 이전 에세이에서 설명한 산업 변화에서 자연스럽게 나온 것입니다. 더 많은 실험을 실행할 수 있게 되면 작업 구성 방식이 변경됩니다." +" 또한 어떤 결정에 폭 넓은 판단이 필요한지, 어떤 결정은 특정 기술에 대한 반복적인 경험을 통해 개선되는지 질문할 이유를 제공합니다." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"지금까지 가장 강한 범용 모델은 내가 해결하지 못했던 문제를 풀어내며 워크플로에서 자리를 얻었다. 그 성공 때문에 작업을 더 자세히 " +"살펴보고 싶다. 얼마나 많은 부분이 모델의 폭넓은 능력에 의존했을까? 이 종류의 재구성을 전문적으로 학습한 모델은 어디까지 담당할 수 " +"있을까?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}저장소는 질문을 테스트할 수 있는 방법을 제공합니다.{ph1} 해당 기록을 사용하여 비교를 구축하고 배운 내용을 확인하고 " +"싶습니다." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "증거 및 모델 속성" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"예제에서는 연결된 커밋에 기록된 기능 수준 비교 기록을 설명합니다. 전체 게임 런타임 확인은 별도의 마일스톤입니다. 출처 및 일치 기록은" +" 2026년 10월 13일에 검토되었습니다." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"TH09 라벨 {ph0}은 GPT-6-Astra을 의미합니다. {ph1}과(와) 관련된 모델은 시간이 지남에 따라 변경되었으므로 " +"라벨만으로는 특정 실행에 사용된 모델을 식별할 수 없습니다. 다른 인용 커밋의 명시적인 모델 이름은 기록된 속성을 제공합니다. 이러한 " +"기록에는 모든 실행에 대한 일관된 비용 또는 노력 측정이 포함되지 않습니다." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 임시 객체 수명:{ph1} {ph2}이전 컨텍스트 검토{ph3} 및 {ph4}소스에서 깔끔한 재컴파일을 통해 확인된 " +"완전한 재구성{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front 콜백:{ph1} {ph2}일치하지 않는 진단 영역{ph3}, {ph4}Astra의 새로운 제어 흐름 " +"그래프{ph5} 및 {ph6}승인된 재컴파일 확인{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}컴파일러 지식:{ph1} {ph2}TH095 식별자 버킷 동작 재사용{ph3}, {ph4}TH04 플레이어 소스 코드 및 링커 " +"순서{ph5} 및 {ph6}Luna의 TH09 적 생성 기능에 대한 완전한 재구성{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}검사 및 진단:{ph1} {ph2}TH08 부동 소수점 상수 감사{ph3}, {ph4}TH08 수치 조사{ph5} 및 " +"{ph6}TH09 재생 저장 재구성{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"제안한 특화 모델과 RL의 비교는 앞으로 해 볼 실험이다. 프로젝트 이력이 그 동기를 제공하지만, 이 글에서 학습된 특화 모델을 평가한 " +"것은 아니다." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "리버스 엔지니어링에 더 큰 모델이 필요할까? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Touhou 재구성을 통해 일반 모델, 전문 모델 및 컴파일러 피드백을 통해 더 나은 가설을 제안하는 방법에 대해 배운 내용." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "이 페이지에" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "모델 및 리버스 엔지니어링 에세이" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "선정된 재구성 실험" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "맨 위로" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "{ph0}상세 증거 기록{ph1}에는 비교 결과와 실험 맥락이 담겨 있다." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "작성: N0zoM1z0 · 2026년 10월 13일 · 검토용 초안" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "설정 가이드" diff --git a/website/locales/messages.pot b/website/locales/messages.pot index da3276762..4d41b3f46 100644 --- a/website/locales/messages.pot +++ b/website/locales/messages.pot @@ -6,209 +6,242 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "" -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "" #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models and " +"learning from compiler feedback." +msgstr "" + +#: website/public/blog/index.html:207 website/public/blog/index.html:222 +msgctxt "page:blog/index.html" +msgid "Read the article" +msgstr "" + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "" + +#. {ph0}: <br /> +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about agents, " "verification and knowledge that compounds across projects." msgstr "" -#: website/public/blog/index.html:204 -msgctxt "page:blog/index.html" -msgid "Read the article" -msgstr "" - -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -227,6 +260,8 @@ msgid "" msgstr "" #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -252,97 +287,1096 @@ msgctxt "shared" msgid "REA — Find out how software works. Reverse engineering with your coding agent." msgstr "" -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later sessions " +"have solved problems that earlier work left unresolved." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to learn.{ph1} Some " +"exact matches depend on narrow, reusable source patterns." +msgstr "" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with good " +"retrieval may already know enough to make progress." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value of feedback" +" depends on what the checker actually verifies." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the result I " +"want from the whole agent." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an agent can " +"carry out with access to a program and a way to check its work. Most of my experience " +"comes from reconstructing games, especially Touhou. As I have changed models, the " +"repositories have kept a record of what each session managed to recover." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained source under" +" a pinned historical toolchain and check whether it reproduces the target function. " +"When a later model succeeds where earlier work stalled, the source changes show what " +"made that progress possible." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but the " +"compiler still stored temporary results differently from the original. The remaining " +"problem was how long those results needed to stay alive and when their storage could " +"be reused." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing several ordinary" +" source arrangements. When {ph2}GPT-6.1-Sol returned to the problem{ph3}, it found a " +"useful hypothesis about how long those temporary values needed to stay alive." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation positions. In " +"C++, a temporary result stays alive until the expression using it finishes. Grouping " +"the real operations into one expression kept those results alive together, so the " +"compiler could no longer reuse the same storage for all of them." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision checks. Giving " +"that value its own lifetime resolved the remaining overlap. After several targeted " +"experiments, {ph0}a clean rebuild confirmed that the full function matched{ph1}." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The lifetime " +"hypothesis gave the agent a new direction; compiler feedback helped it refine that " +"hypothesis into a source arrangement that matched." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the obstacle was" +" how several branches shared their final work. {ph0}GPT-6.1-Sol's earlier work{ph1} " +"got parts of the function to match, but the branches still joined up differently from " +"the original." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main paths now " +"led to a shared final update and return. In that source structure, the compiler " +"combined the branches in the same way as the original. The complete function matched, " +"and a {ph2}separate rebuild check confirmed it{ph3}." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1} Both " +"cases give me a reason to take general model capability seriously: an agent can keep " +"trying local variations for a long time before finding a better way to express the " +"surrounding work." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and recorded " +"failures. That accumulated work was part of their advantage. The history lets us " +"inspect the discoveries and their checks; a controlled comparison would help separate " +"the effect of the model from the experience it inherited." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress came from " +"finding a new representation, while much of the remaining work involved testing source" +" forms against a familiar compiler. How much needs broad reasoning ability, and how " +"much could a model learn through repeated experience with that compiler and code?" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of the game " +"code comes from the same author, ZUN, so recurring habits are a reasonable starting " +"assumption. The repositories back that up with useful examples: related loops and " +"helper arrangements have supplied hypotheses across games." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. Under a " +"particular version and set of options, small changes in source can produce repeatable " +"differences in machine code. Some of those differences are surprisingly obscure." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could change where" +" VC7.1 stored it{ph1}. Moving the declaration alone did not solve the layout, but an " +"earlier background function had revealed a naming pattern that affected the compiler's" +" choice. That gave us a more promising hypothesis for {ph2}the reconstruction of " +"{ph3}{ph4}." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout without " +"adding storage. The full function then matched." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it arrives. A " +"specialist trained on this compiler could encounter many such cases and learn which " +"source variations are worth testing first." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we already " +"understand the behavior. We are then asking which ordinary source form this compiler " +"turns into the observed instructions. Specialization could help the model propose " +"those forms more efficiently, while the target still determines which hypotheses " +"survive." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an earlier " +"Visual C++ version than TH095 and TH09. TH04 uses a different DOS-era compiler, and " +"its {ph0}player reconstruction{ph1} needed different hypotheses about source patterns " +"and how the compiled code was combined into an executable. Shared authorship gives us " +"a prior, but each target tells us whether it applies. Distinguishing those contexts is" +" part of what a specialist would need to learn." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look at the " +"knowledge we already keep in the repository. In the {ph0}previous essay{ph1}, I wrote " +"about it becoming the project's working memory. That memory includes compiler lessons," +" along with the source and failed experiments that made them useful." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and inspect how we " +"reached it. It can also avoid alternatives that have already failed in the same " +"context. The starting point improves without changing the model's weights." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max session{ph1} " +"drew a hypothesis from TH08's corresponding source family. That earlier source " +"suggested how to structure the loop and handle failures within it. TH09's own evidence" +" supplied the game-specific details, and clean rebuilds confirmed the complete match." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could not use it\"" +" are different problems.{ph1} Retrieval may solve the first, but turning that fact " +"into a useful candidate still takes work. And if the candidate fails, the model must " +"decide what the result means for its next attempt. Knowing the relevant pattern is " +"only the beginning of that process." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval in any " +"comparison. Giving it the same library of experience would help us identify what " +"training adds: better candidate generation, better decisions after feedback, or both." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In agentic " +"reconstruction, the model proposes an explanation and tests it against the program. " +"Even when the candidate fails, the result can narrow the remaining possibilities and " +"suggest a more useful next experiment." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the arrangement " +"that worked, but the route to that source contains more information. Each of the " +"following experiments helped identify what still needed to change." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Copying follows the original pattern, but temporary storage still differs." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for collision " +"checks." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped by what " +"they taught us." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final source alone." +" It connects each proposed change to an observed result and the next decision. Keeping" +" ineffective variations matters too: they tell a later agent which hypotheses have " +"already been tested in that context." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral result is a " +"reason to reconsider the variation; a changed mismatch may point to another cause. " +"When local edits stop being informative, the agent should be able to revisit the " +"source representation or inspect the evidence again." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next step is " +"inspecting another caller rather than compiling another edit. A rigid sequence of " +"required rewrites would remove that choice, along with part of the behavior we want " +"the model to learn." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these choices. " +"Once the target and compiler are pinned, many source experiments produce quick, " +"repeatable feedback. The agent can compile a candidate, inspect the mismatch and use " +"that observation to choose its next step." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the feedback " +"it receives. A candidate accepted by a defined check gives us a concrete outcome, " +"while the sequence of attempts lets us observe how much work it took to reach it." +msgstr "" + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1} studies " +"models specialized for decompilation. {ph2}AutoDecompiler{ph3} trains multi-turn " +"refinement using compiler and execution feedback. Their studies focus on functional " +"recovery. For this work, I would use them as a starting point for the related task of " +"finding source that matches a historical compiler's output." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish what a " +"function owns or devise a new runtime measurement. In TH08, for example, a " +"{ph0}collision difference led back to how the original program handled floating-point " +"calculations{ph1}. Before the agent could test a useful correction, it had to work out" +" what to measure." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the problem " +"checkable in the first place. Once that check exists, we can investigate how far a " +"learned search policy can get with it." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the model learns. " +"I call the reference or checker an oracle. Even if it gives a repeatable answer, we " +"still need to understand what that answer covers." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed functions " +"passed their exact comparisons with wrong floating constants. The comparator adjusted " +"relocated addresses before checking instructions, but it checked the values behind " +"those addresses only when they had been explicitly recorded for verification. Other " +"literal references could pass without their values being examined." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in functions that" +" had already been accepted. In one calculation, the reconstructed source added {ph2} " +"where the original added {ph3}." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the observed " +"failure was in the check itself. But using that check as a reward would have made the " +"same blind spot part of the learning environment." +msgstr "" + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing research on" +" LLM decompilers{ph1} has found behavior differences beyond the supplied tests. " +"Passing those tests therefore needs to be read in terms of the cases they exercise, " +"just as an instruction match needs to be read in terms of the bytes and data it " +"checks." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with deliberate " +"failures. I would also keep final acceptance outside the candidate's editable source, " +"so the model has to satisfy the check through its reconstruction. Otherwise, something" +" like a byte array copied from the target could satisfy a naive score without " +"recovering useful source." +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same research " +"problem.{ph1} As the learner gets better at optimizing the feedback we give it, " +"understanding that feedback becomes more important too." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 task family." +" First, I would establish baselines for a strong general model and a smaller one. " +"Adding repository knowledge to the smaller model would show what retrieval changes. " +"From there, supervised specialization and an RL-trained version would let us examine " +"what training adds." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same target " +"evidence and tools. For the training-specific comparisons, I would keep the base model" +" and available knowledge fixed as well. Repeated trials would help distinguish a " +"reliable search strategy from a lucky candidate." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function from its " +"instructions, and closing the last few differences in maintained source. A specialist " +"might be excellent at the second task while a general model does much of the work " +"needed to reach it. Measuring them separately would reveal that division of work." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games share engine" +" code, holding out a game's name would still allow nearly identical functions to " +"appear in training. I would instead hold out source families and keep their accepted " +"answers out of both training and retrieval." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated matches. " +"Giving each model the same candidate or compile budget would help compare search " +"quality. Measuring elapsed time and total cost, including compilation, would tell us " +"whether that quality produces an efficient workflow. Training costs would need their " +"own accounting too." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive workflow if it " +"causes more uninformative compiles. Conversely, a slower model may pay for itself by " +"finding a useful experiment sooner. The comparison should capture those costs." +msgstr "" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. One TH09 " +"{ph0}replay-save candidate{ph1} looked promising because the compiled function had the" +" expected size, but a full comparison still found substantial differences. Changes in " +"how the compiler arranges instructions can also make a candidate look closer without " +"resolving the underlying problem. Such diagnostics can guide the next experiment, but " +"I would validate any reward for \"getting closer\" against the full acceptance check." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist does well " +"within a familiar compiler family, does that advantage survive a toolchain change? And" +" once both models have good retrieval, how much does training still add? The answers " +"would help us decide where each kind of model is most useful." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement might be a " +"broad agent with access to a specialist. Once a task becomes a familiar compiler " +"search, it could ask the specialist for candidates. If the results stop making sense, " +"the broader agent could return to the target evidence or investigate the measurement " +"itself." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as the " +"investigation develops. The agent keeps the freedom to change direction that made the " +"earlier breakthroughs possible." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous essay. " +"Being able to run many more experiments changes how we organize the work. It also " +"gives us a reason to ask which decisions need broad judgment and which improve through" +" repeated experience with a particular craft." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by opening " +"problems I had left unresolved. Those successes are what make me want to examine the " +"work more closely: how much depended on the model's breadth, and how much could be " +"handled by a model trained in this particular kind of reconstruction?" +msgstr "" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like to use " +"that record to build the comparison and see what we learn." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and experiment " +"context." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the linked " +"commits. Whole-game runtime checks are separate milestones. Source and matching " +"records were reviewed on 13 October 2026." +msgstr "" + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model used at the " +"time, so that label alone does not identify an individual run. Explicit model names in" +" the other cited commits establish their recorded attribution; the histories do not " +"contain uniform per-run cost or effort measurements." +msgstr "" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and " +"{ph4}complete cold reconstruction{ph5}." +msgstr "" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, {ph4}Astra's " +"new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, {ph4}TH04 " +"player source and linker order{ph5} and {ph6}Luna's TH09 enemy-spawn closure{ph7}." +msgstr "" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, {ph4}TH08 " +"numerical investigation{ph5} and {ph6}TH09 replay-save reconstruction{ph7}." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The project " +"histories motivate them; no trained specialist was evaluated for this essay." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models and " +"learning to propose better hypotheses from compiler feedback." +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "" + +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "" @@ -351,35 +1385,35 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -389,7 +1423,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -399,7 +1433,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -409,7 +1443,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -419,7 +1453,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -427,65 +1461,65 @@ msgid "" "still taking shape. There is plenty left to explore." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -494,7 +1528,7 @@ msgstr "" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -503,40 +1537,40 @@ msgstr "" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes fixing the " "checks when we discover a gap." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -544,7 +1578,7 @@ msgstr "" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -552,7 +1586,7 @@ msgstr "" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -560,7 +1594,7 @@ msgstr "" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -568,7 +1602,7 @@ msgstr "" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -576,7 +1610,7 @@ msgstr "" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -584,7 +1618,7 @@ msgstr "" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -592,18 +1626,18 @@ msgstr "" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would inspect a " @@ -612,7 +1646,7 @@ msgid "" " keeping an increasingly large picture in my head." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be understood" @@ -621,7 +1655,7 @@ msgid "" " can check against a reliable reference." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to see how far" @@ -629,7 +1663,7 @@ msgid "" "reconstruction gave me a substantial project in which to find out." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without me " @@ -639,14 +1673,14 @@ msgid "" "project's direction and on whether its checks were trustworthy." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive beyond the " "current project. Would the next game benefit from everything we had just learned?" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "" @@ -655,7 +1689,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -665,7 +1699,7 @@ msgid "" "continuation." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent " @@ -673,7 +1707,7 @@ msgid "" "1,107 identified game functions." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly eleven days " @@ -681,7 +1715,7 @@ msgid "" "arrived on 30 August." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. Getting there" @@ -692,7 +1726,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -703,12 +1737,12 @@ msgid "" "something specific to investigate." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how much can " @@ -717,7 +1751,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -726,7 +1760,7 @@ msgid "" "used {ph1}, the maximum-power threshold." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was effectively always " @@ -737,13 +1771,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool accounted for" @@ -754,7 +1788,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -767,7 +1801,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -777,7 +1811,7 @@ msgid "" "accepted functions." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include deliberately " @@ -787,7 +1821,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -795,7 +1829,7 @@ msgid "" " game." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I cannot " @@ -807,7 +1841,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -818,7 +1852,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -826,7 +1860,7 @@ msgid "" "next batch.{ph1}" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "" @@ -835,7 +1869,7 @@ msgstr "" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -844,14 +1878,14 @@ msgid "" "completion. One passage reads:" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from our work " "paints a bad image for future decompilation efforts…" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -861,7 +1895,7 @@ msgid "" "how reconstruction should proceed and how a contribution should be judged." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and " @@ -870,7 +1904,7 @@ msgid "" " happened while they worked." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build tools. What " @@ -878,7 +1912,7 @@ msgid "" "investigation on its own." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a result. " @@ -887,7 +1921,7 @@ msgid "" "an implementation, even if an agent did most of the work." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the foundation " @@ -895,7 +1929,7 @@ msgid "" " also changes what maintainers need to know before accepting a contribution." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the process " @@ -904,7 +1938,7 @@ msgid "" "wrong. Different communities can choose how much of that change they want to take on." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its history " @@ -924,7 +1958,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -933,14 +1967,14 @@ msgid "" "{ph4}credits and provenance{ph5} record the continuation boundary." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -950,7 +1984,7 @@ msgid "" "begin a reconstruction and how to keep it moving." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 September, 696 had " @@ -959,7 +1993,7 @@ msgid "" "after initialization." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target could " @@ -967,7 +2001,7 @@ msgid "" "tools and in the way the project was organized." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program early. If " @@ -976,7 +2010,7 @@ msgid "" "shape how we approached TH095's whole-program build." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a check " @@ -984,7 +2018,7 @@ msgid "" "agent can use the result without repeating the investigation that led to it." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why checking a " @@ -994,7 +2028,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1002,7 +2036,7 @@ msgid "" "spend more of the next project's effort on what is actually new about its target." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a decision and" @@ -1010,7 +2044,7 @@ msgid "" "entire project's history to find out why the source looks the way it does." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "" @@ -1019,7 +2053,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1029,7 +2063,7 @@ msgid "" "{ph2}ReC98 work{ph3} gave us valuable knowledge and source material here too." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played complete Normal " @@ -1037,7 +2071,7 @@ msgid "" "port. Establishing a working DOS version first gives that port a reference." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the compiler " @@ -1045,7 +2079,7 @@ msgid "" "question through to a result and let that result guide the next experiment." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what state carries" @@ -1054,7 +2088,7 @@ msgid "" "an agent can work through the question much as it did on a Windows title." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did not force " @@ -1062,7 +2096,7 @@ msgid "" "workflow still gave us a way to solve it." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against behavior " @@ -1076,7 +2110,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1084,17 +2118,17 @@ msgid "" " {ph2}64-bit port{ph3}. The port remains in development." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Once a reconstruction works, I want someone else to be able to understand it." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is a " @@ -1104,7 +2138,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1115,7 +2149,7 @@ msgid "" "interpretation came from." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me where " @@ -1124,14 +2158,14 @@ msgid "" "recover the relationship behind the old memory access." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1142,7 +2176,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1154,7 +2188,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1166,7 +2200,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1177,7 +2211,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1187,7 +2221,7 @@ msgid "" "still builds and behaves correctly along the paths we exercise." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated instructions. An " @@ -1196,7 +2230,7 @@ msgid "" " carrying a refactor further." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether a field " @@ -1209,7 +2243,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1221,7 +2255,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1229,12 +2263,12 @@ msgid "" "recovered knowledge usable.{ph1} A port can then build on both." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry much of an " @@ -1243,7 +2277,7 @@ msgid "" "needed it." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a failed " @@ -1252,7 +2286,7 @@ msgid "" "attention." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can test them " @@ -1261,7 +2295,7 @@ msgid "" "a project milestone." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's caller can" @@ -1270,7 +2304,7 @@ msgid "" "proposes and see where its explanation holds up." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their own. When " @@ -1282,7 +2316,7 @@ msgstr "" #. {ph0}: <a href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1295,7 +2329,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1306,7 +2340,7 @@ msgid "" "project can then inherit a stronger tool." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before a large " @@ -1316,7 +2350,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1325,7 +2359,7 @@ msgid "" "the starting conditions for another." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience starts becoming" @@ -1333,12 +2367,12 @@ msgid "" "person—or the next agent—can get done." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be fascinating" @@ -1346,7 +2380,7 @@ msgid "" "realistically give it. Many projects would stay ideas." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated investigations. " @@ -1357,7 +2391,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1365,7 +2399,7 @@ msgid "" "accumulated knowledge would let an agent work on this reliably?{ph1}" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone. Each one " @@ -1373,12 +2407,12 @@ msgid "" "take us." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public GitHub history" @@ -1406,7 +2440,7 @@ msgstr "" #. {ph9}: </a > #. {ph10}: <a href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1437,7 +2471,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1452,7 +2486,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1472,7 +2506,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1490,7 +2524,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1503,7 +2537,7 @@ msgstr "" #. {ph2}: <a href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1519,7 +2553,7 @@ msgstr "" #. {ph4}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction- #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge-base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1531,7 +2565,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1549,27 +2583,27 @@ msgid "" " and how knowledge compounds across TH08, TH095 and PC-98 TH04." msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "" @@ -1578,18 +2612,18 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "" @@ -1598,7 +2632,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1607,15 +2641,15 @@ msgid "" "with {ph2}adjustable speed.{ph3}" msgstr "" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1623,7 +2657,7 @@ msgstr "" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1631,7 +2665,7 @@ msgstr "" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1639,18 +2673,18 @@ msgstr "" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower or faster" @@ -1658,54 +2692,54 @@ msgid "" "gradually accelerate again." msgstr "" -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "" -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above remain " "readable." msgstr "" -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "" @@ -1713,7 +2747,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1721,7 +2755,7 @@ msgid "" "the loaded {ph2}, including this branch in the game’s update function:" msgstr "" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "" @@ -1729,7 +2763,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1737,25 +2771,25 @@ msgid "" "without a collision." msgstr "" -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the slider " @@ -1767,59 +2801,59 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic scheduling " "disabled. Compare those recorded speeds with a replay of the recovered rule." msgstr "" -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the final " "increment can take speed just above 13." msgstr "" -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -1828,13 +2862,13 @@ msgstr "" #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "" -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this prompt." @@ -1848,7 +2882,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -1860,7 +2894,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1870,7 +2904,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1883,7 +2917,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1903,63 +2937,63 @@ msgid "" "play." msgstr "" -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is focused." msgstr "" -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "" -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "" -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -1967,7 +3001,7 @@ msgstr "" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -1975,7 +3009,7 @@ msgstr "" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -1983,24 +3017,24 @@ msgstr "" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2008,22 +3042,22 @@ msgid "" "proposed changes." msgstr "" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "" #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2032,12 +3066,12 @@ msgid "" "{ph0}Follow the setup guide{ph1} for prerequisites and your first analysis." msgstr "" -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, Claude Desktop," @@ -2048,29 +3082,29 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "" -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "REA releases frequently, including bug fixes. If you installed the CLI with npm:" msgstr "" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2078,13 +3112,13 @@ msgid "" "through {ph0}, run:" msgstr "" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "" #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2093,14 +3127,14 @@ msgid "" "followed by the command." msgstr "" -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2109,24 +3143,24 @@ msgid "" "can call the tools." msgstr "" -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2136,7 +3170,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2145,7 +3179,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2153,7 +3187,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2161,12 +3195,12 @@ msgid "" "resources. {ph0}See the case studies{ph1} for worked investigations." msgstr "" -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection work with" @@ -2175,7 +3209,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2184,25 +3218,25 @@ msgid "" "{ph0}Set up native analysis{ph1}." msgstr "" -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or Electron app:" msgstr "" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2210,12 +3244,12 @@ msgid "" "CLI{ph1} for installation options." msgstr "" -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "" -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and relevant " @@ -2227,7 +3261,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2236,12 +3270,12 @@ msgid "" "how that process works." msgstr "" -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or Electron " @@ -2256,7 +3290,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2269,7 +3303,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2279,7 +3313,7 @@ msgstr "" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2287,18 +3321,18 @@ msgid "" "Electron and browser examples." msgstr "" -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2306,7 +3340,7 @@ msgid "" "for Codex:" msgstr "" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "" @@ -2314,7 +3348,7 @@ msgstr "" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2322,14 +3356,14 @@ msgid "" "missing or stale registration, run setup for that client:" msgstr "" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2337,14 +3371,14 @@ msgid "" "absent, check the client's MCP connection error. {ph0}More setup diagnostics{ph1}." msgstr "" -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2353,14 +3387,14 @@ msgid "" "provider setup{ph1}." msgstr "" -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2370,7 +3404,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2379,24 +3413,24 @@ msgid "" "problem involves native analysis." msgstr "" -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and its model " "provider's data policy applies to those results." msgstr "" -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "" @@ -2405,7 +3439,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2416,7 +3450,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2436,77 +3470,77 @@ msgid "" " troubleshooting and sharing examples." msgstr "" -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "" -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one detail " @@ -2514,20 +3548,20 @@ msgid "" msgstr "" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" msgstr "" -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2535,7 +3569,7 @@ msgstr "" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2543,7 +3577,7 @@ msgstr "" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2551,7 +3585,7 @@ msgstr "" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2559,13 +3593,13 @@ msgstr "" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "" @@ -2573,7 +3607,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2589,19 +3623,19 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "" @@ -2613,7 +3647,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2621,26 +3655,26 @@ msgid "" "the setup plan for approval, then verify the installation.{ph4}{ph5}{ph6}" msgstr "" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already connected? " "Continue below." msgstr "" -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2656,7 +3690,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2665,7 +3699,7 @@ msgid "" " it contains, and the relevant files and lines.{ph5}{ph6}{ph7}" msgstr "" -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for inspection." @@ -2674,14 +3708,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" download="notes- #. example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2689,12 +3723,12 @@ msgid "" "the {ph0} folder and the same export question." msgstr "" -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "" @@ -2703,7 +3737,7 @@ msgstr "" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2711,7 +3745,7 @@ msgid "" " {ph1} in the user’s Downloads folder. The columns are {ph2} and {ph3}." msgstr "" -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "" @@ -2724,7 +3758,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -2738,7 +3772,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2755,7 +3789,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2763,7 +3797,7 @@ msgid "" "writes the file.{ph8}" msgstr "" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is read from" @@ -2771,18 +3805,18 @@ msgid "" msgstr "" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" msgstr "" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "" -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask your agent " @@ -2791,18 +3825,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "" -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself contains a comma " @@ -2818,7 +3852,7 @@ msgstr "" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2827,13 +3861,13 @@ msgid "" "output.{ph6}{ph7}{ph8}" msgstr "" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2841,48 +3875,48 @@ msgid "" "formatter directly with {ph0}." msgstr "" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" msgstr "" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. Your agent " "can run the same JavaScript in your platform’s shell." msgstr "" -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "What happens if the file can’t be written? Follow the error back to the page." msgstr "" -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or behavior." @@ -2892,7 +3926,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2904,7 +3938,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2916,7 +3950,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2936,110 +3970,110 @@ msgid "" "check the CSV formatter with a sample title." msgstr "" -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "" -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "You'll need {ph0} 22 (22.19+), 24 (24.11+) or 26+. npm comes with {ph1}." msgstr "" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" msgstr "" -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "" -#: website/public/get-started/index.html:207 website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "" -#: website/public/get-started/index.html:208 website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3049,14 +4083,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3066,7 +4100,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3074,17 +4108,17 @@ msgid "" " you run {ph2}, run this once and try again:" msgstr "" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "" @@ -3092,7 +4126,7 @@ msgstr "" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3102,7 +4136,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3112,20 +4146,20 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Prefer a regular installer? Download the LTS version from {ph0}nodejs.org{ph1}." msgstr "" -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3133,7 +4167,7 @@ msgstr "" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3141,7 +4175,7 @@ msgstr "" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3149,18 +4183,18 @@ msgstr "" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude Code, " @@ -3168,12 +4202,12 @@ msgid "" " Bot's connector is added from its chat." msgstr "" -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in a browser " @@ -3181,7 +4215,7 @@ msgid "" "it reverse-engineering tools." msgstr "" -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "If you don't have one yet, pick one, follow its install page and sign in:" msgstr "" @@ -3190,7 +4224,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}Claude Code{ph2}{ph3} by Anthropic. Needs a paid Claude plan." @@ -3200,7 +4234,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}Codex{ph2}{ph3} by OpenAI. Sign in with your ChatGPT account." @@ -3210,14 +4244,14 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" "{ph0}{ph1}OpenCode{ph2}{ph3}, open source. Connect the model provider of your choice." msgstr "" -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup and shows " @@ -3232,7 +4266,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -3245,7 +4279,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3253,12 +4287,12 @@ msgid "" "the setup plan for approval, then verify the installation.{ph4}{ph5}{ph6}" msgstr "" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "" @@ -3267,7 +4301,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3280,7 +4314,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}macOS:{ph1} press {ph2} {ph3}, type {ph4}Terminal{ph5} and press Enter." @@ -3291,7 +4325,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3304,7 +4338,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3312,7 +4346,7 @@ msgid "" "{ph6}), then press Enter." msgstr "" -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection and the " @@ -3320,12 +4354,12 @@ msgid "" "before applying the changes." msgstr "" -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "" -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "" @@ -3334,7 +4368,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3345,7 +4379,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3353,7 +4387,7 @@ msgid "" " it again." msgstr "" -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or Electron " @@ -3361,7 +4395,7 @@ msgid "" msgstr "" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3369,12 +4403,12 @@ msgid "" "dependencies involved, with the source locations for your findings." msgstr "" -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "" -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "" @@ -3383,7 +4417,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3395,7 +4429,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3405,38 +4439,38 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" "{ph0}Any system:{ph1} drag the folder into a terminal window and its path appears." msgstr "" -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without running " "the app:" msgstr "" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3444,13 +4478,13 @@ msgid "" "such as {ph1} works here." msgstr "" -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3460,7 +4494,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3471,7 +4505,7 @@ msgstr "" #. {ph2}: <code >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3482,20 +4516,20 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "" -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives their " @@ -3503,43 +4537,43 @@ msgid "" msgstr "" #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, then give " "REA your executable or library." msgstr "" -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on Linux or " @@ -3547,17 +4581,17 @@ msgid "" "host architecture. Set the paths before running setup:" msgstr "" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and records " @@ -3565,12 +4599,12 @@ msgid "" "Ghidra's native decompiler separately." msgstr "" -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE applications" @@ -3578,38 +4612,38 @@ msgid "" " 64-bit JDK 21 or newer:" msgstr "" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "Replace the two paths with your installations, then review setup's plan." msgstr "" -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an existing " "installation or offers an installation plan for your approval." msgstr "" -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license activation before" " an unattended analysis." msgstr "" -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for an attached" " GUI or a headless database. Linux and macOS headless analysis remains unverified." msgstr "" -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "" @@ -3619,7 +4653,7 @@ msgstr "" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3628,13 +4662,13 @@ msgid "" "before setup:" msgstr "" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3646,7 +4680,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3655,29 +4689,29 @@ msgid "" "binary." msgstr "" -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "" -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. Your " @@ -3686,7 +4720,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3694,18 +4728,18 @@ msgid "" "recovered calculation." msgstr "" -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3713,27 +4747,27 @@ msgid "" "Codex:" msgstr "" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -3742,7 +4776,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}REA FAQ{ph1}{ph2}Quick answers on updates, agents and analysis.{ph3}" @@ -3752,7 +4786,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3764,7 +4798,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3775,7 +4809,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}REA community{ph1}{ph2}Questions, investigations and work in progress.{ph3}" @@ -3793,112 +4827,112 @@ msgid "" "the terminal. Setup, first questions and native provider guides." msgstr "" -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "" @@ -3907,34 +4941,34 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "" -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the JavaScript " "that builds a download." msgstr "" -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -3942,7 +4976,7 @@ msgstr "" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -3950,7 +4984,7 @@ msgstr "" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -3958,7 +4992,7 @@ msgstr "" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -3966,13 +5000,13 @@ msgstr "" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "" @@ -3982,7 +5016,7 @@ msgstr "" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3990,7 +5024,7 @@ msgid "" "loads {ph4}, formats the two notes as CSV, and starts a download." msgstr "" -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "" @@ -4001,7 +5035,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4015,7 +5049,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4031,7 +5065,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4039,52 +5073,52 @@ msgid "" "request to {ph5} in {ph6}.{ph7}" msgstr "" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "" -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local debugging " "port. On Linux:" msgstr "" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can replace the " "page URL with another page you want to inspect." msgstr "" -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform the " "action, and close the browser when finished." msgstr "" -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "" @@ -4097,7 +5131,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4109,7 +5143,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4118,7 +5152,7 @@ msgid "" msgstr "" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4126,30 +5160,30 @@ msgid "" "it start the capture before you click." msgstr "" -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and reads the " "resulting evidence. It can then inspect the script behind the export." msgstr "" -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4157,14 +5191,14 @@ msgid "" "run:" msgstr "" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4172,56 +5206,56 @@ msgid "" "browser. The result arrives after the observation window ends." msgstr "" -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that window, " "and the shape of the JSON response. Earlier requests are outside this capture." msgstr "" -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "" @@ -4229,19 +5263,19 @@ msgstr "" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4250,14 +5284,14 @@ msgid "" msgstr "" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" msgstr "" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4274,14 +5308,14 @@ msgstr "" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the example{ph1} · {ph2}Download {ph3}{ph4} · {ph5}Download {ph6}{ph7}" msgstr "" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4291,7 +5325,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4299,6 +5333,18 @@ msgid "" "workflow{ph1} to follow files and process boundaries." msgstr "" +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ captures, MCP " +"and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA capture Evidence, or " +"connect Everywhere's MCP server to inspect captured traffic with your agent." +msgstr "" + #: website/public/guides/browser/index.html:6 msgctxt "page:guides/browser/index.html" msgid "Browser and Network Analysis — REA" @@ -4311,216 +5357,216 @@ msgid "" "request and follow the export script." msgstr "" -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "" -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each guide " "includes a prompt, code and results." msgstr "" -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "" -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller, read " "numeric constants and check the recovered C." msgstr "" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "" -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main process. " "Use REA to connect the API, IPC channel and file writer." msgstr "" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "" -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "" -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code that turns " "its response into a download." msgstr "" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "" -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "" @@ -4537,12 +5583,12 @@ msgid "" "and a browser request." msgstr "" -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "" @@ -4551,33 +5597,33 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "" -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV file writer." msgstr "" -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4585,7 +5631,7 @@ msgstr "" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4593,7 +5639,7 @@ msgstr "" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4601,7 +5647,7 @@ msgstr "" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4609,20 +5655,20 @@ msgstr "" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4631,7 +5677,7 @@ msgid "" "across several files." msgstr "" -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "" @@ -4645,7 +5691,7 @@ msgstr "" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4660,7 +5706,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4675,7 +5721,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4686,27 +5732,27 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "" -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed API. The " "path is inferred from code; a runtime capture can check what executes." msgstr "" -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Connect your agent to REA{ph1} and give it the app directory or ASAR file:" @@ -4720,14 +5766,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "" @@ -4738,7 +5784,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4747,13 +5793,13 @@ msgid "" msgstr "" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Example prompt. Include the absolute path to the application folder or {ph0}." msgstr "" -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and process " @@ -4761,26 +5807,26 @@ msgid "" "feature." msgstr "" -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" msgstr "" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, which exposes" @@ -4789,7 +5835,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4799,7 +5845,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4807,26 +5853,26 @@ msgid "" "main process writes {ph1} into the user's Downloads folder." msgstr "" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "" -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations accompany " "the API, channel and handler findings." msgstr "" -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4837,25 +5883,25 @@ msgstr "" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" download="notes- #. example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4863,20 +5909,20 @@ msgid "" " matching handler in {ph0}. Source locations are in {ph1}." msgstr "" -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An agent can " "follow a literal string, API name or IPC channel with REA's feature tracing tools." msgstr "" -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4884,7 +5930,7 @@ msgid "" "writing the file fails?" msgstr "" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names and " @@ -4896,7 +5942,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4908,7 +5954,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4920,7 +5966,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4940,32 +5986,32 @@ msgid "" "Includes downloadable example files and a verified analysis result." msgstr "" -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "" @@ -4974,34 +6020,34 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "" -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then check the " "recovered C." msgstr "" -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5009,7 +6055,7 @@ msgstr "" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5017,7 +6063,7 @@ msgstr "" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5025,7 +6071,7 @@ msgstr "" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5033,18 +6079,18 @@ msgstr "" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound code turns it" @@ -5053,7 +6099,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5062,7 +6108,7 @@ msgid "" "missing arithmetic." msgstr "" -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "" @@ -5071,7 +6117,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5081,7 +6127,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5091,7 +6137,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5101,7 +6147,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5110,7 +6156,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5118,7 +6164,7 @@ msgid "" "decoded." msgstr "" -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "" @@ -5129,7 +6175,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5144,7 +6190,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5160,7 +6206,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5168,14 +6214,14 @@ msgid "" "to {ph5}, {ph6} and a scale value.{ph7}" msgstr "" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent interprets them " "together." msgstr "" -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "" @@ -5184,7 +6230,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5192,19 +6238,19 @@ msgid "" "tool{ph3}, provide the local executable and a question:" msgstr "" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5215,7 +6261,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5225,7 +6271,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}IDA{ph1} (Windows): for an existing IDA setup with an MCP registration." @@ -5233,7 +6279,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5247,14 +6293,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "" @@ -5265,7 +6311,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5273,7 +6319,7 @@ msgid "" "calculation and show the code.{ph3}{ph4}{ph5}" msgstr "" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 executable. REA " @@ -5281,7 +6327,7 @@ msgid "" "another small Windows program you have." msgstr "" -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "" @@ -5290,7 +6336,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5302,7 +6348,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5312,46 +6358,46 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Any system:{ph1} drag the file into a terminal window and its path appears." msgstr "" -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " "arithmetic. This is the input absent from the first pseudocode view." msgstr "" -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5359,34 +6405,34 @@ msgid "" "coordinate by 30; adding {ph0} (20) gives the brick's screen position." msgstr "" -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the actual " "values; the instruction order tells the agent how they are used." msgstr "" -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 before " @@ -5394,7 +6440,7 @@ msgid "" " stereo field." msgstr "" -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205 inputs " @@ -5404,20 +6450,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5426,20 +6472,20 @@ msgid "" "this file parsed?” or “Which function handles this menu action?”" msgstr "" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the terminal. " "For a configured Ghidra installation:" msgstr "" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5448,7 +6494,7 @@ msgid "" "queries reuse the imported binary while that session is open." msgstr "" -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result leaves a call" @@ -5467,50 +6513,50 @@ msgid "" "constants and check reconstructed C." msgstr "" -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5518,7 +6564,7 @@ msgstr "" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5526,7 +6572,7 @@ msgstr "" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5534,7 +6580,7 @@ msgstr "" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5542,7 +6588,7 @@ msgstr "" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5550,7 +6596,7 @@ msgstr "" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5558,7 +6604,7 @@ msgstr "" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5566,7 +6612,7 @@ msgstr "" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5574,49 +6620,49 @@ msgstr "" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "" -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "REA gives your agent the tools to inspect a program and explain what it does." msgstr "" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "" #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5624,13 +6670,13 @@ msgstr "" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "" @@ -5643,16 +6689,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "" @@ -5664,7 +6710,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5672,12 +6718,12 @@ msgid "" "the setup plan for approval, then verify the installation.{ph4}{ph5}{ph6}" msgstr "" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "" @@ -5685,7 +6731,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5693,14 +6739,14 @@ msgid "" "guide →{ph2}" msgstr "" -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "Finding out how software works by {ph0}examining the program itself.{ph1}" @@ -5712,7 +6758,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5723,7 +6769,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -5731,7 +6777,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -5739,7 +6785,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -5747,7 +6793,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -5755,7 +6801,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -5765,48 +6811,48 @@ msgstr "" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "“{ph0}0x5b? 0x5c?{ph1} Two jumps to the same place. Which operators are these?”" msgstr "" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "" -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5814,43 +6860,43 @@ msgid "" "in?{ph1}”" msgstr "" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "" -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" "“This path multiplies by the other input. So {ph0}10% means 10% of 200{ph1} after +.”" msgstr "" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "" -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5860,20 +6906,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -5887,7 +6933,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" @@ -5900,7 +6946,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5908,42 +6954,42 @@ msgid "" "220?{ph4}{ph5}{ph6}" msgstr "" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "" -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5953,7 +6999,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5961,37 +7007,37 @@ msgid "" " rebuild its % button." msgstr "" -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5999,61 +7045,61 @@ msgid "" "fast it starts, how much it increases and when it stops." msgstr "" -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "" -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above remain " "readable." msgstr "" -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6069,7 +7115,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6081,7 +7127,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6091,14 +7137,14 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." msgstr "" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -6110,7 +7156,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6118,12 +7164,12 @@ msgid "" " is below {ph4}13{ph5}." msgstr "" -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "" @@ -6134,7 +7180,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6148,7 +7194,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6162,7 +7208,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6170,13 +7216,13 @@ msgid "" "acceleration, then choose your own pace.{ph5}" msgstr "" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6184,12 +7230,12 @@ msgid "" "returned the loaded {ph0}, including its source and digest." msgstr "" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "" -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check, with " @@ -6199,7 +7245,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6212,7 +7258,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6226,18 +7272,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Inspected speed code{ph1} · {ph2}Chromium Authors · BSD license{ph3}" msgstr "" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "" @@ -6245,7 +7291,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6255,7 +7301,7 @@ msgstr "" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "Build a small calculator that handles {ph0}both + and × correctly.{ph1}" @@ -6263,7 +7309,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6271,29 +7317,29 @@ msgid "" " app to find which number the percentage is applied to." msgstr "" -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "" -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6303,7 +7349,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6317,7 +7363,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Rebuild the % button" @@ -6329,7 +7375,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6337,12 +7383,12 @@ msgid "" "after + and ×, then build a small calculator that uses both.{ph3}{ph4}{ph5}" msgstr "" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "" @@ -6350,13 +7396,13 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "" @@ -6364,13 +7410,13 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "" @@ -6383,7 +7429,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6398,7 +7444,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6412,7 +7458,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6421,22 +7467,22 @@ msgid "" "above.{ph5}" msgstr "" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable summary " @@ -6453,7 +7499,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6461,27 +7507,27 @@ msgid "" "setup guide{ph5}" msgstr "" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "" -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "Download our Notes example, trace its CSV export, and check one changed input." msgstr "" -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "" @@ -6490,7 +7536,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6507,7 +7553,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" @@ -6520,14 +7566,14 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" "{ph0}›{ph1}{ph2}Use REA to inspect {ph3}. Clone this website for me.{ph4}{ph5}{ph6}" msgstr "" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "" @@ -6540,7 +7586,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Game reconstruction" @@ -6552,7 +7598,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6562,68 +7608,68 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables and " "libraries." msgstr "" -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder or ASAR " "archive." msgstr "" -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results across runs." msgstr "" -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "" @@ -6634,7 +7680,7 @@ msgstr "" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6642,19 +7688,19 @@ msgid "" "issue{ph5} for bugs and feature requests." msgstr "" -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow REA on X for" " project updates." msgstr "" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "" @@ -6671,63 +7717,63 @@ msgid "" "clear guides and try interactive examples with REA." msgstr "" -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is focused." msgstr "" -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "" @@ -6736,42 +7782,42 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation in an " "Android APK, then rebuild it with a clock you can control." msgstr "" -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "" @@ -6782,7 +7828,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6796,7 +7842,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6810,7 +7856,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6818,14 +7864,14 @@ msgid "" "browser demo reproduces the rule and checks it against public reference cases.{ph5}" msgstr "" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -6833,7 +7879,7 @@ msgstr "" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -6841,7 +7887,7 @@ msgstr "" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -6849,7 +7895,7 @@ msgstr "" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -6857,7 +7903,7 @@ msgstr "" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -6865,20 +7911,20 @@ msgstr "" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6894,14 +7940,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "" @@ -6913,7 +7959,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6924,7 +7970,7 @@ msgstr "" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6932,14 +7978,14 @@ msgid "" "{ph0}Get the APK and analysis setup ↓{ph1}" msgstr "" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6947,33 +7993,33 @@ msgid "" " the account key to generate a code. The same key and block produce the same code." msgstr "" -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "" @@ -6982,35 +8028,35 @@ msgstr "" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "" @@ -7019,7 +8065,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7029,7 +8075,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7037,35 +8083,35 @@ msgid "" "calculation recovered from the APK." msgstr "" -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the clock." msgstr "" -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7073,19 +8119,19 @@ msgid "" "imported accounts. TOTP means a time-based one-time password." msgstr "" -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7094,21 +8140,21 @@ msgid "" msgstr "" #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" "Requests show a shortened input path. Result class names omit the common {ph0} prefix." msgstr "" -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7119,7 +8165,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7127,7 +8173,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7135,25 +8181,25 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" msgstr "" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7163,7 +8209,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7173,7 +8219,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7185,7 +8231,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7193,7 +8239,7 @@ msgid "" "panel is an explanatory summary. {ph0}Aegis code is GPL-3.0.{ph1}" msgstr "" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "" @@ -7202,7 +8248,7 @@ msgstr "" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7210,12 +8256,12 @@ msgid "" " body; the original source calls the helper {ph3}." msgstr "" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "" -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a positive " @@ -7228,20 +8274,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "" -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7250,29 +8296,29 @@ msgid "" "time-block boundaries and codes beginning with zero." msgstr "" -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7280,37 +8326,37 @@ msgid "" "6238{ph1}. Check the browser implementation against them:" msgstr "" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-digit results." msgstr "" -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK was " "inspected statically." msgstr "" -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7320,7 +8366,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7328,28 +8374,28 @@ msgid "" "case used JDK 21." msgstr "" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "" -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7359,7 +8405,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7367,7 +8413,7 @@ msgid "" "time interval?{ph1}" msgstr "" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "" @@ -7382,7 +8428,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7394,13 +8440,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited to Aegis;" @@ -7419,37 +8465,37 @@ msgid "" "and try a reconstruction with an adjustable clock." msgstr "" -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "" @@ -7458,26 +8504,26 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "" #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7485,17 +8531,17 @@ msgid "" "input that makes the original program print {ph0}." msgstr "" -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "" @@ -7506,7 +8552,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7520,7 +8566,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7534,7 +8580,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7542,19 +8588,19 @@ msgid "" "solves the equations. REA captures the original program accepting the result.{ph5}" msgstr "" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7562,7 +8608,7 @@ msgstr "" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7570,7 +8616,7 @@ msgstr "" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7578,7 +8624,7 @@ msgstr "" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7586,7 +8632,7 @@ msgstr "" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7594,20 +8640,20 @@ msgstr "" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7623,15 +8669,15 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/showcase/ctf/index.html:271 website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "" @@ -7642,7 +8688,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7650,48 +8696,48 @@ msgid "" "checks work, then verify the answer with the original program.{ph3}{ph4}{ph5}" msgstr "" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a native " "analysis provider connected." msgstr "" -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "" -#: website/public/showcase/ctf/index.html:298 website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the executable's " "original function names have been removed." msgstr "" -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7700,19 +8746,19 @@ msgid "" "across {ph1} bytes give 26 masks." msgstr "" -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path is " "shortened for display; addresses refer to REA's imported image." msgstr "" -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells contribute to" @@ -7722,23 +8768,23 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "" -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "" @@ -7747,7 +8793,7 @@ msgstr "" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7756,12 +8802,12 @@ msgid "" "{ph2}, so that character is {ph3}." msgstr "" -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule in C." @@ -7769,7 +8815,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -7777,7 +8823,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -7785,7 +8831,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -7793,7 +8839,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -7801,18 +8847,18 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "" @@ -7820,7 +8866,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -7828,7 +8874,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7838,7 +8884,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7848,7 +8894,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7860,7 +8906,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7868,19 +8914,19 @@ msgid "" " mismatch jumps to {ph3}." msgstr "" -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an explanatory " "summary with descriptive names and a flattened 36-cell loop." msgstr "" -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 character codes " @@ -7888,13 +8934,13 @@ msgid "" "Python script can solve together." msgstr "" -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7903,19 +8949,19 @@ msgid "" "braces. The complete download includes all 26 masks and targets." msgstr "" -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7924,71 +8970,71 @@ msgid "" "of 1441, and the program rejects it." msgstr "" -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published challenge " "metadata, checked after solving the binary." msgstr "" -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 with Ghidra" " 12.1.4 on Linux x64. The binary is a stripped x86-64 ELF, 15,248 bytes." msgstr "" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "" -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading the " @@ -8007,7 +9053,7 @@ msgstr "" #. {ph4}: <a href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8015,35 +9061,35 @@ msgid "" "· {ph4}REA evidence notes{ph5}" msgstr "" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the prompt above " "to investigate with your agent, or run the included script." msgstr "" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "" -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8051,7 +9097,7 @@ msgid "" "Python and {ph0}. Running the original executable needs Linux x86-64." msgstr "" -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "" @@ -8068,27 +9114,27 @@ msgid "" "functions, extract the masks and compare a recovered flag with the original program." msgstr "" -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only that cell " @@ -8096,42 +9142,42 @@ msgid "" "is 7." msgstr "" -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "" @@ -8140,39 +9186,39 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "" -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the agent " "inspect the original, one function at a time." msgstr "" -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8181,14 +9227,14 @@ msgid "" "figure{ph1}" msgstr "" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8196,7 +9242,7 @@ msgstr "" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8204,7 +9250,7 @@ msgstr "" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8212,23 +9258,23 @@ msgstr "" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "" @@ -8239,7 +9285,7 @@ msgstr "" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8247,12 +9293,12 @@ msgid "" "coverage{ph3}" msgstr "" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, animations, " @@ -8261,12 +9307,12 @@ msgid "" "power-up handling and Windows integration." msgstr "" -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. The " @@ -8282,17 +9328,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "" @@ -8303,7 +9349,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8311,14 +9357,14 @@ msgid "" "calculation and show the code.{ph3}{ph4}{ph5}" msgstr "" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable available. The " "investigation below shows the REA queries and evidence behind the answer." msgstr "" -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and read the " @@ -8329,7 +9375,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8338,48 +9384,48 @@ msgid "" "discrepancy gave the agent a concrete reason to keep investigating." msgstr "" -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals the input " "and the calculation feeding that call." msgstr "" -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8387,19 +9433,19 @@ msgid "" "{ph0} exposes the integer input missing from the decompiler view." msgstr "" -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8407,36 +9453,36 @@ msgid "" " by 30; adding 20 gives the brick's screen coordinate, {ph1}." msgstr "" -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan scale. The " "agent now has the values needed for the C expression." msgstr "" -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original instructions and " @@ -8445,7 +9491,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8453,7 +9499,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8461,7 +9507,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8469,7 +9515,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8477,18 +9523,18 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "" @@ -8498,7 +9544,7 @@ msgstr "" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8513,7 +9559,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8527,7 +9573,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8541,7 +9587,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8555,7 +9601,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8564,30 +9610,30 @@ msgid "" "returned value." msgstr "" -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. The full " "listing below also includes the intervening stores and function setup and cleanup." msgstr "" -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8595,54 +9641,54 @@ msgid "" " it before the call:" msgstr "" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -8655,31 +9701,31 @@ msgstr "" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" "{ph0}Maintained source{ph1} · {ph2}Investigation notes and evidence references{ph3}" msgstr "" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the original, and " "its compiled bytes match the executable." msgstr "" -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value with the " @@ -8687,12 +9733,12 @@ msgid "" "0.5, 1, 20 and −1." msgstr "" -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay matches " @@ -8700,7 +9746,7 @@ msgid "" "referenced constants." msgstr "" -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 at the " @@ -8711,18 +9757,18 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and bonus " @@ -8730,14 +9776,14 @@ msgid "" " compare the implementation with the original." msgstr "" -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's setup " "instructions and supply its matching original target. Then run:" msgstr "" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "" @@ -8746,7 +9792,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}DX-Ball repository{ph1}{ph2}Current source, progress and local setup.{ph3}" @@ -8756,7 +9802,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8769,7 +9815,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8777,7 +9823,7 @@ msgid "" " and pixel writes.{ph3}" msgstr "" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "" @@ -8794,12 +9840,12 @@ msgid "" "original-x86 tests and matching compiled function bytes." msgstr "" -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller supplies 20 " @@ -8808,170 +9854,170 @@ msgid "" " original x86 in 3,205 cases and by VC4.0 compiler replay matching 63 bytes." msgstr "" -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "" -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked results." msgstr "" -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the generating " "methods with REA, then move a demo clock to see why the code changes every 30 seconds." msgstr "" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "" -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking functions, turn " "masks and sums into equations, then verify the solved flag with the original program." msgstr "" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "" -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's instructions, caller " @@ -8979,42 +10025,42 @@ msgid "" "original behavior and all 63 compiled bytes." msgstr "" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "" -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC wrappers " @@ -9022,42 +10068,42 @@ msgid "" "connected to a copy." msgstr "" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "" -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, divide and " @@ -9065,44 +10111,44 @@ msgid "" "player." msgstr "" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "" -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a browser " "request. Each starts with a prompt and a concrete target." msgstr "" -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "" @@ -9119,12 +10165,12 @@ msgid "" "DX-Ball, Notion, TH04 and a DownUnderCTF flag checker." msgstr "" -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "" @@ -9133,37 +10179,37 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "" -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main process, " "to Electron's clipboard writer." msgstr "" -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "" @@ -9175,7 +10221,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9190,7 +10236,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9205,7 +10251,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9220,7 +10266,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9229,27 +10275,27 @@ msgid "" msgstr "" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. Resolving the" " wrappers reveals the Electron calls behind those names." msgstr "" -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9257,7 +10303,7 @@ msgstr "" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9265,19 +10311,19 @@ msgstr "" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9293,17 +10339,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "" @@ -9314,7 +10360,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9322,19 +10368,19 @@ msgid "" "clipboard. Show the code at each step.{ph3}{ph4}{ph5}" msgstr "" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your coding " "agent." msgstr "" -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and the call " @@ -9342,23 +10388,23 @@ msgid "" "bundle:" msgstr "" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9368,7 +10414,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9377,32 +10423,32 @@ msgid "" " to look for in the main bundle. The four excerpts below show the route it connects." msgstr "" -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. Unrelated " "members are omitted." msgstr "" -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9410,20 +10456,20 @@ msgid "" "request leaves the page's process." msgstr "" -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9431,13 +10477,13 @@ msgid "" "IPC. We can now look for {ph0} on the main-process side." msgstr "" -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" @@ -9445,7 +10491,7 @@ msgstr "" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9453,19 +10499,19 @@ msgid "" "for that channel." msgstr "" -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" msgstr "" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the supplied " @@ -9473,13 +10519,13 @@ msgid "" "the exposed method to this call." msgstr "" -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9487,100 +10533,100 @@ msgid "" " and puts an ID in the copied HTML to connect them." msgstr "" -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data when IDs " "match; a stale entry returns only text and HTML." msgstr "" -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy. Matching " "IDs restore the block data." msgstr "" -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table becomes header " "and data rows." msgstr "" -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows and cells." msgstr "" -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9589,14 +10635,14 @@ msgid "" "Subsequent statement batches and results travel over that port." msgstr "" -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why tracing only the" " initial IPC request misses the later conversation." msgstr "" -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "" @@ -9604,7 +10650,7 @@ msgstr "" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9617,7 +10663,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9627,7 +10673,7 @@ msgid "" "describe those probes rather than a captured desktop UI session." msgstr "" -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, recorded " @@ -9637,7 +10683,7 @@ msgid "" msgstr "" #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9650,7 +10696,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9662,7 +10708,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9670,7 +10716,7 @@ msgid "" "function.{ph3}" msgstr "" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "" @@ -9687,52 +10733,52 @@ msgid "" "process, with short code excerpts and a look at its rich clipboard format." msgstr "" -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "" @@ -9741,42 +10787,42 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "" -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect the " "original DOS function, then follow its instructions into readable C++." msgstr "" -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "" @@ -9787,7 +10833,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9801,7 +10847,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9815,7 +10861,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9829,7 +10875,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9837,21 +10883,21 @@ msgid "" "checks cover the bullet-generation code that contains this helper.{ph5}" msgstr "" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project supplies the" " maintained source and compiler checks." msgstr "" -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -9859,7 +10905,7 @@ msgstr "" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -9867,7 +10913,7 @@ msgstr "" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -9875,7 +10921,7 @@ msgstr "" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -9883,18 +10929,18 @@ msgstr "" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper " @@ -9910,16 +10956,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "" @@ -9930,7 +10976,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9938,7 +10984,7 @@ msgid "" "player. Explain the calculation and show the code.{ph3}{ph4}{ph5}" msgstr "" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout available " @@ -9946,7 +10992,7 @@ msgid "" msgstr "" #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9956,7 +11002,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9964,12 +11010,12 @@ msgid "" "template rotation 0. {ph0}Open figure{ph1}" msgstr "" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "" @@ -9978,7 +11024,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9986,13 +11032,13 @@ msgid "" " attack's source{ph1}." msgstr "" -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10001,41 +11047,41 @@ msgid "" "pattern." msgstr "" -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied executable. The " "path above is shortened for display." msgstr "" -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "" @@ -10043,7 +11089,7 @@ msgstr "" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10052,22 +11098,22 @@ msgid "" "sequence appears below." msgstr "" -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction helper. Its" @@ -10075,12 +11121,12 @@ msgid "" "readable; REA lets the agent check the original operations behind them." msgstr "" -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation. This " @@ -10090,7 +11136,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10098,7 +11144,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10106,7 +11152,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10114,7 +11160,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10122,18 +11168,18 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "" @@ -10141,7 +11187,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10153,7 +11199,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10165,7 +11211,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10177,7 +11223,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10189,7 +11235,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10198,7 +11244,7 @@ msgid "" "surrounding source also converts this angle and speed into velocity." msgstr "" -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store. The C++ " @@ -10206,17 +11252,17 @@ msgid "" "the linked project." msgstr "" -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "" @@ -10233,7 +11279,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10241,36 +11287,36 @@ msgid "" "representation{ph5}" msgstr "" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, including this " "helper, with its pinned Turbo C++ 4.0J toolchain." msgstr "" -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the original " "executable." msgstr "" -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input hashes match " @@ -10281,65 +11327,65 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "" -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this helper. " @@ -10347,7 +11393,7 @@ msgid "" msgstr "" #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10357,7 +11403,7 @@ msgid "" msgstr "" #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10368,19 +11414,19 @@ msgid "" "open." msgstr "" -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and PC-98 " "hardware behavior have separate runtime checks in the reconstruction project." msgstr "" -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and assembly. " @@ -10390,7 +11436,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10402,7 +11448,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10416,7 +11462,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10430,7 +11476,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10450,27 +11496,27 @@ msgid "" "C++ to see how a ring of bullets is spaced and aimed at the player." msgstr "" -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. Adding a player" @@ -10479,27 +11525,27 @@ msgid "" "degrees." msgstr "" -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "" @@ -10619,14 +11665,14 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "" -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-game check " "when rounded to three decimals." msgstr "" -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed rule and " @@ -10674,6 +11720,16 @@ msgctxt "runtime" msgid "REA on GitHub ({count})" msgstr "" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "" + #: website/public/assets/figures/analyst-thinking.svg:2 msgctxt "figure:analyst-thinking.svg" msgid "An analyst thinking at a computer" diff --git a/website/locales/pl/messages.po b/website/locales/pl/messages.po index 05052a169..d97cd87f1 100644 --- a/website/locales/pl/messages.po +++ b/website/locales/pl/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Przejdź do treści" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Spis treści{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Myśli o inżynierii odwrotnej." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Rekonstrukcja gry{ph0}Esej" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Rewolucja przemysłowa w inżynierii odwrotnej" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "Co Instrukcja RE i rekonstrukcji TH08, TH095 i TH04 nauczył mnie O agentów, " "weryfikacja i wiedza, że związki całej projektów." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Przeczytaj artykuł" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Przez N0zoM1z0 * 10 października 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "doświadczenia z agentami REA i AI." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -135,112 +138,117 @@ msgstr "" "REA-dowiedz się, jak działa oprogramowanie. Inżynieria odwrotna z twoim " "agentem kodującym." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Strona główna REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Główna nawigacja" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA na GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Dołącz do REA na Discordzie" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Obserwuj REA na X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -249,35 +257,35 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Spis treści{ph1} / {ph2}Blog{ph3} / Rekonstrukcja Touhou" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Esej * rekonstrukcja Touhou" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Rewolucja przemysłowa w inżynierii odwrotnej." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Przez N0zoM1z0 * 10 października 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Najważniejsze" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -289,7 +297,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -303,7 +311,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -316,7 +324,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -329,7 +337,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -339,65 +347,65 @@ msgstr "" "{ph0}Jesteśmy w pierwszych dniach rewolucji przemysłowej RE.{ph1} Metody " "wciąż nabierają kształtu. Pozostało wiele do odkrycia." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Jak doświadczyć związków" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Human direction{ph1} * Kryteria celu i akceptacji" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Samodzielność" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agent" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Wybierz eksperyment.{ph0}Zaproponuj hipotezę." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Weryfikacja" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Wzorzec weryfikacji" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Test przeciwko{ph0}konkretne odniesienie." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Repozytorium" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Pamięć robocza" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -406,7 +414,7 @@ msgstr "Kod, dowód,{ph0}czeki i lekcje." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -415,26 +423,26 @@ msgstr "Niedopasowanie{ph0}{ph1}Zrewiduj hipotezę{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "A better{ph0}{ph1}punkt wyjścia{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Ponowne wykorzystanie" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Przełęcz{ph1} * Zachowaj wynik i jego dowody" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -443,14 +451,14 @@ msgstr "" "Każdy projekt pozostawia następny z lepszym punktem wyjścia. Obejmuje to " "ustalenie czeków, gdy odkryjemy lukę." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "W tym artykule" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -458,7 +466,7 @@ msgstr "{ph0}Sierpień 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -466,7 +474,7 @@ msgstr "{ph0} TH08: kontynuacja{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -474,7 +482,7 @@ msgstr "{ph0}Dwa podejścia{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -482,7 +490,7 @@ msgstr "{ph0} TH095: składanie{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -490,7 +498,7 @@ msgstr "{ph0} TH04: w różnych architekturach{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -498,7 +506,7 @@ msgstr "{ph0}Od dokładnego do czytelnego{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -506,18 +514,18 @@ msgstr "{ph0}Zmiana przemysłowa{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Co staje się możliwe{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Co się zmieniło w sierpniu 2026 roku" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -532,7 +540,7 @@ msgstr "" " ilości czasu na następnej funkcji. Oznaczało to również utrzymanie coraz " "większego obrazu w mojej głowie." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -546,7 +554,7 @@ msgstr "" "przydatna gdzie indziej, ale każde pole musi ustalić, co może sprawdzić z " "wiarygodnym odniesieniem." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -559,7 +567,7 @@ msgstr "" " zwykłych narzędzi programistycznych. Rekonstrukcja Touhou dała mi znaczący " "projekt, w którym mogę się dowiedzieć." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -576,7 +584,7 @@ msgstr "" "mogłem poświęcić więcej uwagi kierunkowi projektu i temu, czy jego kontrole " "są godne zaufania." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -587,7 +595,7 @@ msgstr "" "przetrwa poza obecnym projektem. Czy następna gra skorzysta na wszystkim, " "czego się właśnie nauczyliśmy?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: budowanie na ludzkiej pracy" @@ -596,7 +604,7 @@ msgstr "TH08: budowanie na ludzkiej pracy" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -610,7 +618,7 @@ msgstr "" "podstawy. Przyszedł ze znajomością budowy i historią wkładów, które " "zachowałem w kontynuacji." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -621,7 +629,7 @@ msgstr "" " Moja niezależna kontynuacja rozpoczęła się 13 sierpnia. Do 19 sierpnia " "Księga rejestrowała źródło wszystkich 1107 zidentyfikowanych funkcji gry." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -632,7 +640,7 @@ msgstr "" "więcej jedenaście dni po rozpoczęciu kontynuacji. Nastąpiło wydanie " "internetowe. Natywna 64-bitowa wersja Linux pojawiła się 30 sierpnia." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -648,7 +656,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -666,12 +674,12 @@ msgstr "" "oczekiwany stan. Agent proponuje wyjaśnienie i testuje je; niedopasowanie " "daje mu coś konkretnego do zbadania." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Dokładne dopasowanie z niewłaściwą stałą" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -682,7 +690,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -694,7 +702,7 @@ msgstr "" "automatycznego zbierania przedmiotów. Zrekonstruowane źródło sprawdziło moc " "gracza przeciwko {ph0}. Oryginalny używany {ph1}, maksymalny próg mocy." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -709,13 +717,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}Jednak funkcja przeszła już dokładne porównanie.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -730,7 +738,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -746,7 +754,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -760,7 +768,7 @@ msgstr "" " stałych zmiennoprzecinkowych odniesień. Znalazł kolejne dwanaście błędnych " "odniesień w pięciu akceptowanych funkcjach." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -774,7 +782,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -784,7 +792,7 @@ msgstr "" "{ph0}Referencja weryfikacyjna (oracle) również wymagała rekonstrukcji.{ph1} " "Naprawa była częścią naprawy gry." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -802,7 +810,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -819,7 +827,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -829,7 +837,7 @@ msgstr "" "{ph0}Udana partia dała nam zarówno odzyskany Kod, jak i lepsze środowisko " "dla następnej partii.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Dwie różne koncepcje rekonstrukcji" @@ -838,7 +846,7 @@ msgstr "Dwie różne koncepcje rekonstrukcji" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -850,7 +858,7 @@ msgstr "" "rodzaju pracy. W zawiadomieniu zapowiada się, że dalszy rozwój nastąpi " "prywatnie do czasu zakończenia. Jeden fragment brzmi:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -859,7 +867,7 @@ msgstr "" "Powstanie grifterów (dekompilacje AI i porty) w tej przestrzeni biorąc z " "naszej pracy maluje zły obraz dla przyszłych wysiłków dekompilacyjnych…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -876,7 +884,7 @@ msgstr "" "który chcę omówić, dotyczy tego, jak powinna przebiegać odbudowa i jak " "należy oceniać wkład." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -889,7 +897,7 @@ msgstr "" " opierał się na wiedzy tej osoby. Zaufanie do współpracownika miało " "znaczenie, ponieważ tak wiele rozumowania wydarzyło się, gdy pracowali." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -900,7 +908,7 @@ msgstr "" "Zmieniło się dla mnie to, że agent mógł wykorzystać tę wiedzę do " "samodzielnego prowadzenia następnego śledztwa." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -915,7 +923,7 @@ msgstr "" " dlaczego wybraliśmy implementację, nawet jeśli agent wykonał większość " "pracy." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -928,7 +936,7 @@ msgstr "" " dotyczące kredytu. Zmienia również to, co opiekunowie muszą wiedzieć przed " "przyjęciem wkładu." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -943,7 +951,7 @@ msgstr "" "proces i rozpoznać, kiedy jego wynik jest nieprawidłowy. Różne społeczności " "mogą wybrać, ile z tej zmiany chcą podjąć." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -968,7 +976,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -981,14 +989,14 @@ msgstr "" " fragmentem. TH08 {ph4}kredyty i pochodzenie{ph5} Zapisz granicę " "kontynuacji." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: doświadczenie zaczyna się mieszać" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1003,7 +1011,7 @@ msgstr "" " nauczyć się gry. Ale wiedzieliśmy już znacznie więcej o tym, jak rozpocząć " "rekonstrukcję i jak ją utrzymać." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1016,7 +1024,7 @@ msgstr "" " połączył się 9 września. Rekonstrukcja Windows i386 została oznaczona jako " "grywalna 10 września, około dwanaście dni po inicjalizacji." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1027,7 +1035,7 @@ msgstr "" " mógłby skorzystać z pracy wykonanej nad inną grą. Doświadczenie było już " "obecne w narzędziach i sposobie organizacji projektu." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1042,7 +1050,7 @@ msgstr "" "razem. Ta lekcja pomogła ukształtować sposób, w jaki zbliżyliśmy się do " "kompilacji całego programu TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1055,7 +1063,7 @@ msgstr "" " po przejściu dalej. Następny agent może wykorzystać wynik bez powtarzania " "dochodzenia, które do niego doprowadziło." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1070,7 +1078,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1082,7 +1090,7 @@ msgstr "" "Możemy poświęcić więcej wysiłku następnego projektu na to, co jest naprawdę " "nowe w jego celu." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1095,7 +1103,7 @@ msgstr "" " rekonstruować całej historii projektu, aby dowiedzieć się, dlaczego źródło " "wygląda tak, jak wygląda." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: przepływ pracy przetrwa inną architekturę" @@ -1104,7 +1112,7 @@ msgstr "TH04: przepływ pracy przetrwa inną architekturę" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1120,7 +1128,7 @@ msgstr "" "Windows. Istniejące {ph2}ReC98 praca{ph3} dał nam również cenną wiedzę i " "materiały źródłowe." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1133,7 +1141,7 @@ msgstr "" "natywny port 64-bitowy. Ustanowienie działającej wersji DOS najpierw daje " "temu portowi odniesienie." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1146,7 +1154,7 @@ msgstr "" "nadal podążać za pytaniem aż do wyniku i pozwolić temu wynikowi kierować " "następnym eksperymentem." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1161,7 +1169,7 @@ msgstr "" "dostępne, agent może przepracować pytanie tak samo, jak w przypadku tytułu " "Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1173,7 +1181,7 @@ msgstr "" "zdefiniowała problem; przepływ pracy nadal dał nam sposób na jego " "rozwiązanie." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1190,7 +1198,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1200,19 +1208,19 @@ msgstr "" "Stan projektu na 10 października 2026 r: {ph0}Rekonstrukcja DOS i testy " "ręczne{ph1} · {ph2}Port 64-bitowy{ph3}. Port pozostaje w fazie rozwoju." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Od dokładnego kodu do czytelnego kodu" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "Gdy rekonstrukcja zadziała, chcę, aby ktoś inny mógł to zrozumieć." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1227,7 +1235,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1243,7 +1251,7 @@ msgstr "" "typ, który pasuje do dowodów. Trzymamy rozumowanie ze źródłem, aby następna " "osoba mogła zobaczyć, skąd pochodzi ta interpretacja." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1258,14 +1266,14 @@ msgstr "" "powinien posiadać ten stan. Aby bezpiecznie przenieść zachowanie, musimy " "odzyskać związek stojący za starym dostępem do pamięci." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Kolejność, której teraz używam, to:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1281,7 +1289,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1298,7 +1306,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1314,7 +1322,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1329,7 +1337,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1346,7 +1354,7 @@ msgstr "" "program nadal buduje i zachowuje się poprawnie wzdłuż ścieżek, które " "ćwiczymy." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1359,7 +1367,7 @@ msgstr "" "Utrzymywanie obu dostępnych kontroli daje agentowi konkretny brak zbadania " "przed dalszym przenoszeniem refaktora." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1377,7 +1385,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1396,7 +1404,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1407,12 +1415,12 @@ msgstr "" "sprawia, że odzyskana wiedza jest użyteczna.{ph1} Port może następnie " "budować na obu." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Co sprawia, że jest to zmiana przemysłowa" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1425,7 +1433,7 @@ msgstr "" "z najbardziej przydatnych rzeczy, jakie mogłem zrobić. Lepsze narzędzie może" " pomóc w każdej późniejszej funkcji, która tego potrzebowała." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1438,7 +1446,7 @@ msgstr "" " aby śledzić ten wynik w nieoczekiwanym miejscu. Jeśli musi czekać, aż " "przepiszę każdy krok, znaczna część pracy pozostaje związana z moją uwagą." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1451,7 +1459,7 @@ msgstr "" "zrozumieć błąd na tyle dobrze, aby spróbować ponownie. Nadal muszę " "zdecydować, czy zgromadzone dowody potwierdzają kamień milowy projektu." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1466,7 +1474,7 @@ msgstr "" "referencyjne. Agent może ich użyć do przetestowania proponowanego źródła i " "sprawdzenia, gdzie znajduje się jego wyjaśnienie." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1484,7 +1492,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1504,7 +1512,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1521,7 +1529,7 @@ msgstr "" " ją naprawić i Ponownie sprawdzić wyniki, na które wpłynęło. Następny " "projekt może następnie odziedziczyć silniejsze narzędzie." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1537,7 +1545,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1549,7 +1557,7 @@ msgstr "" " wspólny sposób na kontynuowanie kontroli i lekcji. Praca nad jedną grą może" " poprawić warunki początkowe dla innej." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1561,12 +1569,12 @@ msgstr "" "Ulepszenie tych narzędzi zmienia, ile może zrobić następna osoba—lub " "następny agent." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Projekty, które możemy teraz rozważyć" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1577,7 +1585,7 @@ msgstr "" "fascynująca w inżynierii wstecznej i nadal wymagać więcej mojej uwagi, niż " "realistycznie mógłbym jej poświęcić. Wiele projektów pozostanie pomysłami." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1594,7 +1602,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1605,7 +1613,7 @@ msgstr "" "zwrotne i zgromadzona wiedza pozwoliłyby agentowi pracować nad tym " "niezawodnie?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1616,12 +1624,12 @@ msgstr "" " sam. Każdy z nich może poprawić sposób, w jaki podchodzimy do następnego. " "Chcę dalej badać, jak daleko to może nas zaprowadzić." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Kamienie milowe i źródła projektu" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1656,7 +1664,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1690,7 +1698,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1708,7 +1716,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1732,7 +1740,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1754,7 +1762,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1770,7 +1778,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1792,7 +1800,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1806,7 +1814,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1827,27 +1835,27 @@ msgstr "" "pomocą agentów AI oraz sposób, w jaki wiedza łączy się z TH08 , TH095 i " "PC-98 TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Doświadczenie prowadzone między projektami" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Esej rekonstrukcyjny Touhou" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -1856,18 +1864,18 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Spis treści{ph1}{ph2}/{ph3}Dinosaur speed lab" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Sprawdź → Odbuduj → Zmień" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Odbuduj zasadę prędkości dinozaura." @@ -1876,7 +1884,7 @@ msgstr "Odbuduj zasadę prędkości dinozaura." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1888,15 +1896,15 @@ msgstr "" "prędkość. {ph0} REA zwrócił uruchomiony skrypt;{ph1} użyliśmy jego reguły, " "aby zbudować tę mini-grę z {ph2}regulowana prędkość.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Na tej stronie" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1904,7 +1912,7 @@ msgstr "{ph0}Graj i zmieniaj prędkość{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1912,7 +1920,7 @@ msgstr "{ph0}Przeczytaj odzyskaną regułę{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1920,18 +1928,18 @@ msgstr "{ph0}Sprawdź rekonstrukcję{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Wypróbuj analizę{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Graj i zmieniaj prędkość" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1943,49 +1951,49 @@ msgstr "" " prędkość. Wybierz odzyskaną regułę, aby rozpocząć od 6 i stopniowo ponownie" " przyspieszać." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Zagraj w odtworzoną wersję" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Graj" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Skok ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Zacznij od nowa" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Prędkość" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Użyj reguły odzyskiwania przyspieszenia" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Pierwotna zasada: zacznij od 6, a następnie zwiększ do 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Przesuń suwak, aby ustawić własną prędkość. Przestrzeń lub skok usuwa " "kaktusa." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -1994,7 +2002,7 @@ msgstr "" "Włącz JavaScript, aby odtworzyć rekonstrukcję. Powyższy kod i Wyjaśnienie " "pozostają czytelne." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Przeczytaj skrypt REA zwrócony" @@ -2002,7 +2010,7 @@ msgstr "Przeczytaj skrypt REA zwrócony" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2017,7 +2025,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2027,18 +2035,18 @@ msgstr "" "Ustawienia to {ph0}, {ph1} oraz {ph2}. Gra uruchamia tę gałąź na " "aktualizacji bez kolizji." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Użyj tej samej zasady w nowej grze" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Kopiuj" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2056,18 +2064,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}Pobierz regułę prędkości{ph1} · {ph2}Przeczytaj kod gry{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Sprawdź rekonstrukcję" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2078,27 +2086,27 @@ msgstr "" "automatycznym planowaniem. Porównaj te zarejestrowane prędkości z powtórką " "odzyskanej reguły." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Aktualizacje" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Oryginalna gra" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Zrekonstruowana reguła" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Uruchom kontrolę prędkości" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2107,14 +2115,14 @@ msgstr "" "Wartości zaokrąglone do trzech miejsc po przecinku. Oddział sprawdza przed " "dodaniem, więc ostateczny przyrost może przybrać prędkość nieco powyżej 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Wypróbuj analizę samodzielnie" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2123,7 +2131,7 @@ msgstr "{ph0}Skonfiguruj REA {ph1} z twoim agentem kodującym." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2132,7 +2140,7 @@ msgstr "" "Śledź {ph0}kroki połączenia przeglądarki{ph1}, za pomocą {ph2} jako adres " "URL strony." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2149,7 +2157,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2161,7 +2169,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2175,7 +2183,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2190,7 +2198,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2216,12 +2224,12 @@ msgstr "" "Przeczytaj zasadę prędkości gry dinozaurów za pomocą REA, Odbuduj ją, a " "następnie zmień prędkość i graj." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Rekonstrukcja prędkości dinozaurów" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2230,52 +2238,52 @@ msgstr "" "Dinozaur mini-gry. Użyj przycisku skoku lub naciśnij spację, gdy gra jest " "skupiona." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Skopiuj zrekonstruowaną regułę prędkości" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Skopiuj monit o analizę dinozaurów" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Przejdź do treści" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Spis treści{ph1} / FAQ" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA FAQ." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Konfiguracja, aktualizacje, analiza i rozwiązywanie problemów." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Tematy" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2283,7 +2291,7 @@ msgstr "{ph0}Konfiguracja i aktualizacje{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2291,7 +2299,7 @@ msgstr "{ph0}Analiza{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2299,31 +2307,31 @@ msgstr "{ph0}Rozwiązywanie problemów{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Dane i udostępnianie{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Konfiguracja i aktualizacje" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Jak zainstalować REA ?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * konfiguracja agenta" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Kopiuj" @@ -2331,7 +2339,7 @@ msgstr "Kopiuj" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2345,12 +2353,12 @@ msgstr "" "oraz pytanie. Wymagania i pierwszą analizę opisuje {ph0}instrukcja " "konfiguracji{ph1}." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Które środki kodujące mogą używać REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2365,18 +2373,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Podłącz swojego agenta kodującego{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Jak zaktualizować REA ?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2384,13 +2392,13 @@ msgid "" msgstr "" "REA wydaje często, w tym poprawki błędów. Jeśli zainstalowałeś CLI z npm :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * zainstalowany CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2400,14 +2408,14 @@ msgstr "" "Postępuj zgodnie z poleceniem odświeżania konfiguracji wydrukowanym przez " "aktualizację. Jeśli ustawisz swojego agenta przez {ph0}, biegnij:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * konfiguracja agenta odświeżania" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2419,14 +2427,14 @@ msgstr "" "wersji pakietu. Powtórz konfigurację, aby agent korzystał z nowej wersji. " "Przy jednorazowym wywołaniu CLI dodaj polecenie po {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Instaluje umiejętność z skills.sh wystarczy?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2438,24 +2446,24 @@ msgstr "" "REA{ph1} aby połączyć serwer MCP i zainstalować umiejętność dopasowywania, " "uruchom ponownie agenta, aby mógł wywołać narzędzia." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Analiza" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Co mogę analizować za pomocą REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Zacznij od rodzaju posiadanego oprogramowania:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2467,7 +2475,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2479,7 +2487,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2489,7 +2497,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2501,12 +2509,12 @@ msgstr "" " Android, oprogramowania układowego i pakietów zasobów. {ph0}Zobacz studia " "przypadków{ph1} do prowadzonych dochodzeń." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Czy potrzebuję Hopper, Ghidra lub IDA ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2518,7 +2526,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2530,12 +2538,12 @@ msgstr "" " Hopper i zaproponować instalację. Twój host i cel określają, który dostawca" " może być używany. {ph0}Skonfiguruj analizę programów kodu maszynowego{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Czy Mogę używać REA bez agenta kodującego?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2544,14 +2552,14 @@ msgstr "" "Tak. CLI wykorzystuje te same przepływy pracy analizy. Dla lokalnej " "aplikacji JavaScript lub Electron:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * statyczna analiza aplikacji" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2562,13 +2570,13 @@ msgstr "" "CLI {ph1} dla opcji instalacji." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Jaki kod zwraca REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2583,7 +2591,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2595,12 +2603,12 @@ msgstr "" "przetestować implementację. The {ph0} Obliczanie DX-Ball{ph1} oraz {ph2}CTF " "flag checker{ph3} pokaż, jak działa ten proces." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "O co zapytać agenta?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2617,7 +2625,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2625,7 +2633,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2635,18 +2643,18 @@ msgstr "" "Zastąp ścieżkę swoim celem. The {ph0}Przewodniki{ph1} podaj monity o " "przykłady natywne, Electron i przeglądarki." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Rozwiązywanie problemów" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Dlaczego mój agent nie widzi narzędzi REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2656,7 +2664,7 @@ msgstr "" "Uruchom ponownie lub podłącz ponownie agenta po konfiguracji. Sprawdź swoją " "rejestrację REA z {ph0}; dla Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * sprawdź jednego klienta" @@ -2664,7 +2672,7 @@ msgstr "Terminal * sprawdź jednego klienta" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2675,14 +2683,14 @@ msgstr "" "raport pokazuje brakującą lub nieaktualną rejestrację, Uruchom setup dla " "tego klienta:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * naprawa konfiguracji jednego klienta" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2694,14 +2702,14 @@ msgstr "" "zdrowa, ale narzędzia pozostają nieobecne, sprawdź błąd połączenia MCP " "klienta. {ph0}Więcej diagnostyki konfiguracji{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Czy muszę najpierw uruchomić Hopper?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2713,14 +2721,14 @@ msgstr "" "pierwszego wyboru trybu demonstracyjnego lub aktywacji licencji przed " "analizą nienadzorowaną. {ph0}Zobacz native provider setup{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Co zrobić, gdy znajdę błąd?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2732,7 +2740,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2745,17 +2753,17 @@ msgstr "" "Uwzględnij nazwę dostawcy, gdy problem obejmuje analizę programów kodu " "maszynowego." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Dane i udostępnianie" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "Czy REA przesyła moją aplikację?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2764,7 +2772,7 @@ msgstr "" "REA analizuje cele na twoim komputerze. Twój agent otrzymuje wyniki, a " "zasady dotyczące danych dostawcy modelu mają zastosowanie do tych wyników." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Jak mogę podzielić się przykładem lub wnieść swój wkład?" @@ -2773,7 +2781,7 @@ msgstr "Jak mogę podzielić się przykładem lub wnieść swój wkład?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2789,7 +2797,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2815,77 +2823,77 @@ msgstr "" "analityczne, środki kodujące, rozwiązywanie problemów i udostępnianie " "przykładów." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Często zadawane pytania dotyczące REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Skopiuj polecenie konfiguracji REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Skopiuj polecenie aktualizacji REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Skopiuj polecenie odświeżania konfiguracji agenta" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Skopiuj polecenie analizy REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Skopiuj przykładowy monit o analizę" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Skopiuj polecenie diagnozy klienta" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Skopiuj polecenie konfiguracji z zakresem" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Przejdź do treści" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Spis treści{ph1} / Twoje pierwsze śledztwo" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Dowiedz się, gdzie{ph0}eksportowane notatki go." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2894,14 +2902,14 @@ msgstr "" "Użyj REA, aby sprawdzić małą aplikację, postępuj zgodnie z jej przyciskiem " "Eksportuj notatki i sam sprawdź jeden szczegół." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "W tym ćwiczeniu" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2909,7 +2917,7 @@ msgstr "{ph0}1. Skonfiguruj{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2917,7 +2925,7 @@ msgstr "{ph0}2. Zapytaj o eksport{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2925,7 +2933,7 @@ msgstr "{ph0}3. Postępuj zgodnie z odpowiedzią{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2933,13 +2941,13 @@ msgstr "{ph0}4. Sprawdź prognozę{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Zadaj kolejne pytanie{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Połącz swojego agenta z REA" @@ -2952,29 +2960,29 @@ msgstr "1. Połącz swojego agenta z REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Kopiuj" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Lub uruchom to polecenie w swoim terminalu:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2983,14 +2991,14 @@ msgstr "" "Przejrzyj plan, Zatwierdź konfigurację, a następnie uruchom ponownie agenta." " Już podłączony? Kontynuuj poniżej." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Zapytaj, gdzie jest napisane CSV" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3002,7 +3010,7 @@ msgstr "" "notatki{ph1} przycisk. Twój agent może sprawdzić swój kod bez instalowania " "lub uruchamiania Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3013,14 +3021,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Pobierz przykład ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3030,12 +3038,12 @@ msgstr "" "Jeśli twój agent nie może pobrać plików, rozpakuj to archiwum samodzielnie. " "Daj mu drogę do {ph0} folder i to samo pytanie o eksport." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Postępuj zgodnie z odpowiedzią z powrotem do kodu" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Poszukaj krótkiego wyjaśnienia z odniesieniami do plików i linii:" @@ -3044,7 +3052,7 @@ msgstr "Poszukaj krótkiego wyjaśnienia z odniesieniami do plików i linii:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3055,12 +3063,12 @@ msgstr "" "Przycisk wysyła {ph0} wiadomość. Główny proces formatuje notatki jako CSV i " "zapisuje {ph1} w folderze Pobrane użytkownika. Kolumny są {ph2} oraz {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Od przycisku Do pisarza plików" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3069,7 +3077,7 @@ msgstr "" "Analiza statyczna REA łączy wiadomość z jej obsługą. Miejsce docelowe jest " "odczytywane z kodu." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3081,18 +3089,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}Zobacz pełny ślad kodu i zapisany wynik REA{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Sprawdź prognozę" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3101,19 +3109,19 @@ msgstr "" "Przecinek oddziela kolumny CSV. Co się stanie, gdy sam tytuł notatki zawiera" " przecinek lub cudzysłów?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Sprawdź sam" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Otwórz terminal w rozpakowanym {ph0} folder:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3123,17 +3131,17 @@ msgstr "" "zsh. Twój agent może uruchomić ten sam JavaScript w powłoce Twojej " "platformy." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Zadaj kolejne pytanie" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Spróbuj kontynuować tę samą rozmowę:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3142,7 +3150,7 @@ msgstr "" "Co się stanie, jeśli pliku nie można zapisać? Postępuj zgodnie z błędem z " "powrotem do strony." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3155,7 +3163,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3169,7 +3177,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3183,7 +3191,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3208,114 +3216,114 @@ msgstr "" "zapytaj, gdzie są eksportowane notatki, i sprawdź formatowanie CSV z " "przykładowym tytułem." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Twoje pierwsze badanie REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Skopiuj monit instalacji REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Skopiuj polecenie konfiguracji" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Skopiuj uwagi dochodzenie prompt" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Skopiuj CSV sprawdź monit" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Skopiuj polecenie sprawdzania formatowania" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Przejdź do treści" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Spis treści{ph1} / Zacznij" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Skonfiguruj REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "" "Połącz REA z agentem kodującym lub sprawdź lokalną aplikację z terminala." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Otwórz terminal i sprawdź:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminal" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Kopiuj" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3328,7 +3336,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3339,17 +3347,17 @@ msgstr "" " tym systemie\"{ph1} kiedy biegniesz {ph2}, uruchom to raz i spróbuj " "ponownie:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Jeśli używasz Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "W przeciwnym razie:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Zamknij Terminal, otwórz go ponownie, a następnie:" @@ -3357,7 +3365,7 @@ msgstr "Zamknij Terminal, otwórz go ponownie, a następnie:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3369,7 +3377,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3381,7 +3389,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3390,14 +3398,14 @@ msgid "" msgstr "" "Wolisz zwykłego instalatora? Pobierz wersję LTS z {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Opcje konfiguracji" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3405,7 +3413,7 @@ msgstr "{ph0}Podłącz swojego agenta kodującego{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3413,7 +3421,7 @@ msgstr "{ph0}Użyj CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3421,18 +3429,18 @@ msgstr "{ph0}Skonfiguruj analizę programów kodu maszynowego{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Uzyskiwanie pomocy{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Podłącz swojego agenta kodującego" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3443,12 +3451,12 @@ msgstr "" "obejmują Claude Code , Codex , Cursor , Gemini CLI , Windsurf , Grok Build i" " innych obsługiwanych klientów MCP. Złącze Grok Bot jest dodawane z czatu." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Nowy w agentach kodujących?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3459,7 +3467,7 @@ msgstr "" "karcie przeglądarki. Może odczytywać pliki i uruchamiać polecenia, a przed " "wprowadzeniem zmian pyta. REA daje narzędzia inżynierii odwrotnej." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3471,7 +3479,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3484,7 +3492,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3497,7 +3505,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3507,7 +3515,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}, open source. Połącz wybranego dostawcę " "modelu." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3524,18 +3532,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Lub uruchom samodzielnie konfigurację" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Jak otworzyć terminal?" @@ -3544,7 +3552,7 @@ msgstr "Jak otworzyć terminal?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3560,7 +3568,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3574,7 +3582,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3589,7 +3597,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3599,7 +3607,7 @@ msgstr "" "Wklej polecenie za pomocą {ph0} {ph1} (macOS : {ph2} {ph3}; Terminale Linux:" " {ph4} {ph5} {ph6}), a następnie naciśnij Enter." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3610,12 +3618,12 @@ msgstr "" "połączenie MCP i umiejętność badania dopasowania, zachowując kopię zapasową " "istniejącej konfiguracji. Pyta przed zastosowaniem zmian." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Uruchom ponownie Klienta po zakończeniu konfiguracji." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Jak zrestartować klienta?" @@ -3624,7 +3632,7 @@ msgstr "Jak zrestartować klienta?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3640,7 +3648,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3650,7 +3658,7 @@ msgstr "" "{ph0}Agenci terminalowi{ph1} (Claude Code , Codex , Gemini CLI ): Zamknij " "sesję i uruchom ją ponownie." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3660,7 +3668,7 @@ msgstr "" "aplikacji JavaScript lub Electron możesz zacząć od:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3670,12 +3678,12 @@ msgstr "" "# Patrz {ph0} i dowiedz się, jak eksportuje dane. Pokaż punkty wejścia, " "połączenia i zależności, z lokalizacjami źródłowymi dla swoich ustaleń." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Zastąp ścieżkę lokalnym celem." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Jak uzyskać pełną ścieżkę folderu?" @@ -3684,7 +3692,7 @@ msgstr "Jak uzyskać pełną ścieżkę folderu?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3699,7 +3707,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3711,7 +3719,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3721,17 +3729,17 @@ msgstr "" "{ph0}Dowolny system:{ph1} przeciągnij folder do okna terminala, a pojawi się" " jego ścieżka." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "W terminalu umieść cudzysłowy wokół ścieżki zawierającej spacje." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Użyj CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3740,14 +3748,14 @@ msgstr "" "Analizuj folder aplikacji JavaScript lub Electron lub archiwum ASAR bez " "uruchamiania aplikacji:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Statyczna analiza aplikacji" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3757,13 +3765,13 @@ msgstr "" "Zastąp ścieżkę wyodrębnionym katalogiem aplikacji lub {ph0} akta. Na Windows" " ścieżka taka jak {ph1} działa tutaj." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Gdzie znajdę aplikację .plik asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3774,7 +3782,7 @@ msgstr "Aplikacje Electron zwykle przechowują go w {ph0} folder:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3786,7 +3794,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3799,14 +3807,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} często {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3814,7 +3822,7 @@ msgstr "" "Niektóre aplikacje instalują się gdzie indziej. Wyszukaj w folderze " "aplikacji {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3826,32 +3834,32 @@ msgstr "" "wyniku." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Jeśli chcesz mieć stałe {ph0} polecenie w Twojej powłoce:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Zainstaluj CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "" "{ph0}Kontynuuj korzystanie z Przewodnika po aplikacjach JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Skonfiguruj analizę programów kodu maszynowego" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3861,12 +3869,12 @@ msgstr "" " i skonfiguruj jeden poniżej, a następnie podaj REA swój plik wykonywalny " "lub bibliotekę." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Wybierz narzędzie: Ghidra, Hopper lub IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3878,17 +3886,17 @@ msgstr "" "dekompilatora dla architektury hosta. Ustaw ścieżki przed uruchomieniem " "konfiguracji:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Podłącz instalację Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Połączenie Ghidra * macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3899,12 +3907,12 @@ msgstr "" "rejestruje prawidłowe ustawienia dla wybranego klienta. Na Linux arm64 może " "być konieczne oddzielne zbudowanie natywnego dekompilatora Ghidra." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Połącz Ghidra na Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3915,19 +3923,19 @@ msgstr "" "aplikacji x86 i x64 PE oraz bibliotek DLL na stałych lokalnych dyskach NTFS." " Użyj istniejącego Ghidra 12.1.instalacja x i 64-bitowy JDK 21 lub nowszy:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Połączenie Ghidra * Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "" "Zastąp dwie ścieżki instalacjami, a następnie przejrzyj plan konfiguracji." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3936,7 +3944,7 @@ msgstr "" "Podłącz Hopper na macOS lub Linux . Uruchom powyższe polecenie konfiguracji;" " wykrywa istniejącą instalację lub oferuje plan instalacji do zatwierdzenia." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3945,7 +3953,7 @@ msgstr "" "W macOS dokonaj pierwszego uruchomienia Hopper wyboru trybu demonstracyjnego" " lub aktywacji licencji przed analizą nienadzorowaną." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3956,7 +3964,7 @@ msgstr "" " dla dołączonego GUI lub bezgłowej bazy danych. Analiza bezgłowa Linux i " "macOS pozostaje niezweryfikowana." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Podłącz istniejącą rejestrację IDA MCP" @@ -3966,7 +3974,7 @@ msgstr "Podłącz istniejącą rejestrację IDA MCP" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3978,13 +3986,13 @@ msgstr "" " JSON. Istniejący {ph3} obiekt z {ph4} wejście jest również akceptowane. " "Wskaż REA na ten plik przed instalacją:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Połączenie IDA * Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4002,7 +4010,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4014,30 +4022,30 @@ msgstr "" "agenta, obejmują {ph1} w środowisku rejestracji REA i wybierz IDA podczas " "otwierania pliku binarnego." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "" "W przypadku istniejącej konfiguracji Ghidra sprawdź funkcję za pomocą:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Analiza funkcji" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "Wymienić {ph0} z nazwą funkcji lub adresem, który chcesz sprawdzić." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Jak działa analiza sesji programów kodu maszynowego" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4050,7 +4058,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4060,18 +4068,18 @@ msgstr "" "{ph0}Wykonaj analizę przykładu programów kodu maszynowego{ph1} aby zobaczyć," " jak wynik funkcji prowadzi do odzyskanego obliczenia." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Uzyskiwanie pomocy" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Jeśli twój agent nie widzi REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4081,27 +4089,27 @@ msgstr "" "Uruchom ponownie lub podłącz ponownie Klienta po konfiguracji. Sprawdź " "połączenie REA z {ph0}; dla Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Sprawdź jednego klienta" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Jeśli dostawca wymaga uwagi" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Sprawdź dostawcę, którego używasz. Dla Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Sprawdź jednego dostawcę" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "Raport zawiera nieudaną kontrolę i sugerowany następny krok." @@ -4110,7 +4118,7 @@ msgstr "Raport zawiera nieudaną kontrolę i sugerowany następny krok." #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4123,7 +4131,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4137,7 +4145,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4151,7 +4159,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4175,112 +4183,112 @@ msgstr "" "lub Electron z terminala. Konfiguracja, pierwsze pytania i Przewodniki " "natywnego dostawcy." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Kopia Node.js wersja sprawdź" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Skopiuj polecenie instalacji Node.js dla Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Skopiuj polecenie zasady wykonywania programu PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Skopiuj polecenie instalacji Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Skopiuj polecenie instalacji fnm dla macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Skopiuj Node.js 24 polecenia dla macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Skopiuj polecenie instalacji fnm dla Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Skopiuj Node.js 24 polecenia dla Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA przewodnik dla początkujących" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Skopiuj monit instalacji REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Skopiuj polecenie konfiguracji agenta" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Skopiuj polecenie analizy JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Skopiuj polecenie instalacji CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Kopiuj polecenie połączenia z Ghidra dla macOS i Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Skopiuj połączenie Ghidra dla Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Skopiuj połączenie IDA dla Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Skopiuj natywne polecenie analizy funkcji" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Skopiuj polecenie diagnozy klienta" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Kopiuj polecenie diagnozy dostawcy" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -4289,7 +4297,7 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" @@ -4297,13 +4305,13 @@ msgstr "" "{ph0}Spis treści{ph1} / {ph2}Przewodniki{ph3} / Obserwacja przeglądarki" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Zobacz, co się stanie{ph0}po kliknięciu." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4312,14 +4320,14 @@ msgstr "" "Użyj małej aplikacji przeglądarki, aby połączyć akcję, jej żądanie sieciowe " "i JavaScript, który tworzy plik do pobrania." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "W tym przewodniku" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4327,7 +4335,7 @@ msgstr "{ph0}Przykład{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4335,7 +4343,7 @@ msgstr "{ph0}Otwórz przeglądarkę{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4343,7 +4351,7 @@ msgstr "{ph0}Zapytaj swojego agenta{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4351,13 +4359,13 @@ msgstr "{ph0}Przechwytywanie z CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Przeczytaj żądanie i skrypt{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Co się stanie po kliknięciu przycisku Eksportuj?" @@ -4367,7 +4375,7 @@ msgstr "Co się stanie po kliknięciu przycisku Eksportuj?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4379,7 +4387,7 @@ msgstr "" "przycisk. Kliknięcie go ładuje {ph4}, formatuje dwie notatki jako CSV i " "rozpoczyna pobieranie." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Od kliknięcia do pobrania CSV" @@ -4390,7 +4398,7 @@ msgstr "Od kliknięcia do pobrania CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4406,7 +4414,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4424,7 +4432,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4434,17 +4442,17 @@ msgstr "" "{ph0}03 * Twój agent{ph1}{ph2}Przeczytaj kod eksportu{ph3}{ph4}Połącz " "obserwowane żądanie z {ph5} w {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Rozpocznij przechwytywanie przed kliknięciem Eksportuj notatki." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Otwórz Chrome ze zdalnym debugowaniem" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4453,21 +4461,21 @@ msgstr "" "Otwórz przykład hostowanych notatek za pomocą oddzielnego profilu " "przeglądarki i lokalnego portu debugowania. Na Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Uruchom przykładową przeglądarkę" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Kopiuj" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4476,7 +4484,7 @@ msgstr "" "Użyj ścieżki wykonywalnej zainstalowanej przeglądarki na macOS lub Windows ." " Możesz zastąpić adres URL strony inną stroną, którą chcesz sprawdzić." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4485,7 +4493,7 @@ msgstr "" "REA łączy się z tą istniejącą przeglądarką. Zachowujesz kontrolę nad stroną," " wykonujesz akcję i zamykasz przeglądarkę po zakończeniu." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Poproś swojego agenta, aby obejrzał jedną akcję" @@ -4498,7 +4506,7 @@ msgstr "Poproś swojego agenta, aby obejrzał jedną akcję" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4510,7 +4518,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4521,7 +4529,7 @@ msgstr "" "notatki. Jakie jest żądanie i jak zbudowany jest CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4531,7 +4539,7 @@ msgstr "" "Przykładowy monit. Daj swojemu agentowi punkt końcowy debugowania, {ph0}, " "oraz adres URL strony. Pozwól mu rozpocząć przechwytywanie, zanim klikniesz." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4541,23 +4549,23 @@ msgstr "" "Twój agent odkrywa cel strony, uruchamia okno obserwacji i odczytuje " "wynikowe dowody. Następnie może sprawdzić skrypt za eksportem." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Lub przechwytywanie z terminala" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Znajdź identyfikator docelowy strony:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Znajdź stronę" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4567,14 +4575,14 @@ msgstr "" "Wybierz cel z przykładowym adresem URL notatek. Wymienić {ph0} poniżej z " "jego ID, a następnie uruchom:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Uchwyć następne dziesięć sekund" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4585,7 +4593,7 @@ msgstr "" "{ph0}Eksportuj notatki{ph1} w tej przeglądarce. Wynik pojawia się po " "zakończeniu okna obserwacji." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4596,49 +4604,49 @@ msgstr "" "oraz kształt odpowiedzi JSON. Wcześniejsze żądania są poza tym " "przechwytywaniem." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Przeczytaj skrypt żądania i eksportu" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Nagrany z REA 4.1.0 na przykładzie notatek lokalnych" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Uchwycony fakt" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Wartość" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Prośba" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Odpowiedź" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Inicjator żądania" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * skrypt" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Struktura odpowiedzi" @@ -4646,19 +4654,19 @@ msgstr "Struktura odpowiedzi" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} z {ph1} oraz {ph2} pola" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Przeczytaj załadowane Skrypty" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4669,7 +4677,7 @@ msgstr "" "Przeczytaj przechwycone źródło skryptu, aby zobaczyć, jak dane są używane:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4682,7 +4690,7 @@ msgstr "" "kliknięcie jest wymagane {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4694,7 +4702,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4719,65 +4727,65 @@ msgstr "" "przechwyć kliknięcie, sprawdź żądanie i postępuj zgodnie ze skryptem " "eksportu." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Obserwacja przeglądarki" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Skopiuj Uruchom przykładową przeglądarkę" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Skopiuj przykładowy monit" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Kopiuj znajdź stronę" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Kopiuj przechwyć następne dziesięć sekund" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Kopiuj przeczytaj załadowane Skrypty" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Przejdź do treści" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Spis treści{ph1} / Przewodniki" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Przewodniki REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4786,37 +4794,37 @@ msgstr "" "Analizuj natywną funkcję, eksport Electron lub żądanie przeglądarki. Każdy " "przewodnik zawiera monit, kod i wyniki." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Pierwsze dochodzenie" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Skonfiguruj REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Podłącz agenta kodującego lub użyj REA z terminala." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Zacznij korzystać z REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Programy do kodu maszynowego" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Odzyskaj obliczenie lewej / prawej pozycji dźwięku" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4825,22 +4833,22 @@ msgstr "" "Zacznij od pliku wykonywalnego gry Windows. Sprawdź instrukcje, postępuj " "zgodnie z rozmówcą, przeczytaj stałe numeryczne i sprawdź odzyskane C." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Analiza programów kodu maszynowego przewodnik" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Śledź eksport CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4850,14 +4858,14 @@ msgstr "" "preload i głównym procesie. Użyj REA, aby połączyć API, kanał IPC i pisarz " "plików." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript & Electron przewodnik" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4865,17 +4873,17 @@ msgstr "" "Aby uzyskać większą spakowaną aplikację, postępuj zgodnie z {ph0} Notion ' s" " clipboard bridge{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Zachowanie przeglądarki" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Obserwuj kliknięcie" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4884,7 +4892,7 @@ msgstr "" "Otwórz przykład notatek roboczych, przechwyć żądanie eksportu i znajdź kod, " "który zamienia jego odpowiedź w pobieranie." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Przewodnik obserwacji przeglądarki" @@ -4903,12 +4911,12 @@ msgstr "" "Naucz się REA poprzez krótkie przykłady: natywne obliczenia, eksport " "Electron CSV i żądanie przeglądarki." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -4917,20 +4925,20 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Spis treści{ph1} / {ph2}Przewodniki{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Śledzenie Electron {ph0} Eksport CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4938,14 +4946,14 @@ msgid "" msgstr "" "Kliknij przycisk od strony API, przez Electron IPC, do CSV File writer." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "W tym przewodniku" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4953,7 +4961,7 @@ msgstr "{ph0}Przykład{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4961,7 +4969,7 @@ msgstr "{ph0}Zapytaj swojego agenta{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4969,7 +4977,7 @@ msgstr "{ph0}Śledzenie kodu eksportu{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4977,20 +4985,20 @@ msgstr "{ph0}Wypróbuj przykład{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Sprawdź pisarz CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Gdzie idzie \"Eksportuj notatki\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5002,7 +5010,7 @@ msgstr "" "notatki{ph1} wywołuje API na stronie, przechodzi do głównego procesu i " "zapisuje CSV . Zachowanie jest rozłożone na kilka plików." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "Eksport CSV w procesach Electron" @@ -5016,7 +5024,7 @@ msgstr "Eksport CSV w procesach Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5033,7 +5041,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5050,7 +5058,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5063,13 +5071,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} formatuje notatki → {ph1} pisze {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5080,14 +5088,14 @@ msgstr "" "odsłonięty interfejs API. Ścieżka jest wywnioskowana z kodu; przechwytywanie" " środowiska wykonawczego może sprawdzić, co wykonuje." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Zapytaj o CSV export" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5105,14 +5113,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Kopiuj" @@ -5123,7 +5131,7 @@ msgstr "Kopiuj" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5134,7 +5142,7 @@ msgstr "" "notatki w tej aplikacji. Gdzie jest tworzony CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5144,7 +5152,7 @@ msgstr "" "Przykładowy monit. Dołącz bezwzględną ścieżkę do folderu aplikacji lub " "{ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5155,17 +5163,17 @@ msgstr "" "granic procesów. Twój agent używa tej mapy, aby zawęzić dochodzenie do " "funkcji eksportu." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Śledzenie kodu eksportu" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Strona wywołuje mały interfejs API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5176,7 +5184,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5188,7 +5196,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5198,7 +5206,7 @@ msgstr "" "Czytanie obsługi odpowiada na pierwotne pytanie: {ph0} formatuje notatki, a " "główny proces zapisuje {ph1} do folderu Pobrane użytkownika." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5207,7 +5215,7 @@ msgstr "" "Nagrane przez REA 4.1.0 na poniższym przykładzie do pobrania. Lokalizacje " "źródłowe towarzyszą ustaleniom API, kanału i obsługi." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Przeanalizuj sam przykład" @@ -5215,25 +5223,25 @@ msgstr "Przeanalizuj sam przykład" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Pobierz przykład ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Przeglądaj sześć plików źródłowych" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Statyczna analiza aplikacji" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5244,7 +5252,7 @@ msgstr "" "jeden pasujący program obsługi w {ph0}. Lokalizacje źródłowe znajdują się w " "{ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5255,13 +5263,13 @@ msgstr "" "lub ścieżką ASAR. Agent może śledzić dosłowny ciąg znaków, nazwę API lub " "kanał IPC za pomocą narzędzi do śledzenia funkcji REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Sprawdź pisarz CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5271,7 +5279,7 @@ msgstr "" "Follow {ph0} do jego obsługi. Które Dane wejściowe docierają do pisarza CSV " "i co się stanie, jeśli zapisanie pliku nie powiedzie się?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5286,7 +5294,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5300,7 +5308,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5314,7 +5322,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5340,32 +5348,32 @@ msgstr "" "wstępnego i obsługi IPC za pomocą REA . Zawiera pliki przykładowe do " "pobrania i zweryfikowany wynik analizy." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Skopiuj przykładowy monit" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Kopiuj statyczną analizę aplikacji" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -5374,7 +5382,7 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5383,13 +5391,13 @@ msgstr "" "maszynowego" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "Recover DX-Ball{ph0}obliczanie lewej / prawej pozycji dźwięku." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5398,14 +5406,14 @@ msgstr "" "Sprawdź oryginalne instrukcje, zidentyfikuj dane wejściowe i stałe, a " "następnie sprawdź odzyskane C." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "W tym przewodniku" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5413,7 +5421,7 @@ msgstr "{ph0}Przykład{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5421,7 +5429,7 @@ msgstr "{ph0}Zapytaj swojego agenta{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5429,7 +5437,7 @@ msgstr "{ph0}Przeczytaj wyniki REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5437,18 +5445,18 @@ msgstr "{ph0}Odzyskaj i sprawdź{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Użyj własnego pliku binarnego{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Oblicz pozycjonowanie dźwięku stereo w lewo / w prawo" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5459,7 +5467,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5471,7 +5479,7 @@ msgstr "" "REA zwraca również swoje instrukcje i dzwoniące, które dają agentowi sposób " "na zbadanie brakującej arytmetyki." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Nowy w tych warunkach?" @@ -5480,7 +5488,7 @@ msgstr "Nowy w tych warunkach?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5492,7 +5500,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5505,7 +5513,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5518,7 +5526,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5530,7 +5538,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5540,7 +5548,7 @@ msgstr "" "{ph0}Stałe:{ph1} stałe numery przechowywane w programie, odczytywane jako " "surowe bajty i dekodowane." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Trzy dowody, jedna kalkulacja" @@ -5551,7 +5559,7 @@ msgstr "Trzy dowody, jedna kalkulacja" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5568,7 +5576,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5586,7 +5594,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5596,7 +5604,7 @@ msgstr "" "{ph0}03 * bajty danych{ph1}{ph2}Stałe numeryczne{ph3}{ph4}Odsyłane bajty " "dekodują do {ph5}, {ph6} i wartość skali.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5605,7 +5613,7 @@ msgstr "" "REA dostarcza instrukcje, relacji funkcja-wywołanie i bajtów. Agent " "interpretuje je razem." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Zapytaj o zachowanie" @@ -5614,7 +5622,7 @@ msgstr "Zapytaj o zachowanie" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5625,19 +5633,19 @@ msgstr "" "analizy programów kodu maszynowego{ph3}, podaj lokalny plik wykonywalny i " "pytanie:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Jakiego narzędzia analitycznego powinienem użyć?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA potrzebuje jednego z nich do odczytu programów natywnych:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5651,7 +5659,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5664,7 +5672,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5675,7 +5683,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5691,14 +5699,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Kopiuj" @@ -5709,7 +5717,7 @@ msgstr "Kopiuj" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5720,7 +5728,7 @@ msgstr "" "pozycjonowanie dźwięku stereo. Wyjaśnij obliczenia i pokaż " "kod.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5732,7 +5740,7 @@ msgstr "" "kopii lub zadaj to samo pytanie dotyczące innego małego programu Windows, " "który masz." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Jak uzyskać pełną ścieżkę pliku?" @@ -5741,7 +5749,7 @@ msgstr "Jak uzyskać pełną ścieżkę pliku?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5756,7 +5764,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5768,7 +5776,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5778,17 +5786,17 @@ msgstr "" "{ph0}Dowolny system:{ph1} przeciągnij plik do okna terminala, a pojawi się " "jego ścieżka." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Przeczytaj wyniki REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Przeczytaj dane wejściowe" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5798,13 +5806,13 @@ msgstr "" "zmiennoprzecinkową. Jest to dane wejściowe nieobecne w pierwszym widoku " "pseudokodu." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Podążaj za dzwoniącym" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5815,12 +5823,12 @@ msgstr "" "współrzędną płytki przez 30; dodawanie {ph0} (20) podaje położenie ekranu " "Cegły." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Przeczytaj przywoływane stałe" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5830,12 +5838,12 @@ msgstr "" "rzeczywistych wartości; kolejność instrukcji informuje agenta, w jaki sposób" " są używane." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Napisz i sprawdź odzyskaną funkcję" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5846,7 +5854,7 @@ msgstr "" "konwersją liczb całkowitych. Obliczenia umieszczają środek ekranu na środku " "pola stereo." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5859,20 +5867,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Zobacz pełne porównanie badań i montażu do C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Spróbuj z własnym binarnym" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5886,7 +5894,7 @@ msgstr "" "Przydatne pytania początkowe obejmują \"Jak jest analizowany ten " "plik?\"lub\" która funkcja obsługuje tę akcję menu?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5895,13 +5903,13 @@ msgstr "" "Jeśli znasz już nazwę lub adres funkcji, możesz wysłać zapytanie z " "terminala. Dla skonfigurowanej instalacji Ghidra:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Analiza funkcji" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5915,7 +5923,7 @@ msgstr "" "sesję. Zapytania MCP twojego agenta ponownie wykorzystują zaimportowany plik" " binarny, gdy ta sesja jest otwarta." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5939,50 +5947,50 @@ msgstr "" "Odzyskaj natywne obliczenia za pomocą REA: sprawdź instrukcje, podążaj za " "dzwoniącym, przeczytaj stałe i sprawdź zrekonstruowane C." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Analiza programów kodu maszynowego" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Skopiuj przykładowy monit" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Analiza funkcji kopiowania" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Przejdź do treści" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Skonfiguruj REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5990,7 +5998,7 @@ msgstr "{ph0}Skonfiguruj REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5998,7 +6006,7 @@ msgstr "{ph0}Co to jest RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6006,7 +6014,7 @@ msgstr "{ph0}Jak pomaga REA{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6014,7 +6022,7 @@ msgstr "{ph0}Dinozaur gry{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6022,7 +6030,7 @@ msgstr "{ph0}Kalkulator{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6030,7 +6038,7 @@ msgstr "{ph0}Spróbuj REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6038,7 +6046,7 @@ msgstr "{ph0}Dowiedz się więcej{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6046,25 +6054,25 @@ msgstr "{ph0}Pomoc i opinie{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Społeczność{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Inżynieria odwrotna z twoim agentem kodującym" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Dowiedz się,{ph0}jak działa oprogramowanie." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6075,7 +6083,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6083,13 +6091,13 @@ msgstr "Znasz już RE? {ph0}Przejdź do poradników analizy →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Chcesz wejść głębiej? {ph0}Czytaj Blog →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Wklej to polecenie do swojego agenta programistycznego:" @@ -6102,38 +6110,38 @@ msgstr "Wklej to polecenie do swojego agenta programistycznego:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Kopiuj" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Albo uruchom to polecenie w terminalu:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Sprawdź i zatwierdź plan zmian, a następnie uruchom agenta ponownie." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Czym jest inżynieria wsteczna?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6148,7 +6156,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6160,7 +6168,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6168,7 +6176,7 @@ msgstr "Przed REA · Badasz program {ph0}samodzielnie{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6176,7 +6184,7 @@ msgstr "{ph0}01{ph1} Dekoduj gałęzie" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6184,7 +6192,7 @@ msgstr "{ph0}02{ph1} Śledzenie połączeń" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6194,20 +6202,20 @@ msgstr "{ph0}03{ph1} Odzyskaj regułę" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Oryginalny x64 * wybrane instrukcje{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * która gałąź?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6216,29 +6224,29 @@ msgid "" msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Dwa skoki w to samo miejsce. Którzy to operatorzy?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Wyszukaj identyfikatory poleceń, a następnie oznacz gałąź." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Podziel ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Mnożenie ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Co robią wywoływane funkcje?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6248,24 +6256,24 @@ msgstr "" "\"100 jest jasne. Rozmowy to tylko adresy. {ph0}Który dzieli? Która wartość " "wchodzi?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Sprawdź funkcje pomocnicze i prześledź zapisane wartości." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Divide" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * Jaka jest reguła?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6275,19 +6283,19 @@ msgstr "" "\"Ta ścieżka mnoży się przez inne dane wejściowe. Więc {ph0}10% oznacza 10% " "z 200{ph1} po +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Nazwij operandy i sprawdź obie ścieżki operatora." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Ilustrujące rozumowanie eksperta" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6299,20 +6307,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Z REA · Pytasz {ph0}swojego agenta{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Wystarczy jedno polecenie." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6326,50 +6334,50 @@ msgstr "Zadaj agentowi pytanie {ph0}zwykłymi słowami.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Przykładowy monit * Kalkulator" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Przykładowa odpowiedź · na podstawie ustaleń" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "Po +, przycisk % trwa {ph0}procent pierwszej liczby.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA dostarcza" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Instrukcje obsługi, zdekompilowany kod i połączenia." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Twój agent wyjaśnia" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Która gałąź ma zastosowanie, co oblicza i jak ją odbudować." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6381,7 +6389,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6391,37 +6399,37 @@ msgstr "" "{ph0}Spróbujmy dwóch przykładów.{ph1} Zmień szybkość gry, a następnie wróć " "do kalkulatora i odbuduj przycisk%." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Przykład 01 * gra dinozaurów Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Dlaczego dinozaur przyspiesza?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Gol" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Odbuduj grę za pomocą {ph0}regulowana prędkość.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Dlaczego reverse engineer it?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6432,49 +6440,49 @@ msgstr "" "biegowej{ph1}: jak szybko się zaczyna, jak bardzo się zwiększa i kiedy się " "zatrzymuje." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Zagraj w odtworzoną wersję" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Graj" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Skok ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Zacznij od nowa" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Prędkość" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Użyj reguły odzyskiwania przyspieszenia" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Pierwotna zasada: zacznij od 6, a następnie zwiększ do 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Przesuń suwak, aby ustawić własną prędkość. Przestrzeń lub skok usuwa " "kaktusa." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6483,14 +6491,14 @@ msgstr "" "Włącz JavaScript, aby odtworzyć rekonstrukcję. Powyższy kod i Wyjaśnienie " "pozostają czytelne." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA zwróciło" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6509,7 +6517,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6522,7 +6530,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6536,7 +6544,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6549,7 +6557,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6559,12 +6567,12 @@ msgstr "" "{ph0}Zacznij od 6.{ph1} Dodaj {ph2}0.001{ph3} każda aktualizacja bez " "kolizji, podczas gdy prędkość jest poniżej {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Otwórz speed lab" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Co robi każda część" @@ -6575,7 +6583,7 @@ msgstr "Co robi każda część" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6591,7 +6599,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6607,7 +6615,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6617,13 +6625,13 @@ msgstr "" "{ph0}03 * Ty{ph1}{ph2}Zmień prędkość i graj{ph3}{ph4}Wypróbuj oryginalne " "przyspieszenie, a następnie wybierz własne tempo.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Zobacz skrypt, kontrole i jak wypróbować analizę" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6633,7 +6641,7 @@ msgstr "" "REA sprawdził wersję przeglądarki HTTP poprzez lokalne połączenie " "debugowania i zwrócił załadowany {ph0}, w tym jego źródło i trawienie." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6647,7 +6655,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6663,7 +6671,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6681,7 +6689,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6690,19 +6698,19 @@ msgstr "" "{ph0}Sprawdzony kod prędkości{ph1} · {ph2} Chromium autorzy * licencja " "BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Przykład 02 * Kalkulator Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Odtwórz przycisk % kalkulatora." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6713,7 +6721,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6724,29 +6732,29 @@ msgstr "" "zainstalowaną aplikację, aby dowiedzieć się, do której liczby zastosowany " "jest procent." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Wypróbuj obliczenia" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Resetuj" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% z 200 = 20. Następnie 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Interaktywna ilustracja kontrolowanej reguły procentowej." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6758,7 +6766,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6772,7 +6780,7 @@ msgstr "Dla tego przykładu, {ph0} oraz {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6788,7 +6796,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6800,7 +6808,7 @@ msgstr "" "Odzyskaj reguły po + I×, a następnie zbuduj mały kalkulator, który używa " "obu.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Z +" @@ -6808,13 +6816,13 @@ msgstr "Z +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Weź 10% pierwszej liczby.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Z ×" @@ -6822,13 +6830,13 @@ msgstr "Z ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Zamień 10% na 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Z zainstalowanej aplikacji do działającego przycisku %" @@ -6840,7 +6848,7 @@ msgstr "Z zainstalowanej aplikacji do działającego przycisku %" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6857,7 +6865,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6869,12 +6877,12 @@ msgstr "" "ZASADY{ph3}{ph4}Sprawdź gałąź za pomocą źródła Microsoft, a następnie " "wypróbuj + i × powyżej.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Zobacz prawdziwy kod i sposób sprawdzenia odpowiedzi" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6895,7 +6903,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6905,17 +6913,17 @@ msgstr "" "{ph0}Procentowa realizacja{ph1} · {ph2}Przypadki testowe Microsoftu{ph3} · " "{ph4}Natywny Przewodnik konfiguracji{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Twoje pierwsze śledztwo" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Wypróbuj REA w małej aplikacji." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6924,12 +6932,12 @@ msgstr "" "Pobierz nasz przykład notatek, prześledź eksport CSV i sprawdź jedno " "zmienione wejście." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Wypróbuj przykład z przewodnikiem" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Chcesz dowiedzieć się więcej?" @@ -6938,7 +6946,7 @@ msgstr "Chcesz dowiedzieć się więcej?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6958,7 +6966,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" @@ -6966,7 +6974,7 @@ msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Przykładowy monit * strona " "internetowa" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Tak, ten." @@ -6979,7 +6987,7 @@ msgstr "Tak, ten." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6994,7 +7002,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7008,23 +7016,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Zobacz studium przypadku DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Aby wykonać kroki konfiguracji i analizy, wybierz cel:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Programy do kodu maszynowego" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7033,17 +7041,17 @@ msgstr "" "Sprawdzaj funkcje, ciągi znaków, odwołania i relacje wywołania funkcji w " "plikach wykonywalnych i bibliotekach." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Analiza programów kodu maszynowego przewodnik" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7052,17 +7060,17 @@ msgstr "" "Mapuj Moduły, trasy, IPC i natywne zależności z folderu aplikacji lub " "archiwum ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Przepływy pracy aplikacji" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Aktywność przeglądarki i środowiska wykonawczego" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7071,12 +7079,12 @@ msgstr "" "Przechwyć wybraną aktywność przeglądarki lub procesu, a następnie porównaj " "wyniki w różnych przebiegach." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Przewodnik obserwacji przeglądarki" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Masz pytania?" @@ -7087,7 +7095,7 @@ msgstr "Masz pytania?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7097,12 +7105,12 @@ msgstr "" "{ph0}Przeczytaj FAQ{ph1}, {ph2}porozmawiaj z nami na Discord {ph3}, lub " "{ph4}otwórz problem GitHub{ph5} dla błędów i żądań funkcji." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Dołącz do społeczności" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7126,27 +7134,27 @@ msgstr "" "agentem kodującym. Postępuj zgodnie z przejrzystymi przewodnikami i wypróbuj" " interaktywne przykłady z REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Skopiuj monit instalacji REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Skopiuj polecenie konfiguracji" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Postępuj zgodnie z ręczną analizą kalkulatora" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Kopiuj Kalkulator Procent pytanie" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7155,37 +7163,37 @@ msgstr "" "Dinozaur mini-gry. Użyj przycisku skoku lub naciśnij spację, gdy gra jest " "skupiona." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Skopiuj monit o analizę dinozaurów" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Wybierz obliczenia" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Kopiuj monit o analizę kalkulatora" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Skopiuj monit projektu witryny" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Skopiuj monit o rekonstrukcję gry" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -7194,25 +7202,25 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Spis treści{ph1} / {ph2}Gabloty{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Case study * Aegis Authenticator" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Jak działa authenticator{ph0}wygenerować kod logowania?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7222,17 +7230,17 @@ msgstr "" "obliczenia w Android APK, a następnie odbudować go z zegarem można " "kontrolować." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * oficjalne wydanie APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Zobacz Aegis na GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Od APK do kodu, który możesz odtworzyć" @@ -7243,7 +7251,7 @@ msgstr "Od APK do kodu, który możesz odtworzyć" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7261,7 +7269,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7279,7 +7287,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7291,14 +7299,14 @@ msgstr "" "kod.{ph3}{ph4}Nowa wersja demonstracyjna przeglądarki odtwarza regułę i " "sprawdza ją w publicznych przypadkach referencyjnych.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "W tym studium przypadku" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7306,7 +7314,7 @@ msgstr "{ph0}Zapytaj swojego agenta{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7314,7 +7322,7 @@ msgstr "{ph0}Wypróbuj generator kodu{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7322,7 +7330,7 @@ msgstr "{ph0}Znajdź kod za pomocą REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7330,7 +7338,7 @@ msgstr "{ph0}Przeczytaj obliczenia{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7338,20 +7346,20 @@ msgstr "{ph0}Sprawdź rekonstrukcję{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Sprawdź sam APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Zapytaj swojego agenta" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7369,21 +7377,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Kopiuj" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7393,14 +7401,14 @@ msgstr "" "Przykładowy monit dla pobranego APK, ze skonfigurowaną analizą Androida REA." " {ph0}Pobierz APK i konfiguracji analizy ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Wypróbuj generator kodu" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7411,33 +7419,33 @@ msgstr "" "Aplikacja grupuje czas w {ph0}30-sekundowe bloki.{ph1} Łączy numer bloku z " "kluczem konta, aby wygenerować kod. Ten sam klucz i blok tworzą ten sam kod." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Przesuń zegar na 60 sekund" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Czas" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "sekund" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Nasz regulowany przykładowy zegar" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30-sekundowy blok" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Blok" @@ -7446,35 +7454,35 @@ msgstr "Blok" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 sekund{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Wygenerowany kod" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Klucz konta + blok → sześć cyfr" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Przykładowy czas, w sekundach" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 sekund" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 sekund" @@ -7483,7 +7491,7 @@ msgstr "60 sekund" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7495,7 +7503,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7505,7 +7513,7 @@ msgstr "" "Klucz jest stały, publiczny {ph0}Dane testowe RFC 6238{ph1}. Demo " "implementuje obliczenia odzyskane z APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7513,18 +7521,18 @@ msgid "" msgstr "" "Diagram pokazuje wynik po 59 sekundach. Włącz JavaScript, aby zmienić zegar." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Znajdź kod za pomocą REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Zawęź APK do trzech klas" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7534,14 +7542,14 @@ msgstr "" "{ph0} jest kandydatem do obliczeń; pozostałe dwa dotyczą paska postępu i " "zaimportowanych kont. TOTP oznacza hasło jednorazowe oparte na czasie." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Podłącz generator do wyświetlacza aplikacji" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7552,7 +7560,7 @@ msgstr "" " bazowej. Kontrola {ph0} następnie pokazuje wywołanie wyświetlacza {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7562,14 +7570,14 @@ msgstr "" "Żądania pokazują skróconą ścieżkę wejściową. Nazwy klas wynikowych pomijają " "wspólne {ph0} prefiks." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Przeczytaj obliczenia" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7583,7 +7591,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7591,7 +7599,7 @@ msgstr "{ph0}01{ph1} Blok czasu" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7599,7 +7607,7 @@ msgstr "{ph0}02{ph1} Klucz + blok" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7607,7 +7615,7 @@ msgstr "{ph0}03{ph1} Sześć cyfr" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7619,7 +7627,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7632,7 +7640,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7646,7 +7654,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7657,7 +7665,7 @@ msgstr "" "Prawy panel jest podsumowaniem wyjaśniającym. {ph0} Kod Aegis to " "GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Wewnątrz generatora" @@ -7666,7 +7674,7 @@ msgstr "Wewnątrz generatora" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7676,7 +7684,7 @@ msgstr "" "Wydany APK stawia {ph0} w {ph1}. REA podąża za wywołaniem z {ph2} i zwraca " "to ciało; oryginalne źródło wywołuje pomocnika {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7693,20 +7701,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Porównaj z pasującym źródłem wydania{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Sprawdź rekonstrukcję" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7718,29 +7726,29 @@ msgstr "" "dorobek odpowiadał niezależnej rekonstrukcji na {ph0}133 przypadki " "testowe{ph1}, w tym granice bloków czasowych i kody zaczynające się od zera." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Przykładowy czas" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Kod sześciocyfrowy" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 sekund" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 sekund" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7751,17 +7759,17 @@ msgstr "" " SHA-1 w {ph0}RFC 6238{ph1}. Sprawdź implementację przeglądarki przeciwko " "nim:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Uruchom kontrole referencyjne" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Przeczytaj obliczenia demo" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7770,7 +7778,7 @@ msgstr "" "Przypadki referencyjne używają ośmiu cyfr. Kontrola weryfikuje również ich " "sześciocyfrowe wyniki." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7779,14 +7787,14 @@ msgstr "" "Weryfikacja uruchamia wyodrębnione metody Java i nowe demo. Android APK " "został sprawdzony statycznie." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Sprawdź sam APK" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7798,7 +7806,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7808,18 +7816,18 @@ msgstr "" "Analiza Androida wymaga pełnego JDK 17 lub nowszego. Wybierz go za pomocą " "{ph0} lub {ph1}. W tym przypadku zastosowano JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Wskaż REA w pliku dostawcy i sprawdź APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7831,7 +7839,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7841,7 +7849,7 @@ msgstr "" "Następne pytanie: {ph0}co się dzieje, gdy konto używa ośmiu cyfr lub innego " "przedziału czasu?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Źródła" @@ -7857,7 +7865,7 @@ msgstr "Źródła" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7871,7 +7879,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" @@ -7879,7 +7887,7 @@ msgstr "" "{ph0}RFC 6238 przypadki referencyjne{ph1} · {ph2}Dane z testów " "demonstracyjnych{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7904,37 +7912,37 @@ msgstr "" "Sprawdź Aegis Android APK za pomocą REA, Odzyskaj jego sześciocyfrowe " "obliczenie kodu logowania i wypróbuj rekonstrukcję z regulowanym zegarem." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK case study" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Skopiuj przykładowy monit Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Postępuj zgodnie z obliczeniem kodu logowania" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Skopiuj polecenie kontroli APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -7943,26 +7951,26 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Spis treści{ph1} / {ph2}Gabloty{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Studium przypadku * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Znajdź flagę w{ph0}binarny CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7973,17 +7981,17 @@ msgstr "" "równania i znaleźć Dane wejściowe, które sprawiają, że oryginalny program " "drukuje {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "maskowane kwadraty FLAG checker * Easy * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Zobacz oryginalne wyzwanie" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Od binarnej do sprawdzonej odpowiedzi" @@ -7994,7 +8002,7 @@ msgstr "Od binarnej do sprawdzonej odpowiedzi" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8012,7 +8020,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8029,7 +8037,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8041,7 +8049,7 @@ msgstr "" "poprawna!{ph3}{ph4}Skrypt Pythona rozwiązuje równania. REA przechwytuje " "oryginalny program akceptujący wynik.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." @@ -8049,14 +8057,14 @@ msgstr "" "Wyzwanie jest autorstwa Josepha, opublikowane w oficjalnym repozytorium " "DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "W tym studium przypadku" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8064,7 +8072,7 @@ msgstr "{ph0}Znajdź kod kontrolny{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8072,7 +8080,7 @@ msgstr "{ph0}Przeczytaj jedną maskę{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8080,7 +8088,7 @@ msgstr "{ph0}Montaż do czytelnego kodu{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8088,7 +8096,7 @@ msgstr "{ph0}Rozwiąż równania{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8096,20 +8104,20 @@ msgstr "{ph0}Sprawdź odpowiedź{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Spróbuj sam{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Znajdź kod kontrolny" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8128,17 +8136,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Kopiuj" @@ -8149,7 +8157,7 @@ msgstr "Kopiuj" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8161,7 +8169,7 @@ msgstr "" "flagę. Wyjaśnij, jak działają kontrole, a następnie zweryfikuj odpowiedź za " "pomocą oryginalnego programu.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8170,12 +8178,12 @@ msgstr "" "Przykładowy monit z pobranym wyzwaniem dostępnym lokalnie i analizą " "podłączonego dostawcy programów kodu maszynowego." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Postępuj zgodnie z monitem wejściowym do jego funkcji" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8184,14 +8192,14 @@ msgstr "" "Odwołanie daje agentowi miejsce do zbadania, mimo że oryginalne nazwy " "funkcji pliku wykonywalnego zostały usunięte." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Przeczytaj kontroler i jego dwóch pomocników" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8203,7 +8211,7 @@ msgstr "" "sumuje wybrane kody i porównuje wynik z zapisaną liczbą. Jego {ph0}- bajtowe" " kroki w poprzek {ph1} bajty dają 26 masek." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8212,12 +8220,12 @@ msgstr "" "Są to wybrane wyniki ze świeżej analizy REA. Lokalna ścieżka docelowa jest " "skrócona do wyświetlania; adresy odnoszą się do importowanego obrazu REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Jeden czek ujawnia jedną postać" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8230,13 +8238,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "Siódmy czek wybiera tylko jedną pozycję. {ph0}Otwórz rysunek{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Odczytaj maskę i jej cel z pliku binarnego" @@ -8245,7 +8253,7 @@ msgstr "Odczytaj maskę i jej cel z pliku binarnego" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8257,12 +8265,12 @@ msgstr "" "dlatego {ph1} oznacza -21. Celem jest liczba całkowita little-endian. Razem " "te bajty mówią agentowi, że {ph2}, więc ta postać jest {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Od instrukcji do czytelnego czeku" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8273,7 +8281,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8281,7 +8289,7 @@ msgstr "{ph0}01{ph1} Start" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8289,7 +8297,7 @@ msgstr "{ph0}02{ph1} Wybierz" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8297,7 +8305,7 @@ msgstr "{ph0}03{ph1} Dodaj" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8305,18 +8313,18 @@ msgstr "{ph0}04{ph1} Advance" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Porównaj" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * wybrane oryginalne instrukcje" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Czytelne podsumowanie C * one-check" @@ -8324,7 +8332,7 @@ msgstr "Czytelne podsumowanie C * one-check" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8332,7 +8340,7 @@ msgstr "{ph0}01 * zacznij od zera · {ph1} {ph2} trzyma bieżącą sumę." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8344,7 +8352,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8356,7 +8364,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8370,7 +8378,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8380,7 +8388,7 @@ msgstr "" "{ph0}05 * Porównaj z zapisanym celem.{ph1} Dzwoniący otrzymuje sumę w {ph2}." " Niedopasowanie skacze do {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8390,12 +8398,12 @@ msgstr "" "podsumowaniem wyjaśniającym z opisowymi nazwami i spłaszczoną pętlą 36 " "komórek." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Rozwiąż 26 równań" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8406,13 +8414,13 @@ msgstr "" "dodaje 16 kodów znaków i wymaga łącznie 1441. Nakładające się zaznaczenia " "dają równania, które mały skrypt Pythona może rozwiązać razem." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * solver fragment" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8426,19 +8434,19 @@ msgstr "" "cyframi, podkreśleniami i nawiasami klamrowymi. Pełne pobieranie obejmuje " "wszystkie 26 masek i celów." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Pobierz kompletny solver" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Sprawdź odpowiedź za pomocą oryginalnego programu" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8450,47 +8458,47 @@ msgstr "" "akceptujący rozwiązaną flagę. Zmiana jednego wybranego znaku z {ph0} do " "{ph1} tworzy pierwszą sumę 1440 zamiast 1441, a program ją odrzuca." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Wejście" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Obserwowane wyjście" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Kod wyjścia" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Flaga solvera" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Jedna postać się zmieniła" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Pokaż odzyskaną flagę i przechwycone dane wyjściowe" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * oryginalne wyjście programu" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Kopiuj flagę" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8500,12 +8508,12 @@ msgstr "" "organizatorów metadanych wyzwania, sprawdzonych po rozwiązaniu pliku " "binarnego." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Źródło, tożsamość docelowa i szczegóły analizy" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8516,7 +8524,7 @@ msgstr "" "r.przy użyciu REA 4.1.0 z Ghidra 12.1.4 na Linux x64. Plik binarny to " "pozbawiony x86-64 ELF, 15 248 bajtów." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8539,7 +8547,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8549,12 +8557,12 @@ msgstr "" "{ph0}Porównaj ze źródłem organizatorów{ph1} · {ph2}Metadane wyzwania i " "flaga{ph3} · {ph4} REA dowody uwagi{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Spróbuj sam" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8563,13 +8571,13 @@ msgstr "" "Pobierz oryginalne wyzwanie i solver do jednego folderu. Użyj powyższego " "monitu, aby zbadać sprawę z agentem lub uruchom dołączony skrypt." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * Rozwiąż i uruchom" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8581,7 +8589,7 @@ msgstr "" "potrzeb Python i {ph0}. Uruchomienie oryginalnego pliku wykonywalnego wymaga" " Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Skonfiguruj REA z agentem kodującym" @@ -8602,27 +8610,27 @@ msgstr "" "DownUnderCTF. Znajdź funkcje sprawdzania, wyodrębnij maski i porównaj " "odzyskaną flagę z oryginalnym programem." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTF flag-checker case study" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Skopiuj przykładowy monit CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "Równanie maski CTF; przewijaj poziomo na mniejszych ekranach" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8633,42 +8641,42 @@ msgstr "" "Tylko ta komórka przyczynia się do sumy. Wymagany kod znaku to 55, co " "oznacza, że znak to 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Postępuj zgodnie z kontrolą CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Kopiuj zespół CTF" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Kopiuj czytelny czek CTF" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Skopiuj fragment CTF solver" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Skopiuj odzyskaną flagę" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Kopiuj polecenia CTF solver" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -8677,25 +8685,25 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Spis treści{ph1} / {ph2}Gabloty{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Studium przypadku * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Przebudowa DX-Ball {ph0}z jego pliku wykonywalnego." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8704,14 +8712,14 @@ msgstr "" "Celem jest utrzymanie wersji C gry Windows z 1996 roku. REA pomaga agentowi" " sprawdzić oryginalną, jedną funkcję na raz." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8723,14 +8731,14 @@ msgstr "" " rozmówców i odczyty danych; projekt rekonstrukcji implementuje i testuje " "wynik. {ph0}Otwórz rysunek{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "W tym studium przypadku" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8738,7 +8746,7 @@ msgstr "{ph0}Projekt{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8746,7 +8754,7 @@ msgstr "{ph0}Sound pan{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8754,23 +8762,23 @@ msgstr "{ph0}Sprawdzanie wyniku{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Kontynuuj pracę{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "utrzymywane funkcje C" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "porównania z oryginalnym kodem" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "funkcje z dopasowanymi skompilowanymi bajtami" @@ -8781,7 +8789,7 @@ msgstr "funkcje z dopasowanymi skompilowanymi bajtami" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8791,12 +8799,12 @@ msgstr "" "Punkt kontrolny projektu: 7 października 2026 r. {ph0}Progress ledger{ph1} ·" " {ph2}Pokrycie testu{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Dotychczasowy projekt" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8810,12 +8818,12 @@ msgstr "" "inspekcyjne i bibliotekę analiz. Prace nad grywalną grą kontynuowane są z " "fizyką piłki i wiosła, obsługą zasilania i integracją Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Znalezienie obliczenia lewej / prawej pozycji dźwięku" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8834,17 +8842,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Kopiuj" @@ -8855,7 +8863,7 @@ msgstr "Kopiuj" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8866,7 +8874,7 @@ msgstr "" "pozycjonowanie dźwięku stereo. Wyjaśnij obliczenia i pokaż " "kod.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8877,7 +8885,7 @@ msgstr "" "wykonywalnym. Poniższe dochodzenie pokazuje zapytania REA i dowody stojące " "za odpowiedzią." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8891,7 +8899,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8905,12 +8913,12 @@ msgstr "" "zmiennoprzecinkowe. Ta rozbieżność dała agentowi konkretny powód do dalszego" " dochodzenia." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "Pierwszy widok dekompilatora" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8919,18 +8927,18 @@ msgstr "" "Wyjście pokazuje wywołanie konwersji. Czytanie poniższych instrukcji ujawnia" " wejście i podawanie obliczeń, które wywołanie." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Trzy pytania odpowiedział przez REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Odzyskaj brakujące dane wejściowe" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8940,14 +8948,14 @@ msgstr "" "Wynik funkcji zawiera instrukcje obok pseudokodu i rozmówców. Tutaj, {ph0} " "ujawnia dane wejściowe całkowite brakujące w widoku dekompilatora." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Postępuj zgodnie z rozmówcą, aby zrozumieć Dane wejściowe" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8957,12 +8965,12 @@ msgstr "" "REA zidentyfikował tego rozmówcę w pierwszym wyniku. Jego poprzednia skala " "instrukcji {ph0} przez 30; dodanie 20 daje współrzędną ekranu Cegły, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Przeczytaj wartości za adresami pamięci" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -8971,12 +8979,12 @@ msgstr "" "Zwracane bajty ustanawiają dwie stałe arytmetyczne i początkową skalę " "przesuwania. Agent ma teraz wartości potrzebne do wyrażenia C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Od ustaleń REA do C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8987,7 +8995,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8995,7 +9003,7 @@ msgstr "{ph0}01{ph1} Wejście" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9003,7 +9011,7 @@ msgstr "{ph0}02{ph1} Pomnóż" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9011,7 +9019,7 @@ msgstr "{ph0}03{ph1} Odejmij" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9019,18 +9027,18 @@ msgstr "{ph0}04{ph1} Skala" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Powrót" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Oryginalny x86 * fragment" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Zrekonstruowany C" @@ -9040,7 +9048,7 @@ msgstr "Zrekonstruowany C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9060,7 +9068,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9076,7 +9084,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9094,7 +9102,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9111,7 +9119,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9123,7 +9131,7 @@ msgstr "" "zidentyfikowane w wynikach callee REA. C rzuca wynik do {ph4}; oryginał-" "porównania x86 sprawdzają zwróconą wartość." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9134,23 +9142,23 @@ msgstr "" " lista poniżej obejmuje również interwencyjne sklepy oraz konfigurację i " "czyszczenie funkcji." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Pełne zgromadzenie i dowody potwierdzające" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "Wynik REA * 0x406400 · 0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Co dostarcza rozmówca" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9160,54 +9168,54 @@ msgstr "" "Funkcja brick-hit w {ph0} skaluje współrzędną płytki o 30, dodaje 20, a " "następnie popycha ją przed wywołaniem:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Co odczytują dane" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "Bajt REA odczytuje, dekoduje jako mało - endian podwaja" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Adres" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Wartość" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Używany do" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Pierwsze mnożenie" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Odejmowanie" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} początkowo" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Przechowywana skala patelni" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9223,7 +9231,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9233,12 +9241,12 @@ msgstr "" "{ph0}Utrzymane źródło{ph1} · {ph2}Notatki z dochodzenia i odniesienia do " "dowodów{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Sprawdzanie odzyskanej funkcji" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9247,12 +9255,12 @@ msgstr "" "Odzyskana Funkcja Przechodzi dwa kontrole: jej wartości zwracane są zgodne z" " oryginałem, a skompilowane bajty są zgodne z plikiem wykonywalnym." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3205 przypadków zachowania" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9263,12 +9271,12 @@ msgstr "" "utrzymanym C. obejmują każdą pozycję całkowitą od 0 do 640 w pięciu skalach " "pan: 0, 0,5, 1, 20 i -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 pasujące bajty" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9279,7 +9287,7 @@ msgstr "" "kompilatora pasuje do pełnej funkcji po zastosowaniu sprawdzonych relokacji " "i sprawdzeniu przywoływanych stałych." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9294,18 +9302,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Przeczytaj szczegóły powtórki kompilatora{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Kontynuuj dochodzenie" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9316,7 +9324,7 @@ msgstr "" "wybuchowych i generowania premii: sprawdź odpowiednie funkcje, Odzyskaj ich " "stan i zależności, a następnie porównaj implementację z oryginałem." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9326,7 +9334,7 @@ msgstr "" " instrukcjami konfiguracji projektu DX-Ball i podaj odpowiadający jej " "oryginalny cel. Następnie uruchom:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "W kasie DX-Ball" @@ -9335,7 +9343,7 @@ msgstr "W kasie DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9349,7 +9357,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9365,7 +9373,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9389,14 +9397,14 @@ msgstr "" "Wykonaj rekonstrukcję DX-Ball z analizy binarnej przez REA do utrzymywanych " "testów C, original-x86 i dopasowywania skompilowanych bajtów funkcji." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "" "DX-Ball sound-pan investigation; przewijanie poziomo na mniejszych ekranach" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9411,70 +9419,70 @@ msgstr "" "Utrzymane C jest sprawdzane niezależnie od oryginalnego x86 w 3205 " "przypadkach i przez kompilator VC4.0 replay pasujący do 63 bajtów." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Studium przypadku rekonstrukcji DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Skopiuj przykładowy monit" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Postępuj zgodnie z obliczeniem lewej / prawej pozycji dźwięku" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Skopiuj oryginalny fragment zespołu" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Kopiuj dźwięk-funkcja panoramowania" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Skopiuj kompletny montaż dźwięku" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Skopiuj polecenie analizy DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Przejdź do treści" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Spis treści{ph1} / Gabloty" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA case studies." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9483,17 +9491,17 @@ msgstr "" "Android, Gry, Electron i wyzwanie CTF, z kodem, liczbami i sprawdzonymi " "wynikami." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * analiza APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Jak authenticator generuje kod logowania" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9504,22 +9512,22 @@ msgstr "" "generowania za pomocą REA, a następnie przesuń zegar demonstracyjny, aby " "zobaczyć, dlaczego kod zmienia się co 30 sekund." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Przeczytaj studium przypadku Androida" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Analiza programów kodu maszynowego" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Rozwiąż sprawdzanie flag CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9530,22 +9538,22 @@ msgstr "" "kontrolne, zamień maski i sumy w równania, a następnie zweryfikuj rozwiązaną" " flagę za pomocą oryginalnego programu." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Przeczytaj studium przypadku CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Natywna * Rekonstrukcja" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball obliczenie lewej / prawej pozycji dźwięku" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9557,22 +9565,22 @@ msgstr "" "do małej funkcji C, sprawdzonej pod kątem oryginalnego zachowania i " "wszystkich 63 skompilowanych bajtów." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Przeczytaj studium przypadku DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * śledzenie funkcji" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Jak Notion kopiuje tekst i HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9584,22 +9592,22 @@ msgstr "" "następnie zobacz, jak mały znacznik HTML utrzymuje bogate dane blokowe " "połączone z kopią." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Przeczytaj studium przypadku Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 dos * rekonstrukcja" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Jak TH04 celuje w pierścień kul" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9610,17 +9618,17 @@ msgstr "" "operacje mnożenia, dzielenia i koordynowania do czytelnego C++, a następnie " "zobacz, jak wytwarzają pierścień skierowany do gracza." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Przeczytaj studium przypadku TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Przewodniki krok po kroku" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9629,7 +9637,7 @@ msgstr "" "Przewodniki przechodzą przez natywne obliczenia, eksport Electron i żądanie " "przeglądarki. Każdy zaczyna się od podpowiedzi i konkretnego celu." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Przeczytaj przewodniki" @@ -9649,12 +9657,12 @@ msgstr "" "Android authenticator , DX-Ball , Notion, TH04 i kontroler flagi " "DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -9663,25 +9671,25 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Spis treści{ph1} / {ph2}Gabloty{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Studium przypadku * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Jak kopie Notion{ph0}tekst i HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9690,12 +9698,12 @@ msgstr "" "Śledź wywołanie schowka z interfejsu API strony Notion, poprzez wstępne i " "główny proces, do programu do zapisywania schowka Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Desktop 7.6.1 * JavaScript * REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Mostek wewnątrz pakietu biurkowego Notion" @@ -9707,7 +9715,7 @@ msgstr "Mostek wewnątrz pakietu biurkowego Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9724,7 +9732,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9741,7 +9749,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9758,7 +9766,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9769,13 +9777,13 @@ msgstr "" "dostarczony tekst i HTML.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Jeden kanał łączy dwie strony: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9784,14 +9792,14 @@ msgstr "" "Spakowany kod używa tego samego kanału w procesie ładowania wstępnego i " "głównego. Rozwiązanie opakowań ujawnia wywołania Electron za tymi nazwami." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "W tym studium przypadku" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9799,7 +9807,7 @@ msgstr "{ph0}Podążaj za mostkiem schowka{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9807,19 +9815,19 @@ msgstr "{ph0}Utrzymanie struktury bloku{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Więcej przykładów i źródeł{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Gdzie idzie operacja kopiowania?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9839,17 +9847,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Kopiuj" @@ -9860,7 +9868,7 @@ msgstr "Kopiuj" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9871,7 +9879,7 @@ msgstr "" "tekst i HTML do schowka systemowego. Pokaż kod na każdym " "kroku.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9880,12 +9888,12 @@ msgstr "" "Przykładowy monit z lokalnym pakietem aplikacji Notion Dostępny dla agenta " "kodującego." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA znajduje, gdzie zacząć czytać" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9896,13 +9904,13 @@ msgstr "" "wystawiony na stronę i wywołanie, które wysyła żądanie IPC. Oba ustalenia " "pochodzą z zakresów źródłowych w minified bundle:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA → dwa miejsca do otwarcia" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9915,7 +9923,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9929,12 +9937,12 @@ msgstr "" "agentowi coś precyzyjnego, czego można szukać w głównym pakiecie. Cztery " "fragmenty poniżej pokazują trasę, którą łączy." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Cztery krótkie fragmenty kodu" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9943,13 +9951,13 @@ msgstr "" "Uproszczony z pakowanego JavaScript, z czytelnymi nazwami zmiennych. " "Niepowiązani członkowie są pomijani." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Zacznij od interfejsu API wyświetlanego na stronie" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9959,13 +9967,13 @@ msgstr "" "Ten członek podaje nazwę kanału. Realizacja {ph0} informuje nas, w jaki " "sposób żądanie opuszcza proces strony." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Rozwiąż opakowanie wstępnego obciążenia" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9975,14 +9983,14 @@ msgstr "" "Zwrócona funkcja przekazuje argumenty za pośrednictwem IPC żądania i " "odpowiedzi Electron. Możemy teraz szukać {ph0} po stronie głównej-proces." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Sprawdź, jak zarejestrowany jest odbiorca" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9992,12 +10000,12 @@ msgstr "" "Główny proces wykorzystuje inne opakowanie. Jego {ph0} metoda rejestruje " "{ph1} odbiornik dla tego kanału." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Znajdź zapis i sprawdzenie jego nadawcy" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10008,13 +10016,13 @@ msgstr "" "dostarczone dane do interfejsu API schowka Electron. Kanał i dwa rozwiązane " "opakowania łączą odsłoniętą metodę z tym wywołaniem." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Jak skopiowany blok zachowuje swoją strukturę?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10025,27 +10033,27 @@ msgstr "" "dane bloku lokalnie i umieszcza identyfikator w skopiowanym kodzie HTML, aby" " je połączyć." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Linki HTML do zapisanych danych blokowych" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Przeczytaj identyfikator HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Znajdź ten sam lokalny identyfikator" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Przywróć dane bloku Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10054,7 +10062,7 @@ msgstr "" "Tekst ilustracyjny i ID. Nagrany test modułu przywraca dane bloku, gdy " "identyfikatory są zgodne; Nieaktualny wpis zwraca tylko tekst i HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10063,23 +10071,23 @@ msgstr "" "Po wklejeniu Notion szuka identyfikatora HTML i sprawdza go z zapisaną " "kopią. Pasujące identyfikatory przywracają dane bloku." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Format schowka nagrany z zasobów internetowych buforowanych 13 lipca 2026 r." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Więcej przykładów i źródeł" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Inny przykład: tabele przeceny" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10088,12 +10096,12 @@ msgstr "" "Notion analizuje Markdown na dane blokowe. Ten przykład pokazuje, jak tabela" " staje się nagłówkiem i wierszami danych." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Tabela za pośrednictwem parsera Markdown Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10102,13 +10110,13 @@ msgstr "" "Nagrane wyjście z wyodrębnionego parsera przeceny. Tabela staje się " "wierszami i komórkami." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Inna ścieżka: połączenie offline SQLite" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10121,7 +10129,7 @@ msgstr "" "wiadomości i daje jeden port rendererowi, a drugi procesowi narzędziowemu " "SQLite. Kolejne partie wyciągów i wyniki przemieszczają się przez ten port." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10130,7 +10138,7 @@ msgstr "" "Po tym przekazaniu wyjaśniono, gdzie działa baza danych i dlaczego śledzenie" " tylko początkowego żądania IPC pomija późniejszą rozmowę." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Źródła i jak czytać fragmenty" @@ -10138,7 +10146,7 @@ msgstr "Źródła i jak czytać fragmenty" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10156,7 +10164,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10172,7 +10180,7 @@ msgstr "" "moduły i małe wiązki; ich wyjścia opisują te sondy, a nie przechwyconą sesję" " interfejsu użytkownika pulpitu." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10187,7 +10195,7 @@ msgstr "" "pakiecie." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10205,7 +10213,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10219,7 +10227,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10245,52 +10253,52 @@ msgstr "" "i główny proces, z krótkimi fragmentami kodu i spojrzeniem na jego bogaty " "format schowka." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron case study" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Skopiuj monit o analizę Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Kopia Notion preload fragment" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Kopiuj Notion wywołaj fragment opakowania" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Kopia Notion obsługi wrapper fragment" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Skopiuj fragment odbiornika schowka Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Przywracanie bogatych danych schowka po wklejeniu" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Do góry" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Przejdź do treści" @@ -10299,25 +10307,25 @@ msgstr "Przejdź do treści" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Spis treści{ph1} / {ph2}Gabloty{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Studium przypadku * Touhou 4: Lotus Land Story" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Rekonstrukcja TH04{ph0}wzory pocisków." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10327,17 +10335,17 @@ msgstr "" "sprawdzić oryginalną funkcję DOS, a następnie postępuj zgodnie z jej " "instrukcjami w czytelnym C++." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * 16-bitowy DOS · C++ i montaż" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Zobacz rekonstrukcję TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Od oryginalnych instrukcji do sprawdzonego źródła" @@ -10348,7 +10356,7 @@ msgstr "Od oryginalnych instrukcji do sprawdzonego źródła" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10364,7 +10372,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10382,7 +10390,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10398,7 +10406,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10410,7 +10418,7 @@ msgstr "" "bajtów{ph3}{ph4}Zarejestrowane kontrole kompilatora obejmują kod generowania" " punktorów, który zawiera ten Pomocnik.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10419,14 +10427,14 @@ msgstr "" "REA zwraca oryginalny kod i jego dowody analizy. Projekt TH04 zapewnia " "utrzymywane kontrole źródła i kompilatora." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "W tym studium przypadku" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10434,7 +10442,7 @@ msgstr "{ph0}Pierścień kuli{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10442,7 +10450,7 @@ msgstr "{ph0}Co zwraca REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10450,7 +10458,7 @@ msgstr "{ph0}Montaż do C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10458,18 +10466,18 @@ msgstr "{ph0}Sprawdzanie źródła{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Pełny projekt{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Jak pierścień celuje w gracza" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10488,16 +10496,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Twój agent kodowania" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Kopiuj" @@ -10508,7 +10516,7 @@ msgstr "Kopiuj" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10518,7 +10526,7 @@ msgstr "" "{ph0}›{ph1}{ph2}Użyj REA, aby dowiedzieć się, jak TH04 tworzy pierścień " "pocisków i celuje w gracza. Wyjaśnij obliczenia i pokaż kod.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10528,7 +10536,7 @@ msgstr "" "dostępną lokalnie." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10542,7 +10550,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10552,12 +10560,12 @@ msgstr "" "Ilustracja odzyskanej matematyki kąta dla liczby 16, kierunku gracza 40 i " "obrotu szablonu 0. {ph0}Otwórz rysunek{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Szablon wypalania w odzyskanym źródle" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Atak pierścienia Elly * fragment źródłowy" @@ -10566,7 +10574,7 @@ msgstr "Atak pierścienia Elly * fragment źródłowy" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10576,13 +10584,13 @@ msgstr "" "Linie te wybierają wzór przed trudnością i strojeniem wydajności. " "{ph0}Przeczytaj źródło ataku{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Co zwraca REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10594,12 +10602,12 @@ msgstr "" "REA zwraca instrukcje, pseudokod i odwołania. Trzy części tego wyniku " "wyjaśniają wzór." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Sprawdź obraz DOS przed przeczytaniem jego kodu" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10608,7 +10616,7 @@ msgstr "" "Sprawdzenie wiąże załadowany kod i rekordy relokacji z dostarczonym plikiem " "wykonywalnym. Ścieżka powyżej jest skrócona do wyświetlania." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Przeczytaj mnożenie i dzielenie pierścienia" @@ -10616,7 +10624,7 @@ msgstr "Przeczytaj mnożenie i dzielenie pierścienia" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10628,12 +10636,12 @@ msgstr "" "podział wykorzystuje liczbę odczytaną z {ph1}. Utrzymane nazwy źródłowe tego" " pola {ph2}. Pełna sekwencja pojawia się poniżej." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Znajdź, gdzie wzór obraca się w kierunku gracza" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10646,12 +10654,12 @@ msgstr "" "pierścienia. Nazwy źródeł sprawiają, że adresy te są czytelne; REA pozwala " "agentowi sprawdzić oryginalne operacje za nimi." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Od zestawu do czytelnego C++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10664,7 +10672,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10672,7 +10680,7 @@ msgstr "{ph0}01{ph1} Indeks" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10680,7 +10688,7 @@ msgstr "{ph0}02{ph1} Kosmos" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10688,7 +10696,7 @@ msgstr "{ph0}03{ph1} Aim" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10696,18 +10704,18 @@ msgstr "{ph0}04{ph1} Rotate" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Sklep" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * oryginalne 16-bitowe instrukcje" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Czytelne podsumowanie C++ · aimed-ring" @@ -10715,7 +10723,7 @@ msgstr "Czytelne podsumowanie C++ · aimed-ring" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10729,7 +10737,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10745,7 +10753,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10760,7 +10768,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10775,7 +10783,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10789,7 +10797,7 @@ msgstr "" "odlewanie bez znaku. Otaczające źródło również przekształca ten kąt i " "prędkość w prędkość." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10800,7 +10808,7 @@ msgstr "" "magazyn. Powyższy C++ jest czytelnym podsumowaniem. Poniższe kontrole " "kompilatora dotyczą utrzymywanego źródła w połączonym projekcie." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Przeczytaj utrzymane źródło pierścienia i celu" @@ -10817,7 +10825,7 @@ msgstr "Przeczytaj utrzymane źródło pierścienia i celu" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10827,12 +10835,12 @@ msgstr "" "{ph0}Makro pierścienia{ph1} · {ph2}Cel i źródło prędkości{ph3} · " "{ph4}Reprezentacja kąta{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Sprawdzanie utrzymywanego źródła" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10841,12 +10849,12 @@ msgstr "" "Zarejestrowane kontrole projektu TH04 kompilują kod generowania pocisków, w " "tym ten pomocnik, z przypiętym łańcuchem narzędzi Turbo C++ 4.0 J." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2139 pasujących bajtów" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10855,12 +10863,12 @@ msgstr "" "Skompilowany kod generowania punktorów pasuje do 2139-bajtowej sekcji " "oryginalnego pliku wykonywalnego." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Dwie czyste Kompilacje" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10873,7 +10881,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." @@ -10881,59 +10889,59 @@ msgstr "" "Zarejestrowany 3 października 2026 roku. {ph0}Przeczytaj kontrole " "kompilatora{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Tożsamość celu i zakres analizy" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Oryginalny cel" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156 258 bajtów, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Wpis pomocnika" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} w załadowanym obrazie REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Oryginalny plik offset" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, zwrócony przez {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Rejestrowana Kontrola kodu" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 października 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10943,7 +10951,7 @@ msgstr "" "pomocnika. Porównują również wkład Mapy i nakładające się relokacje." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10958,7 +10966,7 @@ msgstr "" "powyżej znajdują się w tych zgłaszanych zakresach." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10975,7 +10983,7 @@ msgstr "" "repozytorium, a niezależne pochodzenie nieskazitelnego zrzutu jest nadal " "otwarte." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10986,12 +10994,12 @@ msgstr "" "sprzętowe PC-98 mają oddzielne kontrole środowiska wykonawczego w projekcie " "rekonstrukcji." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "Pełna rekonstrukcja TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11004,7 +11012,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11016,7 +11024,7 @@ msgstr "{ph0}Poznaj repozytorium TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11032,7 +11040,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11048,7 +11056,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11074,22 +11082,22 @@ msgstr "" " montażem i odzyskanym C++, aby zobaczyć, jak pierścień pocisków jest " "rozmieszczony i wycelowany w gracza." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Na tej stronie" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 bullet-pattern case study" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Skopiuj przykładowy monit TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11097,7 +11105,7 @@ msgstr "" "TH04 stałe i wycelowane pierścienie pocisku; przewijaj poziomo na mniejszych" " ekranach" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11110,27 +11118,27 @@ msgstr "" "wartość; podświetlona pierwsza wypunktowanie wskazuje na gracza. Oba " "zachowują odstęp 16 jednostek kąta lub 22,5 stopnia." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Kopiuj szablon TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Postępuj zgodnie z obliczeniem pierścienia celowanego TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Skopiuj fragment zespołu TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Kopiuj czytelne wyliczenie pierścienia" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Do góry" @@ -11240,7 +11248,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Stała prędkość: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11250,7 +11258,7 @@ msgstr "" "kontrolowanej kontroli oryginalnej gry po zaokrągleniu do trzech miejsc po " "przecinku." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11617,591 +11625,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Ten sam odstęp: 256 ÷ 16 = 16 jednostek kąta = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Przykłady" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Pierwsze kroki" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Poradniki" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Kod źródłowy" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Licencja MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Dołącz do społeczności" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Obserwuj na X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * wybrane źródło skryptu" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Kod źródłowy" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Oczekiwany formatowanie wyjście" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Instrukcje" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Dzwoniący" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Stałe" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Funkcja C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Przycisk" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "Preload API" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Plik CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Twoje kliknięcie" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Przechwycone żądanie" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Skrypt eksportu" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA wynik * podsumowanie.fragment ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA Instrukcja fragment * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA fragment dzwoniącego * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "Wyniki bajtów REA * interpretowane jako podwaja się little-endian" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Odzyskany fragment C ·" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Zobacz, jak działa REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Gabloty →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Wybrane ustawienia z kontrolowanego skryptu" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Czytelne podsumowanie % obsługi" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * wybrane oryginalne instrukcje" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Identyfikatory operatora * Źródło Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "@ Reatools na X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → agent * wybrane wyniki" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → agent * metody i rozmówcy" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * wybrana zdekompilowana Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Czytelne podsumowanie * interpretacja agenta" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, kompletne ciało" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Pobierz Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Pobierz Android analysis provider" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → agent * wybrane wyniki" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → agent * wybrane instrukcje" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agent → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → agent * siódme wpisy" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Oryginalny plik wykonywalny * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Pobierz oryginalne wyzwanie" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Pobierz solver" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "Wynik REA * fragment pseudokodu" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → agent * fragment instrukcji" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → agent * fragment dzwoniącego" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agent → REA * dwa {ph0} wnioski" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Wyniki bajtów REA * dekodowane jako podwójne" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Zacznij od własnego celu" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Generowanie kodu" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Odzyskana reguła" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Regulowany zegar" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Binarny" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Sprawdzanie kodu" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Równania" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Zgadza się!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Plik wykonywalny" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Odzyskane C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Walidacja" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Pakowana aplikacja" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Exposed API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Owijarki IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Schowek" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Oryginalny kod DOS" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA instrukcje" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Obliczanie kąta" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Bullet ring" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Exposed page API" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Renderer IPC call" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Wysłane do schowka systemowego" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Zapisane lokalnie przez Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Wejście Markdown" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Ustrukturyzowane wyjście parsera * fragment" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analizuj własną aplikację" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → agent * wybrane pola" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → agent * fragment instrukcji" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Ta sama funkcja wynik * aim fragment" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Odpowiadający utrzymywany C++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Pierścień makro * TH04 oddział, fragment" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Kąt i prędkość * fragment źródła" @@ -12235,7 +12251,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12252,7 +12268,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12273,7 +12289,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12294,7 +12310,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12313,7 +12329,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12332,7 +12348,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12343,14 +12359,14 @@ msgstr "" "stronę.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Rekonstrukcja * {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12361,7 +12377,7 @@ msgstr "" "przejrzyj proponowane zmiany." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12370,7 +12386,7 @@ msgstr "Dostarczony przykład * {ph0} i npm * Twój agent kodujący" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12389,7 +12405,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12405,7 +12421,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12424,7 +12440,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12435,7 +12451,7 @@ msgstr "" "{ph7} i zapisuje plik.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12450,7 +12466,7 @@ msgstr "{ph0} * linie 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12463,7 +12479,7 @@ msgstr "" "prognozę i rzeczywistą wydajność.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12474,7 +12490,7 @@ msgstr "" "sprawdza formatowanie bezpośrednio za pomocą {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12482,7 +12498,7 @@ msgstr "{ph0} · CSV formatowanie" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12492,7 +12508,7 @@ msgstr "" " {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12500,7 +12516,7 @@ msgstr "Nie masz {ph0}, czy nie jesteś pewien?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12513,7 +12529,7 @@ msgstr "" "polecenia\", zainstaluj {ph1} 24 LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12527,7 +12543,7 @@ msgstr "{ph0} * przykładowy fragment źródła" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12538,9 +12554,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12548,7 +12564,7 @@ msgstr "{ph0} * przykładowe źródło" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12563,7 +12579,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12576,7 +12592,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12589,7 +12605,7 @@ msgstr "Na przykład: {ph0}dlaczego kalkulator zwraca 220 dla {ph1}?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12600,7 +12616,7 @@ msgstr "" "daje 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12609,7 +12625,7 @@ msgstr "REA * załadowany {ph0} * wybrane linie" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12627,7 +12643,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12646,7 +12662,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12659,28 +12675,28 @@ msgstr "" "małe demo, w którym mogę zmieniać czas.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view / {ph0} * członek API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view / {ph0} * IPC helper" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "główna/{ph0} * Pomocnik obsługi" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12690,12 +12706,1417 @@ msgstr "główna/{ph0} * odbiornik schowka" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Pierwsze kroki {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Przełącz na jasny motyw" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Przełącz na ciemny motyw" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Aby zbadać treść żądań i odpowiedzi HTTP, użyj {ph0}Fiddler Everywhere: " +"zapisów SAZ, MCP i publicznych umiejętności{ph1}. Wyeksportuj SAZ lub HAR " +"1.2, aby uzyskać Evidence z zapisu w REA offline, lub połącz serwer MCP " +"Everywhere, aby analizować zapisany ruch z agentem." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Modele specjalistyczne{ph0}Esej" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Czy inżynieria odwrotna potrzebuje większego modelu?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Co rekonstrukcja Touhou mówi o modelach ogólnych, modelach specjalistycznych" +" i uczeniu się na podstawie informacji zwrotnych z kompilatora." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Przez N0zoM1z0 · 13 października 2026 r" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Przejdź do treści" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" +"{ph0}Strona główna{ph1} / {ph2}Blog{ph3} / Modele i inżynieria odwrotna" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Esej" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Czy inżynieria odwrotna potrzebuje większego modelu?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Przez N0zoM1z0 · 13 października 2026 r" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Najważniejsze" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Możliwości modelu wpływają na to, jakie hipotezy może postawić agent " +"AI.{ph1} Późniejsze sesje rozwiązały problemy, które nie zostały rozwiązane " +"wcześniej." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Znany kompilator oferuje konkretne wzorce do nauki dla " +"wyspecjalizowanego modelu.{ph1} Niektóre dokładne dopasowania kodu " +"maszynowego zależą od konkretnych wzorców kodu źródłowego, które można " +"ponownie wykorzystać." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}W rzetelnym porównaniu uwzględnij wiedzę o repozytorium.{ph1} Mniejszy " +"model z dobrym wyszukiwaniem wiedzy może już mieć wystarczającą ilość " +"informacji, aby poczynić postępy." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Wytrenuj model, aby wybrał kolejny przydatny eksperyment i przetestuj " +"jego moduł weryfikujący.{ph1} Opinia jest użyteczna tylko w takim stopniu, w" +" jakim moduł sprawdzający weryfikuje właściwe rzeczy." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Oceń zweryfikowane wyniki rekonstrukcji pod względem czasu i " +"kosztów.{ph1} Właśnie to chcę zmierzyć w przypadku pełnego przepływu pracy " +"agenta AI." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "W tym artykule" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Co zmieniły silniejsze modele{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Dlaczego się specjalizować?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Gdzie należy przechowywać to doświadczenie?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Nauka kolejnego przydatnego eksperymentu{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Inżynieria odwrotna i uczenie się przez wzmacnianie{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Gdy osoba sprawdzająca myli się{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Porównanie warte przeprowadzenia{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Jakiego rodzaju agenta AI to sugeruje?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Co zmieniły silniejsze modele" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Od sierpnia 2026 roku badam, ile inżynierii wstecznej może dokonać agent " +"mając dostęp do programu i możliwość sprawdzenia jego działania. Większość " +"mojego doświadczenia pochodzi z rekonstrukcji gier, szczególnie Touhou. " +"Ponieważ zmieniałem modele, repozytoria prowadziły rejestr tego, co udało " +"się odzyskać w każdej sesji." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Duża część tych prac ma na celu dokładną rekonstrukcję: kompilujemy " +"utrzymywane źródło w ramach historycznego zestawu narzędzi ze stałymi " +"wersjami i sprawdzamy, czy odtwarza ono funkcję docelową. Kiedy późniejszy " +"model odniesie sukces tam, gdzie wcześniejsze prace utknęły w martwym " +"punkcie, zmiany źródłowe pokazują, co umożliwiło ten postęp." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Zmienne tymczasowe wymagały nakładających się okresów istnienia" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Duża część logiki funkcji ataku TH09 została już zrekonstruowana, ale " +"kompilator nadal przechowywał tymczasowe wyniki inaczej niż oryginał. " +"Pozostałym problemem było to, jak długo wyniki były potrzebne do zachowania " +"żywotności i kiedy można było ponownie wykorzystać ich pamięć." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"{ph0}GPT-6-Sol rekord sesji{ph1} zgłosił tę niezgodność po przetestowaniu " +"kilku zwykłych ustaleń kodu źródłowego. Kiedy {ph2}GPT-6.1-Sol ponownie " +"zbadał problem{ph3}, zaproponował użyteczną hipotezę dotyczącą czasu życia " +"tych zmiennych tymczasowych." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"Funkcja wygenerowała tymczasowe wyniki i skopiowała je do pozycji animacji. " +"W C++ tymczasowy wynik pozostaje aktywny aż do zakończenia wyrażenia, które " +"go używa. Grupowanie rzeczywistych operacji w jedno wyrażenie utrzymywało te" +" wyniki razem, więc kompilator nie mógł już ponownie używać tej samej " +"pamięci dla nich wszystkich." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Jeden wynik nadal współdzielił pamięć o wartości używanej później do " +"sprawdzania kolizji. Nadanie tej wartości własnego czasu życia rozwiązało " +"pozostałe nakładanie się. Po kilku ukierunkowanych eksperymentach " +"{ph0}czysta rekompilacja ze źródła potwierdziła, że ​​pełna funkcja jest " +"zgodna{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Ciekawi mnie, jak odkrycie i testy wzajemnie się wspierały. Hipoteza " +"dotycząca czasu życia obiektów tymczasowych nadała agentowi AI nowy " +"kierunek. Informacje zwrotne od kompilatora pomogły mu udoskonalić tę " +"hipotezę w celu uzyskania pasującego układu kodu źródłowego." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Inny wykres przepływu sterowania" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Druga funkcja TH09 pokazuje, dlaczego ten nowy kierunek może mieć znaczenie." +" Tutaj przeszkodą był sposób, w jaki kilka oddziałów podzieliło się swoją " +"końcową pracą. We wcześniejszej pracy {ph0}GPT-6.1-Sol{ph1} części funkcji " +"pasowały, ale gałęzie nadal łączyły się inaczej niż w oryginale." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra zmienił otaczający wykres przepływu sterowania{ph1}. Główne" +" ścieżki prowadziły teraz do wspólnej ostatecznej aktualizacji i powrotu. W " +"tej strukturze źródłowej kompilator połączył gałęzie w taki sam sposób jak " +"oryginał. Pełna funkcja została zgodna i {ph2}potwierdziła to osobna " +"kontrola odbudowy{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Zmiana reprezentacji otworzyła bardziej produktywną przestrzeń " +"poszukiwań.{ph1} Obydwa przypadki dają mi powód, aby poważnie traktować " +"możliwości modelu ogólnego: agent może przez długi czas testować lokalne " +"odmiany, zanim znajdzie lepszy sposób na wyrażenie otaczającej pracy." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Jednocześnie późniejsze sesje rozpoczynały się od wcześniejszych źródeł i " +"odnotowanych awarii. Ta skumulowana praca była częścią ich przewagi. " +"Historia pozwala nam na wgląd w odkrycia i ich sprawdzenie; kontrolowane " +"porównanie pomogłoby oddzielić wpływ modelu od odziedziczonego przez niego " +"doświadczenia." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Właśnie dlatego to pytanie jest dla mnie interesujące. Pewien postęp " +"nastąpił po znalezieniu nowej reprezentacji. Większość pozostałej pracy " +"polegała na testowaniu różnych rozwiązań kodu źródłowego w porównaniu ze " +"znanym kompilatorem. Ile z tego wymaga szerokiej zdolności rozumowania? Ile " +"model może się nauczyć, wielokrotnie pracując z tym kompilatorem i kodem?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "" +"Dlaczego wyspecjalizowany model sztucznej inteligencji może się sprawdzić?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou daje nam konkretny powód, aby oczekiwać, że to doświadczenie pomoże. " +"Duża część kodu gry pochodzi od tego samego autora, ZUN, więc powtarzające " +"się nawyki są rozsądnym założeniem wyjściowym. Repozytoria potwierdzają to " +"przydatnymi przykładami: powiązane pętle i układy pomocnicze dostarczyły " +"hipotez w różnych grach." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Te wzorce źródłowe stają się bardziej szczegółowe, gdy dołączymy kompilator." +" W przypadku określonej wersji i zestawu opcji niewielkie zmiany w źródle " +"mogą powodować powtarzalne różnice w kodzie maszynowym. Niektóre z tych " +"różnic są zaskakująco niejasne." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Na przykład w TH095 {ph0}nawet nazwa zmiennej lokalnej może mieć wpływ na " +"miejsce przechowywania jej przez VC7.1{ph1}. Przeniesienie deklaracji nie " +"rozwiązało układu przechowywania. Jednak wcześniejsza funkcja tła ujawniła " +"wzorzec nazewnictwa, który wpłynął na wybór kompilatora. Sugerowało to " +"bardziej obiecującą hipotezę dotyczącą {ph2}rekonstrukcji {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Ponowne użycie tego wzorca dla zmiennej rozmiaru pliku pozwoliło uzyskać " +"wymagany układ bez dodawania pamięci. Pełna funkcja została wówczas " +"dopasowana." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Jest to bardzo specyficzny szczegół, o którym model sztucznej inteligencji " +"ogólnego przeznaczenia może nie wiedzieć, kiedy po raz pierwszy napotka " +"problem. Model wyspecjalizowany dla tego kompilatora mógłby zobaczyć wiele " +"takich przypadków i dowiedzieć się, które odmiany kodu źródłowego warto " +"przetestować w pierwszej kolejności." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Możliwość jest szczególnie wyraźna w przypadku końcowych problemów z " +"dopasowywaniem, w których już rozumiemy zachowanie. Następnie pytamy, jaki " +"zwykły układ kodu źródłowego ten kompilator przekształca w obserwowane " +"instrukcje. Specjalizacja może pomóc modelowi w skuteczniejszym proponowaniu" +" tych form, podczas gdy cel nadal określa, które hipotezy przetrwają." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Przydatne wzorce muszą zachować swój kontekst. TH08 używa wcześniejszej " +"wersji Visual C++ niż TH095 i TH09. TH04 używa innego kompilatora z ery " +"DOS-u. Do jego {ph0}rekonstrukcji kodu gracza{ph1} potrzebne były różne " +"hipotezy dotyczące wzorców kodu źródłowego i sposobu łączenia skompilowanego" +" kodu z plikiem wykonywalnym. Posiadanie tego samego autora daje nam wstępne" +" oczekiwania, ale każdy cel mówi nam, czy ma to zastosowanie. Aby rozróżnić " +"te konteksty, potrzebny byłby wyspecjalizowany model." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Gdzie należy przechowywać to doświadczenie?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Zanim zdecydowałbym się uczyć tych wzorców poprzez szkolenie modelowe, " +"sprawdziłbym wiedzę, którą już przechowujemy w repozytorium. W " +"{ph0}poprzednim eseju{ph1} pisałem, że stanie się ona pamięcią roboczą " +"projektu. Pamięć ta obejmuje lekcje kompilatora wraz ze źródłem i nieudanymi" +" eksperymentami, które uczyniły je użytecznymi." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Pobierając ten rekord, agent może zacząć od znanego wyniku i sprawdzić, w " +"jaki sposób do niego dotarliśmy. Można również uniknąć alternatyw, które już" +" zawiodły w tym samym kontekście. Punkt początkowy poprawia się bez zmiany " +"przeszkolonych parametrów modelu." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Podczas rekonstrukcji funkcji TH09 służącej do tworzenia wrogów, podczas " +"{ph0}GPT-6-Luna-max sesji{ph1} przyjęto hipotezę z powiązanego kodu " +"źródłowego TH08. Ten wcześniejszy kod sugerował, jak zorganizować pętlę i " +"poradzić sobie z błędami w niej występującymi. Zeznania TH09 dostarczyły " +"szczegółów specyficznych dla gry. Przebudowa ze źródła potwierdziła, że " +"​​cała funkcja jest zgodna." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}„Model nie wiedział, że dziwactwo kompilatora” i „model nie mógł go " +"użyć” to różne problemy.{ph1} Pobranie może rozwiązać pierwszy, ale " +"przekształcenie tego faktu w użyteczną kandydaturę nadal wymaga pracy. A " +"jeśli potencjalny kod źródłowy zawiedzie, model musi zdecydować, co oznacza " +"wynik przy następnej próbie. Znajomość odpowiedniego wzorca to dopiero " +"początek tego procesu." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Z tego powodu do każdego porównania uwzględniłbym mniejszy model sztucznej " +"inteligencji ogólnego przeznaczenia z dobrym wyszukiwaniem. Zapewnienie tej " +"samej biblioteki doświadczeń pomogłoby nam określić, co wnosi szkolenie: " +"lepsze generowanie kandydatów, lepsze decyzje po otrzymaniu informacji " +"zwrotnej lub jedno i drugie." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Nauka kolejnego przydatnego eksperymentu" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Najbardziej chciałbym się uczyć tych decyzji po otrzymaniu informacji " +"zwrotnej. W rekonstrukcji agentowej model proponuje wyjaśnienie i testuje je" +" w porównaniu z programem. Nawet jeśli potencjalny kod źródłowy zawiedzie, " +"wynik może zawęzić pozostałe możliwości i zasugerować bardziej przydatny " +"następny eksperyment." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Rozważmy ponownie przykład wyników tymczasowych. Ostateczne źródło pokazuje " +"układ, który zadziałał, ale trasa do tego źródła zawiera więcej informacji. " +"Każdy z poniższych eksperymentów pomógł określić, co należy jeszcze zmienić." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Eksperyment" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Czego nauczył nas jego wynik" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Wypróbuj inny sposób kopiowania wyników" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Kod kopiowania zmienia się, ale funkcja nadal jest inna." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Użyj bezpośrednio zwróconych wartości" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"Kopiowanie odbywa się według oryginalnego wzorca, ale przechowywanie " +"tymczasowe nadal się różni." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Zachowaj ważność wszystkich zmiennych tymczasowych w tym samym czasie" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Dostają oddzielną pamięć, ale jedna z nich nadal pokrywa się z wartością " +"używaną później do sprawdzania kolizji." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Zachowaj wartość kontroli kolizji oddzielnie" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "Czysta rekompilacja ze źródła potwierdza pełne dopasowanie." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Wybrane eksperymenty z powyższej rekonstrukcji funkcji ataku, pogrupowane " +"według tego, czego nas nauczyły." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Zapis szkoleniowy zachowujący tę sekwencję może nauczyć więcej niż samo " +"ostateczne źródło. Łączy każdą proponowaną zmianę z zaobserwowanym " +"rezultatem i następną decyzją. Utrzymywanie nieefektywnych odmian również ma" +" znaczenie: informują późniejszego agenta, które hipotezy zostały już " +"przetestowane w tym kontekście." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Chciałbym, żeby model nauczył się korzystać ze informacji " +"zwrotnej.{ph1} Neutralny wynik jest powodem do ponownego rozważenia odmiany;" +" zmieniona niezgodność może wskazywać na inną przyczynę. Kiedy lokalne " +"zmiany przestaną mieć charakter informacyjny, agent powinien mieć możliwość " +"ponownego przejrzenia reprezentacji źródłowej lub ponownego sprawdzenia " +"dowodów." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Nauka dokonywania takich wyborów wymaga autonomii. Czasami przydatnym " +"następnym krokiem jest sprawdzenie innego obiektu wywołującego, zamiast " +"kompilowania kolejnej edycji. Sztywna sekwencja wymaganych przeróbek usunie " +"ten wybór wraz z częścią zachowań, których ma się nauczyć model." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "" +"Dlaczego inżynieria odwrotna jest interesująca w uczeniu się przez " +"wzmacnianie" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Rekonstrukcja o ustalonym zakresie daje praktyczne środowisko do badania " +"tych decyzji. Po ustaleniu wersji celu i kompilatora wiele eksperymentów z " +"kodem źródłowym zapewnia szybką, powtarzalną informację zwrotną. Agent może " +"skompilować kandydata, sprawdzić różnice i wybrać następny krok." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Uczenie się przez wzmacnianie mogłoby szkolić proces podejmowania decyzji na" +" podstawie otrzymywanych informacji zwrotnych. Kandydat przyjęty przez " +"określony sprawdzian daje nam konkretny wynik, a sekwencja prób pozwala " +"zaobserwować, ile pracy wymagało jego osiągnięcie." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Istnieją już badania potwierdzające ten kierunek. {ph0}LLM4Decompile{ph1} " +"bada modele wyspecjalizowane w dekompilacji. {ph2}AutoDecompiler{ph3} " +"trenuje udoskonalanie w wielu turach, korzystając z informacji zwrotnych od " +"kompilatora i wykonania. Ich badania skupiają się na odzyskaniu funkcji. W " +"tej pracy użyłbym ich jako punktu wyjścia do powiązanego zadania " +"polegającego na znalezieniu źródła, które pasuje do danych wyjściowych " +"historycznego kompilatora." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Aby jednak osiągnąć tak dobrze zdefiniowane zadanie, być może będziemy " +"musieli najpierw ustalić, jakie zasoby posiada funkcja, lub opracować nowy " +"sposób obserwowania zachowania programu podczas wykonania. Na przykład w " +"TH08 {ph0}różnica kolizji doprowadziła do tego, jak oryginalny program " +"obsługiwał obliczenia zmiennoprzecinkowe{ph1}. Zanim agent mógł przetestować" +" użyteczną korektę, musiał ustalić, co należy zmierzyć." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Sugeruje to inną rolę modelu o szerokich możliwościach: przede wszystkim " +"pomoc w sprawdzeniu problemu. Gdy już to sprawdzimy, będziemy mogli " +"sprawdzić, jak daleko może zajść w tym przypadku wyuczona polityka " +"wyszukiwania." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Gdy osoba sprawdzająca myli się" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Gdy używamy sprawdzania podczas uczenia, jego zakres staje się częścią " +"środowiska uczenia. Taki wzorzec lub moduł sprawdzający nazywam wyrocznią. " +"Nawet powtarzalną odpowiedź trzeba rozumieć w granicach tego, co " +"rzeczywiście sprawdza." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 pokazał, jak wiele może ukryć się poza tym zasięgiem. Niektóre " +"zrekonstruowane funkcje przeszły dokładne porównania z nieprawidłowymi " +"stałymi zmiennoprzecinkowymi. Komparator korygował przeniesione adresy przed" +" sprawdzeniem instrukcji, ale sprawdzał wartości za tymi adresami tylko " +"wtedy, gdy zostały one wyraźnie zapisane w celu weryfikacji. Inne dosłowne " +"odniesienia można pominąć bez sprawdzania ich wartości." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Aby zaradzić tej luce, {ph0}szerszy audyt{ph1} wykrył nieprawidłowe stałe w " +"funkcjach, które przeszły już weryfikację. W jednym obliczeniu do " +"zrekonstruowanego kodu źródłowego dodano {ph2}, podczas gdy w oryginale " +"dodano {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Model nagrodzony starym testem weryfikacyjnym mógłby nauczyć się " +"tworzyć niepoprawną rekonstrukcję.{ph1} Nie trenowaliśmy modelu RL przy " +"użyciu tego modułu sprawdzającego. Niepowodzenie, które zaobserwowaliśmy, " +"dotyczyło samego sprawdzenia. Ale gdybyśmy użyli tego jako nagrody, ten sam " +"martwy punkt stałby się częścią środowiska uczenia się." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Test funkcjonalny może mieć podobny martwy punkt. {ph0}Badania " +"wykorzystujące różnicowe rozmycie w dekompilatorach LLM{ph1} wykazały " +"różnice w zachowaniu poza dostarczonymi testami. Dlatego też musimy rozumieć" +" zdanie egzaminu w kategoriach przypadków, w których występuje. Podobnie " +"dopasowanie instrukcji należy rozumieć w kategoriach bajtów i danych, które " +"sprawdza." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Zanim użyję jakiegokolwiek rodzaju kontroli weryfikacyjnej jako nagrody, " +"przetestowałbym ją z celowo błędnymi wynikami. Chciałbym również, aby " +"ostateczna akceptacja była oddzielona od kodu źródłowego, który agent AI " +"może edytować. Model musi przejść weryfikację poprzez poprawną rekonstrukcję" +" programu. W przeciwnym razie zwykłe skopiowanie tablicy bajtów z celu może " +"oszukać naiwny system oceniania bez odzyskiwania przydatnego kodu " +"źródłowego." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Ulepszanie modelu i ulepszanie jego modułu sprawdzającego należą do " +"tego samego problemu badawczego.{ph1} Im lepiej model optymalizuje " +"otrzymywaną informację zwrotną, tym ważniejsze jest zrozumienie tej " +"informacji." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Porównanie warte przeprowadzenia" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Mając te kontrole, rozpocząłbym porównanie od ustalonej rodziny zadań VC7.1." +" Najpierw ustaliłbym podstawy dla silnego modelu sztucznej inteligencji " +"ogólnego przeznaczenia i mniejszego. Dodanie wiedzy o repozytorium do " +"mniejszego modelu pokazałoby, jakie zmiany w pobieraniu. Następnie " +"nadzorowana specjalizacja i wersja przeszkolona przez RL pozwolą nam " +"sprawdzić, co dodaje szkolenie." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Aby porównania te miały charakter informacyjny, każdy model otrzymałby te " +"same docelowe dowody i narzędzia. W przypadku porównań specyficznych dla " +"szkoleń zachowałbym również stały model podstawowy i dostępną wiedzę. " +"Powtarzane próby pomogłyby odróżnić niezawodną strategię wyszukiwania od " +"potencjalnego rozwiązania, które odniosło sukces przez przypadek." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Następnie oddzieliłbym dwa warunki początkowe: rekonstrukcję funkcji na " +"podstawie jej instrukcji i zamknięcie kilku ostatnich różnic w utrzymywanym " +"źródle. Wyspecjalizowany model sztucznej inteligencji może doskonale " +"sprawdzić się w drugim zadaniu, podczas gdy model sztucznej inteligencji " +"ogólnego przeznaczenia wykonuje większość pracy potrzebnej do jego " +"osiągnięcia. Zmierzenie ich osobno ujawniłoby ten podział pracy." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Obydwa zadania wymagają przykładów testowych wyłączonych ze szkolenia i " +"wyszukiwania. Powiązane gry Touhou udostępniają kod silnika. Wykluczenie " +"jednej gry z treningu może w dalszym ciągu pozostawić prawie identyczne " +"funkcje w zbiorze treningowym. Zamiast tego wykluczyłbym całe grupy " +"powiązanego kodu źródłowego i trzymał ich zweryfikowane odpowiedzi poza " +"danymi szkoleniowymi i biblioteką pobierania." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"W przypadku tych przykładów wynikiem będą kompletne, niezależnie " +"zweryfikowane dopasowania. Równe budżety na propozycje kandydatów lub próby " +"kompilacji pomogłyby w porównaniu jakości wyszukiwania. Pomiar całkowitego " +"czasu i kosztów, w tym kompilacji, pokazałby, czy ta jakość zapewnia " +"efektywny przepływ pracy. Koszty szkoleń należy mierzyć osobno." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Obydwa pomiary mają znaczenie. Tania propozycja może prowadzić do " +"kosztownego przepływu pracy, jeśli powoduje więcej kompilacji, które nie " +"dostarczają żadnych przydatnych informacji. I odwrotnie, wolniejszy model " +"może być bardziej ekonomiczny, jeśli wcześniej znajdzie przydatny " +"eksperyment. Porównanie powinno uwzględniać te koszty." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Liczenie zaakceptowanych wyników pozwala również zachować perspektywę " +"postępu pośredniego. Jeden TH09 {ph0}kandydat do zapisania powtórki{ph1} " +"wyglądał obiecująco, ponieważ skompilowana funkcja miała oczekiwany rozmiar," +" ale pełne porównanie nadal wykazało znaczne różnice. Zmiany w sposobie, w " +"jaki kompilator organizuje instrukcje, mogą również sprawić, że kandydat " +"wydaje się bliższy celowi bez rozwiązania podstawowego problemu. Taka " +"diagnostyka może pomóc w kolejnym eksperymencie, ale każdą nagrodę za " +"„zbliżenie się” porównałbym z pełną kontrolą akceptacji." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Byłbym zainteresowany wzorcem tych wyników. Jeśli wyspecjalizowany model " +"sztucznej inteligencji radzi sobie dobrze w znanej rodzinie kompilatorów, " +"czy ta zaleta przetrwa zmianę w zestawie narzędzi? A kiedy oba modele " +"sztucznej inteligencji będą dobrze odzyskiwane, ile jeszcze doda szkolenie? " +"Odpowiedzi pomogłyby nam zdecydować, gdzie każdy rodzaj modelu jest " +"najbardziej przydatny." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Jakiego rodzaju agenta AI to sugeruje?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Jeśli modele pomagają na różnych etapach, przydatny może być agent ogólny z " +"dostępem do modelu specjalistycznego. Gdy zadanie sprowadza się do znanego " +"problemu z kompilatorem, może poprosić specjalistę o kandydatów. Jeśli " +"wyniki przestają mieć sens, agent ogólny może wrócić do danych celu albo " +"zbadać sam pomiar." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"W takim układzie specjalizacja staje się narzędziem, które agent może wybrać" +" w miarę rozwoju dochodzenia. Agent zachowuje swobodę zmiany kierunku, co " +"umożliwiło wcześniejsze przełomy." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Wynika to naturalnie z przemian w przemyśle, które opisałem w poprzednim " +"eseju. Możliwość przeprowadzenia znacznie większej liczby eksperymentów " +"zmienia sposób organizacji pracy. Daje nam to również powód, aby zadać sobie" +" pytanie, które decyzje wymagają szerokiego osądu, a które można poprawić " +"dzięki wielokrotnemu doświadczeniu z konkretnym rzemiosłem." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Na razie najsilniejszy model ogólny zasłużył na miejsce w moim przepływie " +"pracy, rozwiązując problemy, których wcześniej nie rozwiązałem. Te sukcesy " +"skłaniają mnie do zbadania procesu: jaka część zależała od szerokości jego " +"możliwości, a jaką mógłby wykonać model uczony specjalnie do takiej " +"rekonstrukcji?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Repozytoria umożliwiają nam przetestowanie pytania.{ph1} Chciałbym użyć" +" tego rekordu do stworzenia porównania i zobaczenia, czego się dowiemy." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Dowody i modelowe przypisanie" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Przykłady opisują historyczne porównania poziomów funkcji zarejestrowane w " +"połączonych zatwierdzeniach. Sprawdzanie czasu działania całej gry to osobne" +" kamienie milowe. Dokumenty źródłowe i pasujące sprawdzono 13 października " +"2026 r." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"Etykieta TH09 {ph0} oznacza GPT-6-Astra. Model powiązany z {ph1} zmieniał " +"się z biegiem czasu, więc sama etykieta nie może zidentyfikować modelu " +"użytego w konkretnym przebiegu. Wyraźne nazwy modeli w innych cytowanych " +"zatwierdzeniach zapewniają zarejestrowaną atrybucję. Historie te nie " +"obejmują spójnych pomiarów kosztów i wysiłku dla każdego przebiegu." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 okresy istnienia obiektów tymczasowych:{ph1} {ph2}wcześniejszy " +"przegląd kontekstu{ph3} i {ph4}pełna rekonstrukcja zweryfikowana przez " +"czystą rekompilację ze źródła{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}Callback Front w TH09:{ph1} {ph2}obszary diagnostyczne bez pełnej " +"zgodności{ph3}, {ph4}nowy graf przepływu sterowania Astry{ph5} i " +"{ph6}zaakceptowane sprawdzenie ponownej kompilacji{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Wiedza o kompilatorze:{ph1} {ph2}ponowne użycie zachowania grup " +"identyfikatorów w TH095{ph3}, {ph4}kod gracza TH04 i kolejność " +"linkowania{ph5} oraz {ph6}pełna rekonstrukcja funkcji tworzenia przeciwników" +" TH09 przez Lunę{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Kontrola i diagnostyka:{ph1} {ph2}TH08 audyt stałej " +"zmiennoprzecinkowej{ph3}, {ph4}TH08 badanie numeryczne{ph5} i {ph6}TH09 " +"rekonstrukcja z zachowaniem powtórki{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Proponowane porównania wyspecjalizowanych modeli i szkolenia RL to przyszłe " +"eksperymenty. Motywują ich historie projektów. Na potrzeby tego eseju nie " +"oceniano żadnego wyszkolonego specjalistycznego modelu." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Czy inżynieria odwrotna potrzebuje większego modelu? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Czego rekonstrukcja Touhou nauczyła mnie o modelach ogólnych, modelach " +"specjalistycznych i nauce proponowania lepszych hipotez na podstawie " +"informacji zwrotnych od kompilatora." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Na tej stronie" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Modele i esej o inżynierii odwrotnej" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Wybrane eksperymenty rekonstrukcyjne" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Do góry" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}Szczegółowe notatki o dowodach{ph1} zawierają zapisane porównania i " +"kontekst eksperymentów." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Autor: N0zoM1z0 · 13 października 2026 · Szkic do przejrzenia" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Instrukcja instalacji" diff --git a/website/locales/pt-BR/messages.po b/website/locales/pt-BR/messages.po index 82d15f9a2..c1e2d5d2b 100644 --- a/website/locales/pt-BR/messages.po +++ b/website/locales/pt-BR/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Casa{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Reflexões sobre engenharia reversa." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Reconstrução do jogo{ph0}Ensaio" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "A Revolução industrial na engenharia reversa" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "O manual RE e reconstrução TH08, TH095 e TH04 me ensinou sobre agentes, " "verificação e conhecimento que compostos entre projetos." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Leia o artigo" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Por N0zoM1z0 * 10 de outubro de 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "agentes REA e AI." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -135,112 +138,117 @@ msgstr "" "REA-descubra como o software funciona. Engenharia reversa com seu agente de " "codificação." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Página inicial do REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Navegação principal" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA no GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Participe do Discord do REA" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Siga o REA no X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -249,35 +257,35 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Casa{ph1} / {ph2}Blogue{ph3} / Reconstrução de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Ensaio * reconstrução de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "A Revolução industrial na engenharia reversa." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Por N0zoM1z0 * 10 de outubro de 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Pontos principais" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -290,7 +298,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -304,7 +312,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -317,7 +325,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -330,7 +338,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -340,65 +348,65 @@ msgstr "" "{ph0}Estamos nos primeiros dias da Revolução industrial da RE.{ph1} Os " "métodos continuam a tomar forma. Ainda há muito para explorar." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Como experiência compostos" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Direcção humana{ph1} * Objectivo e critérios de aceitação" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Autonomia" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Agente" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Escolha uma experiência.{ph0}Propor uma hipótese." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Verificação" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Referência de validação" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Ensaio contra a{ph0}referência concreta." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Repositório" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Memória de trabalho" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -407,7 +415,7 @@ msgstr "Código, elementos de prova,{ph0}verificações e lições." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -416,26 +424,26 @@ msgstr "Incompatibilidade{ph0}{ph1}Rever a hipótese{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Um melhor{ph0}{ph1}ponto de partida{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Reutilização" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Passe{ph1} * Conservar o resultado e as suas provas" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -444,14 +452,14 @@ msgstr "" "Cada projecto deixa o próximo com um melhor ponto de partida. Isso inclui a " "fixação dos controlos quando descobrimos uma lacuna." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "Neste artigo" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -459,7 +467,7 @@ msgstr "{ph0}Agosto 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -467,7 +475,7 @@ msgstr "{ph0} TH08: a continuação{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -475,7 +483,7 @@ msgstr "{ph0}Duas abordagens{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -483,7 +491,7 @@ msgstr "{ph0} TH095: composição{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -491,7 +499,7 @@ msgstr "{ph0} TH04: entre arquiteturas{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -499,7 +507,7 @@ msgstr "{ph0}Do exato ao legível{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -507,18 +515,18 @@ msgstr "{ph0}A mudança industrial{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}O que se torna possível{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "O que mudou em agosto de 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -533,7 +541,7 @@ msgstr "" " meu próprio tempo na próxima função. Também significava manter uma imagem " "cada vez maior na minha cabeça." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -547,7 +555,7 @@ msgstr "" " método pode ser útil em outros lugares, mas cada campo precisa estabelecer " "o que pode verificar em relação a uma referência confiável." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -560,7 +568,7 @@ msgstr "" " ferramentas de desenvolvimento comuns. A reconstrução de Touhou deu-me um " "projecto substancial para descobrir." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -577,7 +585,7 @@ msgstr "" "essa liberdade fez a diferença: eu poderia dedicar mais atenção à direcção " "do projecto e à fiabilidade dos seus controlos." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -588,7 +596,7 @@ msgstr "" "sobreviveria além do projeto atual. O próximo jogo beneficiaria de tudo o " "que acabámos de aprender?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: baseando-se no trabalho humano" @@ -597,7 +605,7 @@ msgstr "TH08: baseando-se no trabalho humano" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -611,7 +619,7 @@ msgstr "" "substancial. Veio com o conhecimento da construção e uma história de " "contribuições que preservei na continuação." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -623,7 +631,7 @@ msgstr "" "agosto, o livro-razão registou a fonte para todas as 1.107 funções do jogo " "identificadas." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -634,7 +642,7 @@ msgstr "" " de onze dias após o início da continuação. Seguiu-se uma edição Web. A " "versão nativa Linux de 64 bits chegou em 30 de agosto." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -650,7 +658,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -668,12 +676,12 @@ msgstr "" "exercida atinge o estado esperado. O agente propõe uma explicação e testa - " "a; uma incompatibilidade dá-lhe algo específico para investigar." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Uma correspondência exata com a constante errada" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -684,7 +692,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -697,7 +705,7 @@ msgstr "" "do jogador contra {ph0}. O original utilizado {ph1}, o limiar de potência " "máxima." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -712,13 +720,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}No entanto, a função já havia passado na comparação exata.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -733,7 +741,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -749,7 +757,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -764,7 +772,7 @@ msgstr "" "flutuante. Encontrou outras doze referências incorrectas em cinco funções " "aceites." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -778,7 +786,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -788,7 +796,7 @@ msgstr "" "{ph0}A referência de verificação (oráculo) também precisava de ser " "reconstruída.{ph1} Repará-lo fazia parte da reparação do jogo." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -806,7 +814,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -823,7 +831,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -833,7 +841,7 @@ msgstr "" "{ph0}Um lote bem sucedido proporcionou-nos tanto o código recuperado como um" " ambiente melhor para o próximo lote.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Duas ideias diferentes de reconstrução" @@ -842,7 +850,7 @@ msgstr "Duas ideias diferentes de reconstrução" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -854,7 +862,7 @@ msgstr "" "tipo de trabalho. O aviso anuncia que o desenvolvimento adicional ocorrerá " "em particular até a conclusão. Uma passagem diz:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -864,7 +872,7 @@ msgstr "" "tirando do nosso trabalho, pinta uma imagem ruim para futuros esforços de " "descompilação…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -881,7 +889,7 @@ msgstr "" "disso. O desacordo que quero discutir é sobre como a reconstrução deve " "prosseguir e como uma contribuição deve ser julgada." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -895,7 +903,7 @@ msgstr "" " importava porque grande parte do raciocínio acontecia enquanto eles " "trabalhavam." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -906,7 +914,7 @@ msgstr "" "ferramentas. O que mudou para mim foi que um agente poderia usar esse " "conhecimento para prosseguir a próxima investigação por conta própria." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -921,7 +929,7 @@ msgstr "" "pessoa possa examinar a razão pela qual escolhemos uma implementação, mesmo " "que um agente tenha feito a maior parte do trabalho." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -934,7 +942,7 @@ msgstr "" "Isso levanta questões reais sobre o crédito. Também altera o que os " "mantenedores precisam saber antes de aceitar uma contribuição." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -949,7 +957,7 @@ msgstr "" "processo e reconhecer quando sua saída está errada. Diferentes comunidades " "podem escolher quanto dessa mudança querem assumir." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -974,7 +982,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -987,14 +995,14 @@ msgstr "" "abreviado. De TH08 {ph4}créditos e proveniência{ph5} registre o limite de " "continuação." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: a experiência começa a compor" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1009,7 +1017,7 @@ msgstr "" "sabíamos muito mais sobre como iniciar uma reconstrução e como mantê-la em " "movimento." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1023,7 +1031,7 @@ msgstr "" "marcada como jogável em 10 de setembro, cerca de doze dias após a " "inicialização." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1034,7 +1042,7 @@ msgstr "" " alvo poderia beneficiar do trabalho realizado noutro jogo. A experiência já" " estava presente nas Ferramentas e na forma como o projecto foi organizado." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1049,7 +1057,7 @@ msgstr "" "trabalhar em conjunto. Essa lição ajudou a moldar a forma como abordamos a " "construção de todo o programa do TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1062,7 +1070,7 @@ msgstr "" "continuar ajudando depois que eu seguir em frente. O próximo agente pode " "utilizar o resultado sem repetir a investigação que o conduziu." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1077,7 +1085,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1089,7 +1097,7 @@ msgstr "" "jogo.{ph1} Podemos gastar mais do esforço do próximo projecto naquilo que é " "realmente novo sobre o seu objectivo." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1102,7 +1110,7 @@ msgstr "" "continuar o trabalho. Não têm de reconstruir toda a história do projecto " "para descobrir porque é que a fonte se parece com ela." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: o fluxo de trabalho sobrevive a uma arquitetura diferente" @@ -1111,7 +1119,7 @@ msgstr "TH04: o fluxo de trabalho sobrevive a uma arquitetura diferente" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1127,7 +1135,7 @@ msgstr "" "diferentes dos jogos Windows. Existente {ph2}Trabalho ReC98{ph3} deu-nos " "também aqui conhecimentos valiosos e material de origem." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1140,7 +1148,7 @@ msgstr "" "trabalho atual é uma porta nativa de 64 bits. O estabelecimento de uma " "versão DOS funcional dá, em primeiro lugar, a essa porta uma referência." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1153,7 +1161,7 @@ msgstr "" "trabalho. Mas o agente ainda pode seguir uma pergunta até um resultado e " "deixar que esse resultado guie a próxima experiência." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1168,7 +1176,7 @@ msgstr "" "os controlos estejam disponíveis, um agente pode resolver a questão da mesma" " forma que fez com um título Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1180,7 +1188,7 @@ msgstr "" " arquitetura definiu o problema; o fluxo de trabalho ainda nos deu uma " "maneira de resolvê-lo." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1197,7 +1205,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1208,12 +1216,12 @@ msgstr "" " manuais{ph1} · {ph2}Porta de 64 bits{ph3}. O porto continua em " "desenvolvimento." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Do código exato ao código legível" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1222,7 +1230,7 @@ msgstr "" "Uma vez que uma reconstrução funcione, quero que outra pessoa possa " "compreendê-la." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1237,7 +1245,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1254,7 +1262,7 @@ msgstr "" " raciocínio com a fonte para que a próxima pessoa possa ver de onde veio " "essa interpretação." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1269,14 +1277,14 @@ msgstr "" "esse estado. Para mover o comportamento com segurança, precisamos recuperar " "a relação por trás do antigo acesso à memória." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "A ordem que eu uso agora é:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1292,7 +1300,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1309,7 +1317,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1325,7 +1333,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1340,7 +1348,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1357,7 +1365,7 @@ msgstr "" "reconstruído continua a construir e a comportar-se correctamente ao longo " "dos caminhos que exercemos." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1371,7 +1379,7 @@ msgstr "" "disponíveis dá ao Agente uma falha concreta em investigar antes de levar " "mais longe um refatorador." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1389,7 +1397,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1408,7 +1416,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1419,12 +1427,12 @@ msgstr "" "torna utilizável o conhecimento recuperado.{ph1} Um porto pode então basear-" "se em ambos." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "O que torna esta mudança industrial" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1438,7 +1446,7 @@ msgstr "" "fazer. Uma ferramenta melhor poderia ajudar em todas as funções posteriores " "que dela necessitassem." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1452,7 +1460,7 @@ msgstr "" " esperar que eu prescreva cada passo, grande parte do trabalho continua " "ligada à minha atenção." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1465,7 +1473,7 @@ msgstr "" "lo a entender o erro o suficiente para tentar novamente. Ainda tenho de " "decidir se as provas acumuladas apoiam um marco do projecto." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1480,7 +1488,7 @@ msgstr "" "verificações de referência. O agente pode usá-los para testar a fonte que " "propõe e ver onde está a sua explicação." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1498,7 +1506,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1519,7 +1527,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1537,7 +1545,7 @@ msgstr "" " que afectou. O próximo projecto pode então herdar uma ferramenta mais " "forte." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1553,7 +1561,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1565,7 +1573,7 @@ msgstr "" "aos projectos uma forma partilhada de levar adiante os seus controlos e " "lições. Trabalhar num jogo pode melhorar as condições de partida para outro." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1577,12 +1585,12 @@ msgstr "" "essas ferramentas muda o quanto a próxima pessoa—ou o próximo agente—pode " "fazer." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Os projectos que podemos agora considerar" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1594,7 +1602,7 @@ msgstr "" "própria atenção do que eu poderia realisticamente dar. Muitos projectos " "continuariam a ser ideias." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1612,7 +1620,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1623,7 +1631,7 @@ msgstr "" "feedback e conhecimento acumulado permitiriam que um agente trabalhasse de " "forma fiável?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1634,12 +1642,12 @@ msgstr "" " em paz. Cada um pode melhorar a forma como abordamos o próximo. Quero " "continuar a explorar até onde isso nos pode levar." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Marcos e fontes do projecto" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1674,7 +1682,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1708,7 +1716,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1726,7 +1734,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1750,7 +1758,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1773,7 +1781,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1789,7 +1797,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1811,7 +1819,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1826,7 +1834,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1847,27 +1855,27 @@ msgstr "" " agentes de IA e como o conhecimento se compõe em TH08 , TH095 e PC-98 TH04 " "." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Experiência realizada entre projectos" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Ensaio de reconstrução de Touhou" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -1876,18 +1884,18 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Casa{ph1}{ph2}/{ph3}Dinosaur speed lab" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Inspeccionar valuetech" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Reconstrua a regra da velocidade do dinossauro." @@ -1896,7 +1904,7 @@ msgstr "Reconstrua a regra da velocidade do dinossauro." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1908,15 +1916,15 @@ msgstr "" "sua velocidade. {ph0} REA retornou o script em execução;{ph1} usámos a sua " "regra para construir este mini-jogo com {ph2}velocidade ajustável.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Nesta página" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1924,7 +1932,7 @@ msgstr "{ph0}Jogue e mude a velocidade{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1932,7 +1940,7 @@ msgstr "{ph0}Leia a regra recuperada{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1940,18 +1948,18 @@ msgstr "{ph0}Verificar a reconstrução{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Experimente a análise{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Jogue e mude a velocidade" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1963,49 +1971,49 @@ msgstr "" "muda para uma velocidade fixa. Selecione a regra recuperada para começar em " "6 e acelerar gradualmente novamente." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Jogue a reconstrução" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Jogar" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Pular ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Reiniciar" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Velocidade" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Use a regra de aceleração recuperada" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Regra Original: comece em 6, depois aumente para 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Mova o controle deslizante para definir sua própria velocidade. Espaço ou " "salto limpa um cacto." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2014,7 +2022,7 @@ msgstr "" "Permitir que o JavaScript reproduza a reconstrução. O código e a explicação " "acima permanecem legíveis." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Leia o script REA retornado" @@ -2022,7 +2030,7 @@ msgstr "Leia o script REA retornado" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2037,7 +2045,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2047,18 +2055,18 @@ msgstr "" "As configurações são {ph0}, {ph1} e {ph2}. O jogo executa este ramo em uma " "atualização sem colisão." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Use a mesma regra no novo jogo" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Copiar" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2075,19 +2083,19 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "" "{ph0}Baixe a regra da velocidade{ph1} · {ph2}Leia o código do jogo{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Verificar a reconstrução" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2098,27 +2106,27 @@ msgstr "" "programação automática desativada. Compare essas velocidades registadas com " "uma repetição da regra recuperada." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Actualizações" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Jogo Original" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Regra reconstruída" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Execute a verificação de velocidade" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2128,14 +2136,14 @@ msgstr "" "adicionar, de modo que o incremento final pode ter velocidade um pouco acima" " de 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Experimente você mesmo a análise" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2144,7 +2152,7 @@ msgstr "{ph0}Configurar REA {ph1} com o seu agente de codificação." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2153,7 +2161,7 @@ msgstr "" "Siga o {ph0}etapas de conexão do navegador{ph1}, utilizando {ph2} como o URL" " da página." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2170,7 +2178,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2182,7 +2190,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2196,7 +2204,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2211,7 +2219,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2237,12 +2245,12 @@ msgstr "" "Leia a regra de Velocidade do jogo de dinossauros com REA, reconstrua-a, " "depois altere a velocidade e jogue." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Reconstrução da velocidade dos dinossauros" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2251,52 +2259,52 @@ msgstr "" "Mini-jogo de dinossauros. Use o botão de salto ou pressione espaço enquanto " "o jogo está focado." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Copiar regra de velocidade reconstruída" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copie o alerta da análise do dinossauro" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Casa{ph1} / FAQ" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA FAQ." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Configuração, atualizações, análise e resolução de problemas." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Temas" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2304,7 +2312,7 @@ msgstr "{ph0}Configuração e atualizações{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2312,7 +2320,7 @@ msgstr "{ph0}Análise{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2320,31 +2328,31 @@ msgstr "{ph0}Resolução de problemas{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Dados e partilha{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Configuração e atualizações" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Como instalo o REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * configuração do agente" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Copiar" @@ -2352,7 +2360,7 @@ msgstr "Copiar" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2366,12 +2374,12 @@ msgstr "" "caminho do arquivo e uma pergunta. O {ph0}guia de configuração{ph1} explica " "os pré-requisitos e a primeira análise." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Que agentes de codificação podem utilizar REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2386,18 +2394,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Ligue o seu agente de codificação{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Como atualizo o REA?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2406,13 +2414,13 @@ msgstr "" "O REA é lançado com frequência, incluindo correções de bugs. Se você " "instalou o CLI com npm :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * CLI instalado" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2422,14 +2430,14 @@ msgstr "" "Siga o comando setup refresh impresso pela atualização. Se configurar o seu " "agente através de {ph0}, correr:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * configuração do agente de atualização" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2442,14 +2450,14 @@ msgstr "" "usar a nova versão. Para um comando avulso na CLI, coloque o comando depois " "de {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Está instalando a habilidade de skills.sh chega?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2461,24 +2469,24 @@ msgstr "" "Configuração REA{ph1} para conectar o servidor MCP e instalar a habilidade " "correspondente, reinicie o agente para que ele possa chamar as ferramentas." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Análise" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "O que posso analisar com REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Comece com o tipo de software que você tem:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2490,7 +2498,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2502,7 +2510,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2512,7 +2520,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2524,12 +2532,12 @@ msgstr "" "Android, firmware e recursos empacotados. {ph0}Ver os estudos de caso{ph1} " "para investigações trabalhadas." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Preciso de Hopper, Ghidra ou IDA ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2542,7 +2550,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2555,12 +2563,12 @@ msgstr "" "pode ser usado. {ph0}Configurar a análise de programas de código de " "máquina{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Posso usar REA sem um agente de codificação?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2569,14 +2577,14 @@ msgstr "" "Sim. O CLI utiliza os mesmos fluxos de trabalho de análise. Para uma " "aplicação local JavaScript ou Electron:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * análise estática da aplicação" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2587,13 +2595,13 @@ msgstr "" "{ph0}Utilizar o CLI {ph1} para opções de instalação." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Que código o REA retorna?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2608,7 +2616,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2620,12 +2628,12 @@ msgstr "" " testar uma implementação. O {ph0} Cálculo DX-Ball{ph1} e {ph2}Verificador " "de bandeira CTF{ph3} mostre como esse processo funciona." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "O que devo perguntar ao meu agente?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2642,7 +2650,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2650,7 +2658,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2660,18 +2668,18 @@ msgstr "" "Substitua o caminho pelo seu alvo. O {ph0}guias{ph1} forneça prompts para " "exemplos nativos, Electron e navegadores." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Resolução de problemas" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Por Que meu agente não pode ver as ferramentas REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2681,7 +2689,7 @@ msgstr "" "Reinicie ou reconecte seu agente após a configuração. Verifique seu registro" " REA com {ph0}; para Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * verificar um cliente" @@ -2689,7 +2697,7 @@ msgstr "Terminal * verificar um cliente" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2700,14 +2708,14 @@ msgstr "" "relatório mostrar um registo em falta ou obsoleto, execute a configuração " "para esse cliente:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * reparar a configuração de um cliente" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2719,14 +2727,14 @@ msgstr "" "as ferramentas permanecerem ausentes, Verifique o erro de conexão MCP do " "cliente. {ph0}Mais diagnósticos de configuração{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Preciso iniciar o Hopper primeiro?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2738,14 +2746,14 @@ msgstr "" "escolha de modo de demonstração ou ativação de licença antes da análise " "autônoma. {ph0}Consulte Configuração do provedor nativo{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "O que faço se encontrar um bug?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2757,7 +2765,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2770,17 +2778,17 @@ msgstr "" " o nome do Fornecedor quando o problema envolver a análise de programas de " "código de máquina." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Dados e partilha" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "O REA carrega a minha aplicação?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2790,7 +2798,7 @@ msgstr "" "Política de dados do respetivo Fornecedor modelo aplica-se a esses " "resultados." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Como posso partilhar um exemplo ou contribuir?" @@ -2799,7 +2807,7 @@ msgstr "Como posso partilhar um exemplo ou contribuir?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2815,7 +2823,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2841,77 +2849,77 @@ msgstr "" "de análise, agentes de codificação, solução de problemas e exemplos de " "compartilhamento." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Perguntas frequentes sobre REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Copiar o comando de configuração REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Copiar comando de actualização REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Comando de atualização de configuração do agente de cópia" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Copiar comando de análise REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Copiar exemplo de pedido de análise" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Comando Copy client diagnosis" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Comando de configuração com escopo de cópia" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Casa{ph1} / Sua primeira investigação" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Descubra onde{ph0}notas exportadas vão." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2920,14 +2928,14 @@ msgstr "" "Use o REA para inspecionar um pequeno aplicativo, siga o botão Exportar " "notas e verifique você mesmo um detalhe." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "Neste exercício" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2935,7 +2943,7 @@ msgstr "{ph0}1. Configurar{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2943,7 +2951,7 @@ msgstr "{ph0}2. Pergunte sobre exportação{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2951,7 +2959,7 @@ msgstr "{ph0}3. Siga a resposta{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2959,13 +2967,13 @@ msgstr "{ph0}4. Verificar uma previsão{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Faça outra pergunta{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Ligue o seu agente ao REA" @@ -2978,29 +2986,29 @@ msgstr "1. Ligue o seu agente ao REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Copiar" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Ou execute este comando no seu terminal:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3009,14 +3017,14 @@ msgstr "" "Revise o plano, aprove a configuração e reinicie o agente. Já está ligado? " "Continue abaixo." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Pergunte onde está escrito o CSV" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3028,7 +3036,7 @@ msgstr "" "exportação{ph1} botão. Seu agente pode inspecionar seu código sem instalar " "ou iniciar o Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3040,14 +3048,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Baixar exemplo ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3057,12 +3065,12 @@ msgstr "" "Se o seu agente não puder baixar arquivos, Descompacte este arquivo você " "mesmo. Dê-lhe o caminho para o {ph0} pasta e a mesma questão de exportação." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Siga a resposta de volta ao código" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Procure uma breve explicação com referências de arquivo e linha:" @@ -3071,7 +3079,7 @@ msgstr "Procure uma breve explicação com referências de arquivo e linha:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3083,12 +3091,12 @@ msgstr "" "CSV e escreve {ph1} na pasta Downloads do utilizador. As colunas são {ph2} e" " {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Do botão ao gravador de arquivos" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3097,7 +3105,7 @@ msgstr "" "A análise estática do REA emparelha a mensagem com o seu manipulador. O " "destino é lido a partir do Código." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3109,7 +3117,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." @@ -3117,12 +3125,12 @@ msgstr "" "{ph0}Veja o rastreamento completo do código e o resultado REA " "registrado{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Verificar uma previsão" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3131,19 +3139,19 @@ msgstr "" "Uma vírgula separa as colunas CSV. O que acontece quando o próprio título de" " uma nota contém uma vírgula ou aspas?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Execute o cheque você mesmo" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Abrir um terminal no desembalado {ph0} pasta:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3152,17 +3160,17 @@ msgstr "" "Este comando usa um shell com suporte a documentos here, como Bash ou Zsh. " "Seu agente pode executar o mesmo JavaScript no shell da sua plataforma." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Faça outra pergunta" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Tente um acompanhamento na mesma conversa:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3171,7 +3179,7 @@ msgstr "" "O que acontece se o ficheiro não puder ser gravado? Siga o erro de volta à " "página." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3184,7 +3192,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3198,7 +3206,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3212,7 +3220,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3237,65 +3245,65 @@ msgstr "" "pergunte para onde vão as notas exportadas e verifique o formatador CSV com " "um título de amostra." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Sua primeira investigação REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Copiar o aviso de instalação do REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Comando Copiar configuração" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Copiar notas pedido de investigação" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Copiar o pedido de verificação CSV" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Comando Copiar verificação do formatador" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Casa{ph1} / Começar" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Configurar REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3303,49 +3311,49 @@ msgstr "" "Conecte o REA ao seu agente de codificação ou inspecione um aplicativo local" " do seu terminal." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Abrir um terminal e verificar:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminal" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Copiar" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3358,7 +3366,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3369,17 +3377,17 @@ msgstr "" "desativada neste sistema\"{ph1} quando você corre {ph2}, execute isto uma " "vez e tente novamente:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Se utilizar Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Caso contrário:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Feche o Terminal, abra-o novamente, depois:" @@ -3387,7 +3395,7 @@ msgstr "Feche o Terminal, abra-o novamente, depois:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3399,7 +3407,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3411,7 +3419,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3420,14 +3428,14 @@ msgid "" msgstr "" "Prefere um instalador regular? Baixe a versão LTS de {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Opções de configuração" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3435,7 +3443,7 @@ msgstr "{ph0}Ligue o seu agente de codificação{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3443,7 +3451,7 @@ msgstr "{ph0}Utilizar o CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3451,18 +3459,18 @@ msgstr "{ph0}Configurar a análise de programas de código de máquina{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Obter ajuda{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Ligue o seu agente de codificação" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3474,12 +3482,12 @@ msgstr "" "Windsurf , Grok Build e outros clientes MCP suportados. O conector do Grok " "Bot é adicionado a partir do seu chat." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Novo em agentes de codificação?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3491,7 +3499,7 @@ msgstr "" "executar comandos, e pergunta antes de fazer alterações. REA dá-lhe " "ferramentas da reverso-engenharia." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3503,7 +3511,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3516,7 +3524,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3529,7 +3537,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3539,7 +3547,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}, código aberto. Conecte o Provedor do modelo " "de sua escolha." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3556,18 +3564,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Ou execute a configuração você mesmo" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Como abrir um terminal?" @@ -3576,7 +3584,7 @@ msgstr "Como abrir um terminal?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3592,7 +3600,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3606,7 +3614,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3620,7 +3628,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3630,7 +3638,7 @@ msgstr "" "Colar um comando com {ph0} {ph1} (macOS : {ph2} {ph3}; Terminais Linux: " "{ph4} {ph5} {ph6}) e, em seguida, prima Enter." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3641,12 +3649,12 @@ msgstr "" "conexão MCP e a habilidade de investigação correspondente, mantendo um " "backup da configuração existente. Pergunta antes de aplicar as alterações." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Reinicie o cliente quando a configuração terminar." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Como faço para reiniciar meu cliente?" @@ -3655,7 +3663,7 @@ msgstr "Como faço para reiniciar meu cliente?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3671,7 +3679,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3681,7 +3689,7 @@ msgstr "" "{ph0}Agentes terminais{ph1} (Claude Code, Codex, Gemini CLI ): saia da " "sessão e inicie-a novamente." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3691,7 +3699,7 @@ msgstr "" "aplicativo JavaScript ou Electron, você pode começar com:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3702,12 +3710,12 @@ msgstr "" "chamadas e dependências envolvidas, com os locais de origem das suas " "descobertas." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Substitua o caminho pelo seu destino local." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Como obtenho o caminho completo de uma pasta?" @@ -3716,7 +3724,7 @@ msgstr "Como obtenho o caminho completo de uma pasta?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3732,7 +3740,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3744,7 +3752,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3754,18 +3762,18 @@ msgstr "" "{ph0}Qualquer sistema:{ph1} arraste a pasta para uma janela de terminal e " "seu caminho será exibido." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "Em um terminal, coloque aspas em torno de um caminho que contém espaços." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Utilizar o CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3774,14 +3782,14 @@ msgstr "" "Analisar uma pasta de Aplicação JavaScript ou Electron ou um arquivo ASAR " "sem executar a aplicação:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Análise estática da aplicação" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3791,13 +3799,13 @@ msgstr "" "Substitua o caminho pelo diretório do aplicativo extraído ou {ph0} ficheiro." " Em Windows, um caminho como {ph1} trabalha aqui." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Onde encontro um aplicativo .ficheiro asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3808,7 +3816,7 @@ msgstr "Os aplicativos Electron geralmente o mantêm em um {ph0} pasta:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3820,7 +3828,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3833,14 +3841,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} muitas vezes {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3848,7 +3856,7 @@ msgstr "" "Alguns aplicativos são instalados em outro lugar. Pesquise na pasta do " "aplicativo {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3860,31 +3868,31 @@ msgstr "" "resolvidas estão marcadas no resultado." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Se você quiser uma permanente {ph0} comando na sua concha:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Instalar o CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Continue com o Guia de Aplicação JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Configurar a análise de programas de código de máquina" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3894,12 +3902,12 @@ msgstr "" "local. Escolha e configure um abaixo e, em seguida, forneça ao REA seu " "executável ou biblioteca." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Escolha uma ferramenta: Ghidra, Hopper ou IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3911,17 +3919,17 @@ msgstr "" " de um descompilador nativo para sua arquitetura de host. Definir os " "caminhos antes de executar a configuração:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Conecte sua instalação Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ligação Ghidra * macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3933,12 +3941,12 @@ msgstr "" "Linux arm64, pode ser necessário construir o decompilador nativo do Ghidra " "separadamente." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Ligar Ghidra em Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3949,12 +3957,12 @@ msgstr "" "nativas x86 e x64 PE e DLLs em unidades NTFS locais fixas. Use um Ghidra " "12.1 existente.x Instalação e um JDK de 64 bits 21 ou mais recente:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ligação Ghidra * Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3962,7 +3970,7 @@ msgstr "" "Substitua os dois caminhos pelas suas instalações e, em seguida, reveja o " "plano da instalação." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3972,7 +3980,7 @@ msgstr "" "detecta uma instalação existente ou oferece um plano de instalação para sua " "aprovação." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3981,7 +3989,7 @@ msgstr "" "No macOS, conclua a primeira escolha do modo de demonstração ou ativação da " "licença do Hopper antes de uma análise autônoma." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3992,7 +4000,7 @@ msgstr "" " para uma GUI anexada ou um banco de dados sem cabeça. A análise sem cabeça" " Linux e macOS permanece não verificada." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Ligar um registo IDA MCP existente" @@ -4002,7 +4010,7 @@ msgstr "Ligar um registo IDA MCP existente" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4014,13 +4022,13 @@ msgstr "" " em um arquivo JSON. Um existente {ph3} objecto com um {ph4} a entrada " "também é aceita. Aponte REA nesse ficheiro antes da configuração:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Ligação IDA * Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4037,7 +4045,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4049,31 +4057,31 @@ msgstr "" "um agente, incluir {ph1} no ambiente do registro REA e selecione IDA ao " "abrir o binário." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Para uma configuração existente do Ghidra, inspecione uma função com:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Análise de funções" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "" "Substituir {ph0} com o nome ou endereço da função que pretende inspecionar." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "" "Como funcionam as sessões de análise de programas de código de máquina" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4086,7 +4094,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4096,18 +4104,18 @@ msgstr "" "{ph0}Seguir um exemplo de análise de programas de código de máquina{ph1} " "para ver como o resultado da função conduz a um cálculo recuperado." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Obter ajuda" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Se o seu agente não vir REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4117,27 +4125,27 @@ msgstr "" "Reinicie ou volte a ligar o cliente após a configuração. Verificar a ligação" " REA com {ph0}; para Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Verificar um cliente" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Se um fornecedor precisar de atenção" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Verifique o fornecedor que está a utilizar. Para Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Verificar um fornecedor" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "O relatório apresenta a verificação falhada e sugere o próximo passo." @@ -4146,7 +4154,7 @@ msgstr "O relatório apresenta a verificação falhada e sugere o próximo passo #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4159,7 +4167,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4173,7 +4181,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4187,7 +4195,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4212,112 +4220,112 @@ msgstr "" "JavaScript ou Electron local a partir do terminal. Configuração, primeiras " "perguntas e guias do provedor nativo." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Copiar a verificação da versão Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Copiar o comando de instalação Node.js para Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Copiar o comando da Política de execução do PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Comando de instalação copiar Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Copiar o comando de instalação do fnm para macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Copiar comandos Node.js 24 para macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Copiar o comando de instalação do fnm para Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Copiar comandos Node.js 24 para Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA guia de introdução" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Copiar o aviso de instalação do REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Comando Copy agent setup" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Copiar comando de análise JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Copiar o comando de instalação do CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Copiar o comando de conexão do Ghidra para macOS e Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Copiar ligação Ghidra para Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Copiar ligação IDA para Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Copiar comando de análise de função nativa" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Comando Copy client diagnosis" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Comando de diagnóstico do Fornecedor de cópia" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -4326,20 +4334,20 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Casa{ph1} / {ph2}Guias{ph3} / Observação do navegador" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Veja o que acontece{ph0}quando você clica." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4348,14 +4356,14 @@ msgstr "" "Use um pequeno aplicativo de navegador para conectar uma ação, sua " "solicitação de rede e o JavaScript que cria um download." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "Neste guia" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4363,7 +4371,7 @@ msgstr "{ph0}O exemplo{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4371,7 +4379,7 @@ msgstr "{ph0}Abra o navegador{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4379,7 +4387,7 @@ msgstr "{ph0}Pergunte ao seu agente{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4387,13 +4395,13 @@ msgstr "{ph0}Captura a partir de CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Ler o pedido e o guião{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "O que acontece quando você clica em Exportar?" @@ -4403,7 +4411,7 @@ msgstr "O que acontece quando você clica em Exportar?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4415,7 +4423,7 @@ msgstr "" "botão. Clicar nele carrega {ph4}, Formata as duas notas como CSV e inicia um" " download." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Do clique ao download do CSV" @@ -4426,7 +4434,7 @@ msgstr "Do clique ao download do CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4442,7 +4450,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4461,7 +4469,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4471,17 +4479,17 @@ msgstr "" "{ph0}03 * o seu agente{ph1}{ph2}Ler o código de exportação{ph3}{ph4}Ligar o " "pedido observado ao {ph5} em {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Inicie a captura antes de clicar em Exportar notas." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Abrir Chrome com depuração remota" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4490,21 +4498,21 @@ msgstr "" "Abra o exemplo do hosted Notes com um perfil de navegador separado e uma " "porta de depuração local. Em Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Inicie o navegador de exemplo" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Copiar" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4513,7 +4521,7 @@ msgstr "" "Use o caminho executável do navegador instalado em macOS ou Windows . Você " "pode substituir o URL da página por outra página que deseja inspecionar." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4522,7 +4530,7 @@ msgstr "" "REA se conecta a este navegador existente. Você mantém o controle da página," " executa a ação e fecha o navegador quando terminar." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Peça ao seu agente para assistir a uma ação" @@ -4535,7 +4543,7 @@ msgstr "Peça ao seu agente para assistir a uma ação" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4547,7 +4555,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4558,7 +4566,7 @@ msgstr "" "Exportar notas. Que Pedido faz e como é construído o CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4568,7 +4576,7 @@ msgstr "" "Exemplo de alerta. Dê ao seu agente o ponto de extremidade de depuração, " "{ph0}, e o URL da página. Deixe-o iniciar a captura antes de clicar." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4579,23 +4587,23 @@ msgstr "" "lê as evidências resultantes. Ele pode então inspecionar o script por trás " "da exportação." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Ou captura a partir do terminal" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Encontrar o ID de destino da página:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Encontre a página" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4605,14 +4613,14 @@ msgstr "" "Escolha o destino com o URL de exemplo do Notes. Substituir {ph0} abaixo com" " o seu ID, em seguida, executar:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Capture os próximos dez segundos" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4623,7 +4631,7 @@ msgstr "" "exportação{ph1} nesse navegador. O resultado chega após o fim da janela de " "observação." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4634,49 +4642,49 @@ msgstr "" "durante essa janela e a forma da resposta JSON. Os pedidos anteriores estão " "fora desta captura." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Leia o script de solicitação e exportação" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Gravado com REA 4.1.0 no exemplo de notas locais" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Facto capturado" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Valor" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Pedido" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Resposta" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Iniciador do pedido" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * roteiro" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Estrutura de resposta" @@ -4684,19 +4692,19 @@ msgstr "Estrutura de resposta" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} com {ph1} e {ph2} campos" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Ler os scripts carregados" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4708,7 +4716,7 @@ msgstr "" "usados:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4721,7 +4729,7 @@ msgstr "" "solicitado {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4733,7 +4741,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4758,65 +4766,65 @@ msgstr "" "Observe uma exportação de notas com REA: selecione uma página do navegador, " "capture um clique, inspecione a solicitação e siga o script de exportação." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Observação do navegador" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Copiar iniciar o navegador de exemplo" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Copiar exemplo de pedido" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Copiar encontrar a página" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Copiar capturar os próximos dez segundos" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Copiar ler os scripts carregados" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Casa{ph1} / Guias" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Guias REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4825,38 +4833,38 @@ msgstr "" "Analise uma função nativa, uma exportação Electron ou uma solicitação do " "navegador. Cada guia inclui um aviso, código e resultados." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Primeira investigação" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Configurar REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "" "Ligue o seu agente de codificação ou utilize o REA a partir do terminal." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Começar a utilizar REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Programas de código de máquina" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Recuperar um cálculo da posição sonora esquerda/direita" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4865,22 +4873,22 @@ msgstr "" "Comece com um executável de jogo Windows. Inspecione as instruções, siga um " "chamador, leia constantes numéricas e verifique o C recuperado." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Análise do Guia de programas de código de máquina" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Seguir uma exportação CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4890,14 +4898,14 @@ msgstr "" "carregamento e processo principal. Use REA para conectar a API, o canal IPC " "e o gravador de arquivos." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript & guia Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4905,17 +4913,17 @@ msgstr "" "Para um aplicativo empacotado maior, siga {ph0} Notion's clipboard " "bridge{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Comportamento do navegador" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Observe um clique" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4924,7 +4932,7 @@ msgstr "" "Abra um exemplo de notas de trabalho, capture uma solicitação de exportação " "e encontre o código que transforma sua resposta em um download." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Guia de observação do navegador" @@ -4943,12 +4951,12 @@ msgstr "" "Aprenda REA através de exemplos curtos trabalhados: um cálculo nativo, uma " "exportação Electron CSV e uma solicitação do navegador." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -4957,20 +4965,20 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Casa{ph1} / {ph2}Guias{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Rastrear um Electron {ph0} Exportação CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4979,14 +4987,14 @@ msgstr "" "Siga um clique de botão da API da página, através do Electron IPC, até o " "gravador de arquivos CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "Neste guia" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4994,7 +5002,7 @@ msgstr "{ph0}O exemplo{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5002,7 +5010,7 @@ msgstr "{ph0}Pergunte ao seu agente{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5010,7 +5018,7 @@ msgstr "{ph0}Rastrear o código de exportação{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5018,20 +5026,20 @@ msgstr "{ph0}Experimente o exemplo{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Inspecionar o gravador CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Para onde vão as\" notas de exportação\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5043,7 +5051,7 @@ msgstr "" "exportação{ph1} chama uma API na página, cruza para o processo principal e " "grava um CSV . O comportamento está espalhado por vários arquivos." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "A exportação CSV através dos processos Electron" @@ -5057,7 +5065,7 @@ msgstr "A exportação CSV através dos processos Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5074,7 +5082,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5091,7 +5099,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5104,13 +5112,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} Formata as notas7 {ph1} escreve {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5121,14 +5129,14 @@ msgstr "" "exposta. O caminho é inferido do Código; uma captura de tempo de execução " "pode verificar o que é executado." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Pergunte sobre a exportação CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5146,14 +5154,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Copiar" @@ -5164,7 +5172,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5175,7 +5183,7 @@ msgstr "" "notas neste app. Onde é criado o CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5185,7 +5193,7 @@ msgstr "" "Exemplo de alerta. Inclua o caminho absoluto para a pasta do aplicativo ou " "{ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5196,17 +5204,17 @@ msgstr "" "módulos e limites do processo. Seu agente usa esse mapa para restringir a " "investigação ao recurso de exportação." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Rastrear o código de exportação" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "A página chama uma pequena API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5217,7 +5225,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5229,7 +5237,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5240,7 +5248,7 @@ msgstr "" "notas e o processo principal escreve {ph1} na pasta Transferências do " "utilizador." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5249,7 +5257,7 @@ msgstr "" "Gravado por REA 4.1.0 no exemplo para download abaixo. Os locais de origem " "acompanham as descobertas da API, do canal e do manipulador." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Analise você mesmo o exemplo" @@ -5257,25 +5265,25 @@ msgstr "Analise você mesmo o exemplo" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Baixar exemplo ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Procurar os seis ficheiros de origem" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Análise estática da aplicação" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5286,7 +5294,7 @@ msgstr "" " canal IPC e um manipulador correspondente em {ph0}. Os locais de origem " "estão em {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5297,13 +5305,13 @@ msgstr "" "caminho ASAR. Um agente pode seguir uma string literal, nome de API ou canal" " IPC com as ferramentas de rastreamento de recursos do REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Inspecionar o gravador CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5313,7 +5321,7 @@ msgstr "" "Seguir {ph0} ao seu manipulador. Quais entradas atingem o gravador CSV e o " "que acontece se a gravação do arquivo falhar?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5328,7 +5336,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5342,7 +5350,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5356,7 +5364,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5382,32 +5390,32 @@ msgstr "" "pré-carga e manipulador IPC com REA . Inclui ficheiros de exemplo " "descarregáveis e um resultado de análise verificado." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Copiar exemplo de pedido" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Copiar análise estática da aplicação" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -5416,7 +5424,7 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5424,14 +5432,14 @@ msgstr "" "{ph0}Casa{ph1} / {ph2}Guias{ph3} / Análise de programas de código de máquina" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "" "Recuperar o de DX-Ball{ph0}cálculo da posição sonora esquerda/direita." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5440,14 +5448,14 @@ msgstr "" "Inspecione as instruções originais, identifique a entrada e as constantes e," " em seguida, verifique o C recuperado." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "Neste guia" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5455,7 +5463,7 @@ msgstr "{ph0}O exemplo{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5463,7 +5471,7 @@ msgstr "{ph0}Pergunte ao seu agente{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5471,7 +5479,7 @@ msgstr "{ph0}Leia os resultados do REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5479,18 +5487,18 @@ msgstr "{ph0}Recuperar e verificar{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Use seu próprio binário{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Calcular o posicionamento do som estéreo esquerdo / direito" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5501,7 +5509,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5513,7 +5521,7 @@ msgstr "" "para {ph1}. REA também retorna suas instruções e chamadores, que dão ao " "Agente uma maneira de investigar a aritmética ausente." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Novo nestes Termos?" @@ -5522,7 +5530,7 @@ msgstr "Novo nestes Termos?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5534,7 +5542,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5547,7 +5555,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5560,7 +5568,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5572,7 +5580,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5582,7 +5590,7 @@ msgstr "" "{ph0}Constantes:{ph1} números fixos armazenados no programa, lidos como " "bytes brutos e decodificados." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Três elementos de prova, um cálculo" @@ -5593,7 +5601,7 @@ msgstr "Três elementos de prova, um cálculo" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5610,7 +5618,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5628,7 +5636,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5638,7 +5646,7 @@ msgstr "" "{ph0}03 * bytes de dados{ph1}{ph2}As constantes numéricas{ph3}{ph4}Os bytes " "referenciados descodificam para {ph5}, {ph6} e um valor de escala.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5647,7 +5655,7 @@ msgstr "" "REA fornece as instruções, a relação função-chamada e os bytes. O agente " "interpreta-os em conjunto." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Pergunte sobre o comportamento" @@ -5656,7 +5664,7 @@ msgstr "Pergunte sobre o comportamento" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5667,19 +5675,19 @@ msgstr "" " de análise de programas de código de máquina{ph3}, forneça o executável " "local e uma pergunta:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Que Ferramenta de análise devo utilizar?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA precisa de um destes para ler programas nativos:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5693,7 +5701,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5706,7 +5714,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5717,7 +5725,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5733,14 +5741,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Copiar" @@ -5751,7 +5759,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5762,7 +5770,7 @@ msgstr "" "posicionamento do som estéreo. Explique o cálculo e mostre o " "código.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5773,7 +5781,7 @@ msgstr "" "Ball 1.07. REA não inclui DX-Ball, então use sua própria cópia ou Faça o " "mesmo tipo de pergunta sobre outro pequeno programa Windows que você possui." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Como obtenho o caminho completo de um ficheiro?" @@ -5782,7 +5790,7 @@ msgstr "Como obtenho o caminho completo de um ficheiro?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5798,7 +5806,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5811,7 +5819,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5821,17 +5829,17 @@ msgstr "" "{ph0}Qualquer sistema:{ph1} arraste o arquivo para uma janela de terminal e " "seu caminho será exibido." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Leia os resultados do REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Leia a entrada" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5841,13 +5849,13 @@ msgstr "" " ponto flutuante. Esta é a entrada ausente da primeira visualização de " "pseudocódigo." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Siga o chamador" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5858,12 +5866,12 @@ msgstr "" "multiplicam a coordenada do bloco por 30; adicionando {ph0} (20) indica a " "posição do ecrã do tijolo." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Leia as constantes referenciadas" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5873,12 +5881,12 @@ msgstr "" "os valores reais; a ordem de instrução informa ao agente como eles são " "usados." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Escrever e verificar a função recuperada" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5889,7 +5897,7 @@ msgstr "" "-500, 0 e 500 antes da conversão de inteiros. O cálculo coloca o centro da " "tela no centro do campo estéreo." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5902,21 +5910,21 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "" "{ph0}Ver o inquérito completo e a comparação entre a montagem e a c{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Experimente com seu próprio binário" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5930,7 +5938,7 @@ msgstr "" " para investigar. Perguntas iniciais úteis incluem \"como este arquivo é " "analisado?\"ou\" qual função lida com esta ação do menu?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5939,13 +5947,13 @@ msgstr "" "Se já souber o nome ou endereço de uma função, pode consultá-la a partir do " "terminal. Para uma instalação Ghidra configurada:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Análise de funções" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5959,7 +5967,7 @@ msgstr "" "fecha sua sessão. As consultas MCP do seu agente reutilizam o binário " "importado enquanto essa sessão está aberta." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5983,50 +5991,50 @@ msgstr "" "Recupere um cálculo nativo com REA: inspecione as instruções, siga um " "chamador, leia constantes e verifique c reconstruído." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Análise de programas de código de máquina" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Copiar exemplo de pedido" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Análise da função de cópia" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Configurar REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6034,7 +6042,7 @@ msgstr "{ph0}Configurar REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6042,7 +6050,7 @@ msgstr "{ph0}O que é RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6050,7 +6058,7 @@ msgstr "{ph0}Como o REA ajuda{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6058,7 +6066,7 @@ msgstr "{ph0}Jogo de dinossauros{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6066,7 +6074,7 @@ msgstr "{ph0}Calculadora{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6074,7 +6082,7 @@ msgstr "{ph0}Experimente REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6082,7 +6090,7 @@ msgstr "{ph0}Aprofunde-se{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6090,25 +6098,25 @@ msgstr "{ph0}Ajuda e feedback{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Comunidade{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Engenharia reversa, com seu agente de codificação" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Descubra como{ph0}o software funciona." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6119,7 +6127,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6127,13 +6135,13 @@ msgstr "Já conhece o RE? {ph0}Ir para os guias de análise{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Quer ir mais fundo? {ph0}Leia o blogue{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Copie este prompt para seu agente de programação:" @@ -6146,38 +6154,38 @@ msgstr "Copie este prompt para seu agente de programação:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Copiar" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Ou execute este comando no terminal:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Revise e aprove as alterações propostas. Depois, reinicie seu agente." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "O que é engenharia reversa?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6191,7 +6199,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6203,7 +6211,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6211,7 +6219,7 @@ msgstr "Antes do REA · Você investiga {ph0}por conta própria{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6219,7 +6227,7 @@ msgstr "{ph0}01{ph1} Descodificar ramificações" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6227,7 +6235,7 @@ msgstr "{ph0}02{ph1} Rastrear chamadas" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6237,20 +6245,20 @@ msgstr "{ph0}03{ph1} Recuperar a regra" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Original x64 · instruções seleccionadas{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * que ramo?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6260,29 +6268,29 @@ msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Dois saltos para o mesmo lugar. Que operadores são " "estes?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Procure os IDs do comando e, em seguida, rotule a ramificação." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Dividir ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Multiplicar ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · O que fazem as funções chamadas?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6292,24 +6300,24 @@ msgstr "" "\"100 é claro. As chamadas são apenas endereços. {ph0}Qual deles divide? Que" " valor entra?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Inspecione as funções auxiliares e rastreie os valores armazenados." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Dividir" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * Qual é a regra?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6319,19 +6327,19 @@ msgstr "" "\"Este caminho multiplica-se pela outra entrada. Então {ph0}10% significa " "10% de 200{ph1} depois de +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Nomeie os operandos e verifique os dois caminhos do operador." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Raciocínio ilustrativo de peritos" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6343,20 +6351,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Com o REA · Você pergunta ao {ph0}seu agente{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Um único prompt." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6370,21 +6378,21 @@ msgstr "Pergunte ao seu agente {ph0}com palavras simples.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Exemplo de alerta * Calculadora" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Exemplo de resposta * com base nas conclusões" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6392,29 +6400,29 @@ msgid "" msgstr "" "Depois de+, o botão % leva {ph0}uma percentagem do primeiro número.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "O REA fornece" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Instruções do manipulador, código descompilado e chamadas." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Seu agente explica" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Qual ramificação se aplica, o que calcula e como reconstruí-la." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6427,7 +6435,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6437,37 +6445,37 @@ msgstr "" "{ph0}Vamos tentar dois exemplos.{ph1} Altere a velocidade de um jogo, depois" " volte à calculadora e reconstrua o botão%." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Exemplo 01 * jogo de dinossauros de Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Por que o dinossauro fica mais rápido?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Objectivo" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Reconstrua o jogo com {ph0}velocidade ajustável.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Por que fazer engenharia reversa?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6477,49 +6485,49 @@ msgstr "" "Para reproduzir sua aceleração, precisamos {ph0}a regra no jogo de " "corrida{ph1}: quão rápido começa, quanto aumenta e quando pára." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Jogue a reconstrução" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Jogar" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Pular ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Reiniciar" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Velocidade" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Use a regra de aceleração recuperada" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Regra Original: comece em 6, depois aumente para 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Mova o controle deslizante para definir sua própria velocidade. Espaço ou " "salto limpa um cacto." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6528,14 +6536,14 @@ msgstr "" "Permitir que o JavaScript reproduza a reconstrução. O código e a explicação " "acima permanecem legíveis." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "O REA retornou" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6554,7 +6562,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6568,7 +6576,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6582,7 +6590,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6596,7 +6604,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6606,12 +6614,12 @@ msgstr "" "{ph0}Comece às 6.{ph1} Adicionar {ph2}0.001{ph3} cada atualização sem " "colisão, enquanto a velocidade é inferior {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Abrir o laboratório de velocidade" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "O que cada parte faz" @@ -6622,7 +6630,7 @@ msgstr "O que cada parte faz" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6638,7 +6646,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6655,7 +6663,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6665,13 +6673,13 @@ msgstr "" "{ph0}03 * Você{ph1}{ph2}Alterar a velocidade e jogar{ph3}{ph4}Experimente a " "aceleração original e escolha o seu próprio ritmo.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Veja o script, verificações e como tentar a análise" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6681,7 +6689,7 @@ msgstr "" "O REA inspecionou a edição do navegador HTTP por meio de uma conexão de " "depuração local e retornou {ph0}, incluindo a sua fonte e digestão." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6695,7 +6703,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6712,7 +6720,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6730,7 +6738,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6739,19 +6747,19 @@ msgstr "" "{ph0}Código de velocidade inspeccionado{ph1} · {ph2} Chromium autores * " "licença BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Exemplo 02 * Calculadora Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Recrie o botão % da calculadora." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6762,7 +6770,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6773,29 +6781,29 @@ msgstr "" " o aplicativo instalado para descobrir a qual número a porcentagem é " "aplicada." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Tente o cálculo" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Redefinir" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% de 200 = 20. Então 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Ilustração interactiva da regra das percentagens inspeccionadas." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6807,7 +6815,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6821,7 +6829,7 @@ msgstr "Para este exemplo, {ph0} e {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6837,7 +6845,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6849,7 +6857,7 @@ msgstr "" "Recupere as regras depois de + E7X, em seguida, construir uma pequena " "calculadora que usa ambos.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Com +" @@ -6857,13 +6865,13 @@ msgstr "Com +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Pegue 10% do primeiro número.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Com a ×" @@ -6871,13 +6879,13 @@ msgstr "Com a ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Transformar 10% em 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Do aplicativo instalado para um botão % funcional" @@ -6889,7 +6897,7 @@ msgstr "Do aplicativo instalado para um botão % funcional" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6906,7 +6914,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6918,12 +6926,12 @@ msgstr "" "regras{ph3}{ph4}Verifique o ramo com a fonte da Microsoft e, em seguida, " "tente + e elimi acima.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Veja o código real e como a resposta foi verificada" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6944,7 +6952,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6954,17 +6962,17 @@ msgstr "" "{ph0}Percentagem de execução{ph1} · {ph2}Casos de teste da Microsoft{ph3} · " "{ph4}Guia de configuração nativo{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Sua primeira investigação" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Tente REA em um pequeno aplicativo." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6973,12 +6981,12 @@ msgstr "" "Baixe nosso exemplo de notas, Rastreie sua exportação CSV e verifique uma " "entrada alterada." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Experimente o exemplo guiado" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Quer se aprofundar?" @@ -6987,7 +6995,7 @@ msgstr "Quer se aprofundar?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7007,13 +7015,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Exemplo de pedido * Sítio Web" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Sim, esta." @@ -7026,7 +7034,7 @@ msgstr "Sim, esta." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7041,7 +7049,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7055,23 +7063,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Ver estudo de caso DX-Ball{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Para as etapas de configuração e análise, escolha o seu destino:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Programas de código de máquina" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7080,17 +7088,17 @@ msgstr "" "Inspecione funções, strings, referências e relações de chamada de função em " "executáveis e bibliotecas." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Análise do Guia de programas de código de máquina" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7099,17 +7107,17 @@ msgstr "" "Mapeie módulos, rotas, IPC e dependências nativas de uma pasta de aplicativo" " ou arquivo ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Fluxos de trabalho da aplicação" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Atividade do navegador e do tempo de execução" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7118,12 +7126,12 @@ msgstr "" "Capture a atividade selecionada do navegador ou do processo e compare os " "resultados entre as execuções." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Guia de observação do navegador" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Alguma dúvida?" @@ -7134,7 +7142,7 @@ msgstr "Alguma dúvida?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7144,12 +7152,12 @@ msgstr "" "{ph0}Leia as perguntas frequentes{ph1}, {ph2}fale connosco em Discord {ph3}," " ou {ph4}abrir um problema GitHub{ph5} para bugs e solicitações de recursos." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Participe da comunidade" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7173,27 +7181,27 @@ msgstr "" " seu agente de codificação. Siga guias claros e experimente exemplos " "interativos com REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Copiar o aviso de instalação do REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Comando Copiar configuração" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Siga a análise manual da calculadora" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Pergunta percentual da calculadora de cópia" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7202,37 +7210,37 @@ msgstr "" "Mini-jogo de dinossauros. Use o botão de salto ou pressione espaço enquanto " "o jogo está focado." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Copie o alerta da análise do dinossauro" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Escolha o cálculo" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Cópia Calculadora análise prompt" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Copiar pedido de Projecto do website" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Copiar o prompt de reconstrução do jogo" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -7241,25 +7249,25 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Casa{ph1} / {ph2}Vitrines{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Estudo de caso · autenticador Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Como é que um autenticador{ph0}gerar um código de login?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7269,17 +7277,17 @@ msgstr "" "cálculo em um APK Android, em seguida, reconstruí-lo com um relógio que você" " pode controlar." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * lançamento oficial APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Ver Aegis em GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "De um APK a um código que pode reproduzir" @@ -7290,7 +7298,7 @@ msgstr "De um APK a um código que pode reproduzir" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7308,7 +7316,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7325,7 +7333,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7337,14 +7345,14 @@ msgstr "" "código.{ph3}{ph4}Uma nova demonstração do navegador reproduz a regra e " "verifica-a em relação a casos de referência públicos.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "Neste estudo de caso" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7352,7 +7360,7 @@ msgstr "{ph0}Pergunte ao seu agente{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7360,7 +7368,7 @@ msgstr "{ph0}Experimente o gerador de código{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7368,7 +7376,7 @@ msgstr "{ph0}Encontre o código com REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7376,7 +7384,7 @@ msgstr "{ph0}Leia o cálculo{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7384,20 +7392,20 @@ msgstr "{ph0}Verificar a reconstrução{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Inspecione você mesmo o APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Pergunte ao seu agente" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7415,21 +7423,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Copiar" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7439,14 +7447,14 @@ msgstr "" "Um exemplo de prompt para o APK baixado, com a análise Android do REA " "configurada. {ph0}Obter o APK e a configuração de análise{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Experimente o gerador de código" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7458,33 +7466,33 @@ msgstr "" "o número do bloco com a chave da conta para gerar um código. A mesma chave e" " bloco produzem o mesmo código." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Mova o relógio em 60 segundos" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Tempo" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "segundos" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Nosso exemplo de relógio ajustável" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "Bloco de 30 segundos" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Bloco" @@ -7493,35 +7501,35 @@ msgstr "Bloco" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 segundos{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Código gerado" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Chave de conta + bloco7 seis dígitos" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Tempo de exemplo, em segundos" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 segundos" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 segundos" @@ -7530,7 +7538,7 @@ msgstr "60 segundos" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7542,7 +7550,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7552,7 +7560,7 @@ msgstr "" "A chave é fixa, pública {ph0}Dados do ensaio RFC 6238{ph1}. A demonstração " "implementa o cálculo recuperado do APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7561,18 +7569,18 @@ msgstr "" "O diagrama mostra o resultado em 59 segundos. Habilite o JavaScript para " "alterar o relógio." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Encontre o código com REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Reduzir o APK a três classes" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7583,14 +7591,14 @@ msgstr "" "progresso e às contas importadas. TOTP significa uma senha de uso único " "baseada no tempo." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Ligue o gerador ao ecrã da aplicação" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7602,7 +7610,7 @@ msgstr "" "chamando {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7612,14 +7620,14 @@ msgstr "" "As solicitações mostram um caminho de entrada reduzido. Os nomes das classes" " de resultado omitem o comum {ph0} prefixo." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Leia o cálculo" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7634,7 +7642,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7642,7 +7650,7 @@ msgstr "{ph0}01{ph1} Bloco de tempo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7650,7 +7658,7 @@ msgstr "{ph0}02{ph1} Chave + bloco" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7658,7 +7666,7 @@ msgstr "{ph0}03{ph1} Seis dígitos" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7670,7 +7678,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7684,7 +7692,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7699,7 +7707,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7710,7 +7718,7 @@ msgstr "" "exibição. O painel da direita é um Resumo Explicativo. {ph0} O código Aegis " "é GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Dentro do gerador" @@ -7719,7 +7727,7 @@ msgstr "Dentro do gerador" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7729,7 +7737,7 @@ msgstr "" "O APK lançado coloca {ph0} em {ph1}. REA segue a chamada de {ph2} e retorna" " este corpo; a fonte original chama o ajudante {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7746,20 +7754,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Comparar com a fonte de lançamento correspondente{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Verificar a reconstrução" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7772,29 +7780,29 @@ msgstr "" "independente em {ph0}133 casos de ensaio{ph1}, incluindo limites de bloqueio" " de tempo e códigos que começam com zero." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Tempo de exemplo" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Código de seis dígitos" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 segundos" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 segundos" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7804,17 +7812,17 @@ msgstr "" "O gerador também corresponde aos seis casos de referência SHA-1 publicados " "em {ph0}RFC 6238{ph1}. Verifique a implementação do navegador contra eles:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Executar verificações de referência" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Leia o cálculo da demonstração" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7823,7 +7831,7 @@ msgstr "" "Os casos de referência utilizam oito dígitos. O controlo verifica igualmente" " os seus resultados de seis dígitos." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7832,14 +7840,14 @@ msgstr "" "A verificação executa métodos Java extraídos e a nova demonstração. O " "Android APK foi inspeccionado estaticamente." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Inspecione você mesmo o APK" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7851,7 +7859,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7861,18 +7869,18 @@ msgstr "" "A análise do Android precisa de um JDK 17 completo ou posterior. Selecione-o" " com {ph0} ou {ph1}. Este caso utilizou o JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Aponte REA para o ficheiro do fornecedor e inspecione o APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7884,7 +7892,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7894,7 +7902,7 @@ msgstr "" "Uma próxima pergunta: {ph0}o que acontece quando uma conta utiliza oito " "dígitos ou um intervalo de tempo diferente?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Fontes" @@ -7910,7 +7918,7 @@ msgstr "Fontes" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7924,7 +7932,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" @@ -7932,7 +7940,7 @@ msgstr "" "{ph0}RFC 6238 casos de referência{ph1} · {ph2}Dados do teste de " "demonstração{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7957,37 +7965,37 @@ msgstr "" "Inspecione o Aegis Android APK com REA, recupere seu cálculo de código de " "login de seis dígitos e tente uma reconstrução com um relógio ajustável." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK estudo de caso" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Copiar o prompt de exemplo Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Siga o cálculo do código de login" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Copiar comando de inspecção APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -7996,26 +8004,26 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Casa{ph1} / {ph2}Vitrines{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Estudo de caso * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Encontre a bandeira em{ph0}um binário CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8026,18 +8034,18 @@ msgstr "" "suas regras em equações e encontrar uma entrada que faça o programa original" " imprimir {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "" "verificador Mascarado da bandeira dos quadrados * fácil * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Veja o desafio original" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "De um binário para uma resposta verificada" @@ -8048,7 +8056,7 @@ msgstr "De um binário para uma resposta verificada" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8066,7 +8074,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8084,7 +8092,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8096,21 +8104,21 @@ msgstr "" "Correct!{ph3}{ph4}Um script Python resolve as equações. REA captura o " "programa original aceitando o resultado.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" "O desafio é de joseph, publicado no repositório oficial da DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "Neste estudo de caso" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8118,7 +8126,7 @@ msgstr "{ph0}Encontrar o código de verificação{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8126,7 +8134,7 @@ msgstr "{ph0}Leia uma máscara{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8134,7 +8142,7 @@ msgstr "{ph0}Montagem em código legível{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8142,7 +8150,7 @@ msgstr "{ph0}Resolver as equações{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8150,20 +8158,20 @@ msgstr "{ph0}Verifique a resposta{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Experimente você mesmo{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Encontrar o código de verificação" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8181,17 +8189,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Copiar" @@ -8202,7 +8210,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8214,7 +8222,7 @@ msgstr "" "sinalizador. Explique como funcionam as verificações e, em seguida, " "verifique a resposta com o programa original.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8223,12 +8231,12 @@ msgstr "" "Um exemplo de alerta, com o desafio baixado disponível localmente e uma " "análise do provedor de programas de código de máquina conectado." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Siga o prompt de entrada para sua função" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8237,14 +8245,14 @@ msgstr "" "A referência dá ao Agente um local para investigar, mesmo que os nomes das " "funções originais do executável tenham sido removidos." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Leia o verificador e seus dois ajudantes" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8257,7 +8265,7 @@ msgstr "" " com um número memorizado. Sua {ph0}- passos byte através {ph1} bytes dar 26" " máscaras." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8267,12 +8275,12 @@ msgstr "" "destino local é encurtado para exibição; os endereços referem-se à imagem " "importada de REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Uma verificação revela um carácter" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8285,14 +8293,14 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "" "A sétima verificação selecciona apenas uma posição. {ph0}Figura aberta{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Leia a máscara e seu alvo a partir do binário" @@ -8301,7 +8309,7 @@ msgstr "Leia a máscara e seu alvo a partir do binário" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8313,12 +8321,12 @@ msgstr "" " {ph1} meios -21. O alvo é um número inteiro little-endian. Juntos, esses " "bytes informam ao agente que {ph2}, então esse personagem é {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Das instruções a um controlo legível" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8329,7 +8337,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8337,7 +8345,7 @@ msgstr "{ph0}01{ph1} Comece" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8345,7 +8353,7 @@ msgstr "{ph0}02{ph1} Seleccionar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8353,7 +8361,7 @@ msgstr "{ph0}03{ph1} Adicionar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8361,18 +8369,18 @@ msgstr "{ph0}04{ph1} Adiantamento" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Comparar" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * instruções originais selecionadas" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "C · resumo de uma verificação legível" @@ -8380,7 +8388,7 @@ msgstr "C · resumo de uma verificação legível" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8388,7 +8396,7 @@ msgstr "{ph0}01 * Comece em zero.{ph1} {ph2} detém a soma corrente." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8400,7 +8408,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8412,7 +8420,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8426,7 +8434,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8436,7 +8444,7 @@ msgstr "" "{ph0}05 * comparar com o alvo armazenado.{ph1} O chamador recebe a soma em " "{ph2}. Uma incompatibilidade salta para {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8445,12 +8453,12 @@ msgstr "" "As instruções vêm do Auxiliar de Somação e do seu interlocutor. O C é um " "Resumo Explicativo com nomes descritivos e um loop de 36 células achatado." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Resolva as 26 equações" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8462,13 +8470,13 @@ msgstr "" "seleções sobrepostas fornecem equações que um pequeno script Python pode " "resolver juntos." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * trecho do solver" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8482,19 +8490,19 @@ msgstr "" "com letras, dígitos, sublinhados e chaves. O download completo inclui todas " "as 26 Máscaras e alvos." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Baixe o solucionador completo" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Verifique a resposta com o programa original" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8506,47 +8514,47 @@ msgstr "" "sinalizador resolvido. Alterar um carácter seleccionado de {ph0} para {ph1} " "faz a primeira soma 1440 em vez de 1441, e o programa rejeita-a." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Entrada" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Resultados observados" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Código de saída" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Bandeira do Solver" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Um caractere alterado" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Mostrar o sinalizador recuperado e a saída capturada" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * saída original do programa" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Copiar bandeira" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8556,12 +8564,12 @@ msgstr "" "Desafio publicados pelos organizadores, verificados após a resolução do " "binário." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Fonte, identidade do alvo e dados de análise" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8572,7 +8580,7 @@ msgstr "" " REA 4.1.0 com Ghidra 12.1.4 em Linux x64. O binário é um Elf x86-64 " "despojado, 15.248 bytes." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8596,7 +8604,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8606,12 +8614,12 @@ msgstr "" "{ph0}Compare com a fonte dos organizadores{ph1} · {ph2}Metadados do Desafio " "e sinalizador{ph3} · {ph4} REA notas de prova{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Experimente você mesmo" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8620,13 +8628,13 @@ msgstr "" "Baixe o desafio original e o solucionador em uma pasta. Use o prompt acima " "para investigar com seu agente ou execute o script incluído." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * resolver e executar" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8638,7 +8646,7 @@ msgstr "" "Resolvendo necessidades Python e {ph0}. A execução do executável original " "Precisa de Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Configurar REA com o seu agente de codificação" @@ -8660,27 +8668,27 @@ msgstr "" "DownUnderCTF. Encontre as funções de verificação, extraia as máscaras e " "compare uma bandeira recuperada com o programa original." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Estudo de caso CTF flag-checker" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Copiar o prompt de exemplo do CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "Equação da máscara CTF; rolar horizontalmente em telas menores" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8691,42 +8699,42 @@ msgstr "" " 14. Só essa célula contribui para a soma. Seu código de caracteres exigido " "é 55, o que significa que o caractere é 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Siga a verificação do CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Copiar montagem CTF" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Cópia de verificação CTF legível" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Copiar trecho do solucionador CTF" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Copiar bandeira recuperada" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Copiar comandos do solucionador CTF" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -8735,25 +8743,25 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Casa{ph1} / {ph2}Vitrines{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Estudo de caso * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Reconstrução DX-Ball {ph0}do seu executável." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8762,14 +8770,14 @@ msgstr "" "O objetivo é uma versão c sustentável do jogo Windows de 1996. REA ajuda o " "agente a inspecionar o original, uma função de cada vez." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8781,14 +8789,14 @@ msgstr "" "chamadores e as leituras dos dados; o projecto de reconstrução implementa e " "testa o resultado. {ph0}Figura aberta{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "Neste estudo de caso" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8796,7 +8804,7 @@ msgstr "{ph0}O projecto{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8804,7 +8812,7 @@ msgstr "{ph0}Som pan{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8812,23 +8820,23 @@ msgstr "{ph0}Verificando o resultado{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Continuar o trabalho{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "funções C mantidas" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "comparações com o código original" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "funções com correspondência de bytes compilados" @@ -8839,7 +8847,7 @@ msgstr "funções com correspondência de bytes compilados" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8849,12 +8857,12 @@ msgstr "" "Ponto de verificação do projeto: 7 de outubro de 2026. {ph0}Razão de " "progresso{ph1} · {ph2}Cobertura do ensaio{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "O projecto até agora" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8869,12 +8877,12 @@ msgstr "" "jogo jogável continua com física de bola e remo, manipulação de power-up e " "integração Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Determinação do cálculo da posição sonora esquerda/direita" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8893,17 +8901,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Copiar" @@ -8914,7 +8922,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8925,7 +8933,7 @@ msgstr "" "posicionamento do som estéreo. Explique o cálculo e mostre o " "código.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8936,7 +8944,7 @@ msgstr "" "local disponível. A investigação que se segue mostra as questões REA e os " "elementos de prova subjacentes à resposta." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8950,7 +8958,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8964,12 +8972,12 @@ msgstr "" "e operações de ponto flutuante. Essa discrepância deu ao Agente uma razão " "concreta para continuar a investigar." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "A primeira vista decompiladora" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8978,18 +8986,18 @@ msgstr "" "A saída mostra uma chamada de conversão. A leitura das instruções abaixo " "revela a entrada e o cálculo que alimentam essa chamada." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Três perguntas respondidas através de REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Recuperar a entrada em falta" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9000,14 +9008,14 @@ msgstr "" "chamadores. Aqui, {ph0} expõe a entrada inteira ausente da visualização " "decompiler." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Siga o chamador para entender a entrada" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9018,12 +9026,12 @@ msgstr "" "instruções anteriores {ph0} por 30; adicionar 20 dá a coordenada da tela do " "tijolo, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Ler os valores por detrás dos endereços de memória" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9032,12 +9040,12 @@ msgstr "" "Os bytes retornados estabelecem as duas constantes aritméticas e a escala " "pan inicial. O agente agora tem os valores necessários para a expressão C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Das conclusões do REA até C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9048,7 +9056,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9056,7 +9064,7 @@ msgstr "{ph0}01{ph1} Entrada" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9064,7 +9072,7 @@ msgstr "{ph0}02{ph1} Multiplicar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9072,7 +9080,7 @@ msgstr "{ph0}03{ph1} Subtrair" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9080,18 +9088,18 @@ msgstr "{ph0}04{ph1} Escala" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Retorno" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Original x86 * excerto" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Reconstrução C" @@ -9101,7 +9109,7 @@ msgstr "Reconstrução C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9121,7 +9129,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9137,7 +9145,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9155,7 +9163,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9172,7 +9180,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9184,7 +9192,7 @@ msgstr "" " identificado nos resultados do receptor do REA. O C lança o resultado para " "{ph4}; comparações originais-x86 verificam o valor devolvido." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9195,23 +9203,23 @@ msgstr "" "retorno. A lista completa abaixo também inclui os armazenamentos " "intermediários e a configuração e limpeza de funções." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Conjunto completo e elementos de prova de apoio" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA resultado · 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "O que o chamador fornece" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9221,54 +9229,54 @@ msgstr "" "A função brick-hit em {ph0} dimensiona sua coordenada de bloco em 30, " "adiciona 20 e, em seguida, empurra-a antes da chamada:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "O que os dados indicam" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA Byte lê, decodificado como Little-Endian duplica" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Endereço" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Valor" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Usado para" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Primeira multiplicação" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Subtração" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} inicialmente" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Escala armazenada da bandeja" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9284,7 +9292,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9294,12 +9302,12 @@ msgstr "" "{ph0}Fonte mantida{ph1} · {ph2}Notas de investigação e referências de " "elementos de prova{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Verificação da função recuperada" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9308,12 +9316,12 @@ msgstr "" "A função recuperada passa por duas verificações: seus valores de retorno " "correspondem ao original e seus bytes compilados correspondem ao executável." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 casos de comportamento" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9324,12 +9332,12 @@ msgstr "" "com o C mantido.cobrem todas as posições inteiras de 0 a 640 em cinco " "escalas pan: 0, 0,5, 1, 20 e -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 bytes correspondentes" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9340,7 +9348,7 @@ msgstr "" "do compilador corresponde à função completa após aplicar as relocações " "revisadas e verificar as constantes referenciadas." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9355,18 +9363,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Leia os detalhes do replay do compilador{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Prosseguir o inquérito" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9378,7 +9386,7 @@ msgstr "" "recuperar o seu estado e dependências e, em seguida, comparar a " "implementação com a original." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9388,7 +9396,7 @@ msgstr "" "configuração do projeto DX-Ball e forneça seu alvo original correspondente. " "Em seguida, execute:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "No checkout DX-Ball" @@ -9397,7 +9405,7 @@ msgstr "No checkout DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9411,7 +9419,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9427,7 +9435,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9452,7 +9460,7 @@ msgstr "" "mantido, testes originais-x86 e correspondência de bytes de função " "compilados." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9460,7 +9468,7 @@ msgstr "" "DX-Ball sound-Pan investigation; deslocar horizontalmente em ecrãs mais " "pequenos" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9475,70 +9483,70 @@ msgstr "" "é verificado independentemente em relação ao x86 original em 3.205 casos e " "por repetição do compilador VC4.0 correspondente a 63 bytes." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Estudo de caso de reconstrução DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Copiar exemplo de pedido" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Seguir o cálculo da posição sonora esquerda/direita" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Copiar o excerto original da montagem" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Função de cópia de som-pan" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Copiar o conjunto completo da bandeja de som" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Copiar comando de análise DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Casa{ph1} / Vitrines" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA estudos de caso." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9547,17 +9555,17 @@ msgstr "" "Android, Jogos, Electron e um desafio CTF, com código, números e resultados " "verificados." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * análise APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Como um autenticador gera um código de login" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9568,22 +9576,22 @@ msgstr "" "Rastreie os métodos de geração com REA e, em seguida, mova um relógio de " "demonstração para ver por que o código muda a cada 30 segundos." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Leia o estudo de caso do Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Análise de programas de código de máquina" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Resolver um verificador de bandeira CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9594,22 +9602,22 @@ msgstr "" "verificação, transforme Máscaras e somas em equações e verifique o " "sinalizador resolvido com o programa original." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Leia o estudo de caso do CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Nativo * Reconstrução" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball cálculo da posição sonora esquerda/direita" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9621,22 +9629,22 @@ msgstr "" "numéricas conduzem a uma pequena função C, verificada em relação ao " "comportamento original e a todos os 63 bytes compilados." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Leia o estudo de caso DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * rastreio de características" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Como Notion copia texto e HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9648,22 +9656,22 @@ msgstr "" " veja como um pequeno marcador HTML mantém os dados de bloco ricos " "conectados a uma cópia." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Leia o estudo de caso Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 dos * reconstrução" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Como TH04 aponta um anel de balas" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9674,17 +9682,17 @@ msgstr "" "operações de multiplicação, divisão e coordenação com C++ legível e veja " "como elas produzem um anel voltado para o jogador." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Leia o estudo de caso TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Guias passo a passo" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9694,7 +9702,7 @@ msgstr "" "solicitação do navegador. Cada um começa com um objectivo imediato e um " "objectivo Concreto." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Leia os guias" @@ -9714,12 +9722,12 @@ msgstr "" " autenticador Android, DX-Ball , Notion , TH04 e um verificador de " "sinalizador DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -9728,25 +9736,25 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Casa{ph1} / {ph2}Vitrines{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Estudo de caso * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Como cópias Notion{ph0}texto e HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9756,12 +9764,12 @@ msgstr "" "através do processo de pré-carregamento e principal, até o gravador da área " "de transferência do Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Desktop 7.6.1 · JavaScript * REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "A ponte dentro do pacote de desktop do Notion" @@ -9773,7 +9781,7 @@ msgstr "A ponte dentro do pacote de desktop do Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9790,7 +9798,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9807,7 +9815,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9824,7 +9832,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9835,13 +9843,13 @@ msgstr "" "Electron escreve o texto fornecido e HTML.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Um canal une os dois lados: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9851,14 +9859,14 @@ msgstr "" "A resolução dos invólucros revela as chamadas Electron por trás desses " "nomes." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "Neste estudo de caso" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9866,7 +9874,7 @@ msgstr "{ph0}Siga a Ponte da área de transferência{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9874,19 +9882,19 @@ msgstr "{ph0}Manter a estrutura de um bloco{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Mais exemplos e fontes{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Para onde vai a operação de cópia?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9905,17 +9913,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Copiar" @@ -9926,7 +9934,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9937,7 +9945,7 @@ msgstr "" "área de transferência do sistema. Mostre o código em cada " "etapa.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9946,12 +9954,12 @@ msgstr "" "Um exemplo de prompt com o pacote de aplicativos locais do Notion disponível" " para o seu agente de codificação." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA descobre por onde começar a ler" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9962,13 +9970,13 @@ msgstr "" "chamada que envia uma solicitação IPC. Ambas as descobertas vêm com " "intervalos de origem no pacote reduzido:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA constatações intesti dois lugares a abrir" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9982,7 +9990,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9996,12 +10004,12 @@ msgstr "" "agente algo preciso para procurar no pacote principal. Os quatro trechos " "abaixo mostram a rota que liga." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Quatro pequenos pedaços de código" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -10010,13 +10018,13 @@ msgstr "" "Simplificado a partir do pacote JavaScript, com nomes de variáveis legíveis." " Os membros independentes são omitidos." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Comece na API exposta à página" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10026,13 +10034,13 @@ msgstr "" "Este membro fornece o nome do canal. A aplicação do {ph0} diz-nos como o " "pedido sai do processo da página." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Resolver o wrapper da pré-carga" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10043,14 +10051,14 @@ msgstr "" "resposta do Electron. Podemos agora procurar {ph0} do lado do processo " "principal." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Verificar como o recetor está registado" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10060,12 +10068,12 @@ msgstr "" "O processo principal utiliza outro invólucro. Sua {ph0} o método regista uma" " {ph1} receptor para esse canal." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Encontre a gravação e a verificação do remetente" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10076,13 +10084,13 @@ msgstr "" "dados fornecidos para a API da área de transferência do Electron. O canal e " "os dois wrappers resolvidos conectam o método exposto a esta chamada." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Como é que um bloco copiado mantém a sua estrutura?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10092,27 +10100,27 @@ msgstr "" "O editor web do Notion envia texto e HTML através de {ph0}. Ele mantém os " "dados do bloco localmente e coloca um ID no HTML copiado para conectá-los." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Links HTML para dados de bloco salvos" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Leia o ID HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Encontre o mesmo ID local" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Restaurar dados do bloco Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10122,7 +10130,7 @@ msgstr "" " quando os IDs correspondem; uma entrada obsoleta retorna apenas texto e " "HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10131,24 +10139,24 @@ msgstr "" "Ao colar, Notion procura o ID HTML e verifica-o em relação à cópia salva. Os" " IDs correspondentes restauram os dados do bloco." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Formato da área de transferência gravado a partir de ativos da web " "armazenados em cache em 13 de julho de 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Mais exemplos e fontes" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Outro exemplo: tabelas de remarcação" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10157,12 +10165,12 @@ msgstr "" "Notion analisa Markdown em dados de bloco. Este exemplo mostra como uma " "tabela se torna cabeçalho e linhas de dados." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Uma tabela através do analisador Markdown do Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10171,13 +10179,13 @@ msgstr "" "Saída gravada de um analisador Markdown extraído. A tabela torna-se linhas e" " células." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Outro caminho: a conexão SQLite offline" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10191,7 +10199,7 @@ msgstr "" " processo utilitário SQLite. Os lotes de declaração subsequentes e os " "resultados percorrem esse Porto." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10201,7 +10209,7 @@ msgstr "" "executado e por que o rastreamento apenas da solicitação IPC inicial perde a" " conversa posterior." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Fontes e como ler os excertos" @@ -10209,7 +10217,7 @@ msgstr "Fontes e como ler os excertos" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10227,7 +10235,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10244,7 +10252,7 @@ msgstr "" "sondas em vez de uma sessão de interface do usuário da área de trabalho " "capturada." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10259,7 +10267,7 @@ msgstr "" "Pacote." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10277,7 +10285,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10291,7 +10299,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10317,52 +10325,52 @@ msgstr "" "Electron, invólucros IPC e processo principal, com trechos de código curtos " "e uma olhada em seu Rico formato de área de transferência." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron estudo de caso" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Copiar o pedido de análise Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Copiar trecho de pré-carga Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Copiar Notion invocar o excerto do Invólucro" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Copiar o excerto do invólucro do manipulador Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Cópia Notion clipboard receiver excerto" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Restaurando dados ricos da área de transferência na pasta" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Voltar ao topo" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Ir para o conteúdo" @@ -10371,25 +10379,25 @@ msgstr "Ir para o conteúdo" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Casa{ph1} / {ph2}Vitrines{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Estudo de caso · Touhou 4: História da Lotus Land" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Reconstrução de TH04{ph0}padrões de bala." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10399,17 +10407,17 @@ msgstr "" "inspecionar a função DOS original e, em seguida, siga suas instruções em " "C++legível." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 · 16-bit DOS * C++ e montagem" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Ver a reconstrução TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Das instruções originais à fonte verificada" @@ -10420,7 +10428,7 @@ msgstr "Das instruções originais à fonte verificada" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10436,7 +10444,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10454,7 +10462,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10470,7 +10478,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10482,7 +10490,7 @@ msgstr "" " verificações do compilador gravadas cobrem o código de geração de " "marcadores que contém este auxiliar.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10491,14 +10499,14 @@ msgstr "" "REA retorna o código original e sua evidência de análise. O projeto TH04 " "fornece as verificações de origem e compilador mantidas." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "Neste estudo de caso" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10506,7 +10514,7 @@ msgstr "{ph0}O anel bala{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10514,7 +10522,7 @@ msgstr "{ph0}O que REA retorna{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10522,7 +10530,7 @@ msgstr "{ph0}Montagem Em C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10530,18 +10538,18 @@ msgstr "{ph0}Verificação da fonte{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}O projecto completo{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Como um anel visa o jogador" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10560,16 +10568,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}O seu agente de codificação" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Copiar" @@ -10580,7 +10588,7 @@ msgstr "Copiar" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10590,7 +10598,7 @@ msgstr "" "{ph0}›{ph1}{ph2}Use REA para descobrir como TH04 cria um anel de balas e o " "aponta para o jogador. Explique o cálculo e mostre o código.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10600,7 +10608,7 @@ msgstr "" " disponíveis localmente." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10614,7 +10622,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10624,12 +10632,12 @@ msgstr "" "Uma ilustração da matemática do ângulo recuperado para a contagem 16, " "direção do jogador 40 e rotação do Modelo 0. {ph0}Figura aberta{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "O modelo de disparo na fonte recuperada" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Elly's ring attack * trecho da fonte" @@ -10638,7 +10646,7 @@ msgstr "Elly's ring attack * trecho da fonte" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10648,13 +10656,13 @@ msgstr "" "Essas linhas selecionam o padrão antes da dificuldade e do ajuste de " "desempenho. {ph0}Leia a fonte do ataque{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "O que REA retorna" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10666,12 +10674,12 @@ msgstr "" " bala. REA retorna suas instruções, pseudocódigo e referências. Três partes" " desse resultado explicam o padrão." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Verifique a imagem do DOS antes de ler seu código" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10680,7 +10688,7 @@ msgstr "" "A verificação vincula o código carregado e os registros de realocação ao " "executável fornecido. O caminho acima é encurtado para exibição." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Leia o anel multiplicar e dividir" @@ -10688,7 +10696,7 @@ msgstr "Leia o anel multiplicar e dividir" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10700,12 +10708,12 @@ msgstr "" "então a divisão usa a contagem lida de {ph1}. Os nomes de origem mantidos " "nesse campo {ph2}. A sequência completa é apresentada abaixo." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Encontre onde o padrão gira em direção ao jogador" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10718,12 +10726,12 @@ msgstr "" "do anel. Os nomes de origem tornam esses endereços legíveis; REA permite que" " o agente verifique as operações originais por trás deles." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Da montagem ao C++legível" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10736,7 +10744,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10744,7 +10752,7 @@ msgstr "{ph0}01{ph1} Índice" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10752,7 +10760,7 @@ msgstr "{ph0}02{ph1} Espaço" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10760,7 +10768,7 @@ msgstr "{ph0}03{ph1} Objectivo" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10768,18 +10776,18 @@ msgstr "{ph0}04{ph1} Rodar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Loja" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * instruções originais de 16 bits" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "C++ legível · resumo do anel direcionado" @@ -10787,7 +10795,7 @@ msgstr "C++ legível · resumo do anel direcionado" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10801,7 +10809,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10817,7 +10825,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10832,7 +10840,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10847,7 +10855,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10861,7 +10869,7 @@ msgstr "" "byte faz. A fonte circundante também converte este ângulo e velocidade em " "velocidade." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10872,7 +10880,7 @@ msgstr "" "armazenamento final. O C++ acima é um resumo legível. As verificações do " "compilador abaixo se aplicam à fonte mantida no projeto vinculado." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Leia o anel mantido e aim fonte" @@ -10889,7 +10897,7 @@ msgstr "Leia o anel mantido e aim fonte" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10899,12 +10907,12 @@ msgstr "" "{ph0}Anel macro{ph1} · {ph2}Alvo e fonte de velocidade{ph3} · " "{ph4}Representação do ângulo{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Verificação da fonte mantida" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10914,12 +10922,12 @@ msgstr "" "marcadores, incluindo este auxiliar, com a sua cadeia de ferramentas Turbo " "C++ 4.0 j fixada." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2.139 bytes correspondentes" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10928,12 +10936,12 @@ msgstr "" "O código compilado de geração de marcadores corresponde a uma seção de 2.139" " bytes do executável original." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Duas construções limpas" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10946,7 +10954,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." @@ -10954,59 +10962,59 @@ msgstr "" "Gravado em 3 de outubro de 2026. {ph0}Leia as verificações do " "compilador{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Identidade-alvo e âmbito de análise" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Alvo Original" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156.258 bytes, dos MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Entrada auxiliar" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} na imagem carregada de REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Deslocamento do ficheiro Original" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, devolvido por {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Inspecção do Código registado" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 de outubro de 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11017,7 +11025,7 @@ msgstr "" " mapa e a deslocalização sobreposta." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11032,7 +11040,7 @@ msgstr "" " instruções seleccionadas acima situam-se nesses intervalos comunicados." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11049,7 +11057,7 @@ msgstr "" "fixada por seu manifesto de repositório, com proveniência independente de " "despejo intocado ainda aberta." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11060,12 +11068,12 @@ msgstr "" "temporização e o comportamento do hardware PC-98 têm verificações de tempo " "de execução separadas no projecto de reconstrução." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "A reconstrução completa do TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11078,7 +11086,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11090,7 +11098,7 @@ msgstr "{ph0}Explore o repositório TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11106,7 +11114,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11122,7 +11130,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11148,22 +11156,22 @@ msgstr "" "montagem e recuperou C++ para ver como um anel de balas é espaçado e apontou" " para o jogador." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Nesta página" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "Estudo de caso com padrão de marcadores TH04" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Copiar o prompt de exemplo TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11171,7 +11179,7 @@ msgstr "" "TH04 anéis de bala fixos e apontados; deslocar horizontalmente em ecrãs mais" " pequenos" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11184,27 +11192,27 @@ msgstr "" "quantidade; o primeiro marcador destacado aponta para o jogador. Ambos " "mantêm um espaçamento de 16 unidades de ângulo, ou 22,5 graus." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Copiar modelo de disparo TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Siga o cálculo do anel direcionado TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Copiar o excerto do conjunto TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Cópia legível cálculo do anel destinado" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Voltar ao topo" @@ -11314,7 +11322,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Velocidade fixa: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11324,7 +11332,7 @@ msgstr "" "verificação do jogo original controlada quando arredondados para três casas " "decimais." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11694,591 +11702,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Mesmo espaçamento: 256 16 = 16 unidades angulares = 22,5" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Casos práticos" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Começar" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Guias" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Código-fonte" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Licença MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Participe da comunidade" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Siga no X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * fonte de script seleccionada" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Código-fonte" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Saída esperada do formatador" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Instruções" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Chamador" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Constantes" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Função C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Botão" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API de pré-carregamento" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Ficheiro CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "O seu clique" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Pedido capturado" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Script de exportação" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA resultado * resumo.excerto do ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "Trecho de instrução REA * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "Trecho do chamador REA * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "Resultados do byte REA * interpretados como duplos little-endian" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Excerto c * recuperado" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Veja como o REA funciona ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Apresenta →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Definições seleccionadas a partir do script inspeccionado" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Resumo legível do manipulador %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * instruções originais selecionadas" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "IDs do operador * fonte da Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Siga @reatools em X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agente REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA extraterritorial * resultados seleccionados" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA7AGENTE * métodos e chamadores" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * java descompilado selecionado" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Resumo legível * interpretação do agente" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * gerateotp, corpo completo" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Baixar Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Baixar Android analysis provider" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agente REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA extraterritorial * resultados seleccionados" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA7 agente * instruções seleccionadas" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agente REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA7agente * sétima entrada" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Executável Original * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Baixe o desafio original" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Baixar solver" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA resultado * excerto de pseudocódigo" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agente REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA7 agente * excerto de instruções" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA extraterritorial * excerto do autor da chamada" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agente REA * dois {ph0} pedidos" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Resultados do byte REA * descodificados como duplos" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Comece com o seu próprio alvo" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Gerar código" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Regra recuperada" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Relógio ajustável" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Binário" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Código de verificação" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Equações" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Correcto!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Executável" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Conclusões do REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Recuperado C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Validação" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Aplicação empacotada" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "API exposta" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Invólucros IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Área de transferência" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Código DOS Original" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Instruções REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Cálculo do ângulo" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Anel bala" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "API da página exposta" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Chamada IPC do renderizador" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Enviado para a área de transferência do sistema" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Salvo localmente por Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Entrada de redução" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Saída do analisador estruturado * excerto" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Analise seu próprio aplicativo" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agente REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA extraterritorial * campos seleccionados" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agente REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA7 agente * excerto de instruções" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Resultado da mesma função * trecho aim" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "C++mantido correspondente" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Macro do anel * ramificação TH04, excerto" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Ângulo e velocidade * excerto da fonte" @@ -12311,7 +12327,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12328,7 +12344,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12349,7 +12365,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12370,7 +12386,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12389,7 +12405,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12408,7 +12424,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12419,14 +12435,14 @@ msgstr "" "mim.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Reconstrução * {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12437,7 +12453,7 @@ msgstr "" " codificação e revise as alterações propostas." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12446,7 +12462,7 @@ msgstr "Um exemplo fornecido * {ph0} e npm * seu agente de codificação" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12465,7 +12481,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12481,7 +12497,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12500,7 +12516,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12511,7 +12527,7 @@ msgstr "" "{ph7} e escreve o ficheiro.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12526,7 +12542,7 @@ msgstr "{ph0} * linhas 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12539,7 +12555,7 @@ msgstr "" "Mostrar a previsão e o resultado real.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12550,7 +12566,7 @@ msgstr "" "verifica o formatador diretamente com {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12558,7 +12574,7 @@ msgstr "{ph0} · CSV formatador" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12567,7 +12583,7 @@ msgstr "" "Você vai precisar {ph0} 22 (22.19+), 24 (24.11+) ou 26+. npm vem com {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12575,7 +12591,7 @@ msgstr "Não tem {ph0}, ou não tem certeza?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12588,7 +12604,7 @@ msgstr "" "instale {ph1} 24 LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12602,7 +12618,7 @@ msgstr "{ph0} * exemplo de excerto da fonte" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12612,9 +12628,9 @@ msgstr "" "{ph0}Abra o exemplo{ph1} · {ph2}Baixar {ph3}{ph4} · {ph5}Baixar {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12622,7 +12638,7 @@ msgstr "{ph0} * fonte de exemplo" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12637,7 +12653,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12650,7 +12666,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12663,7 +12679,7 @@ msgstr "Por exemplo: {ph0}por que a calculadora retorna 220 para {ph1}?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12674,7 +12690,7 @@ msgstr "" "{ph3} dão 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12683,7 +12699,7 @@ msgstr "REA * carregado {ph0} * linhas seleccionadas" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12701,7 +12717,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12720,7 +12736,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12733,28 +12749,28 @@ msgstr "" "demonstração em que eu possa alterar o horário.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view / {ph0} * membro da API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view / {ph0} * IPC helper" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "principal/{ph0} * handler helper" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12764,12 +12780,1420 @@ msgstr "principal/{ph0} * receptor da área de transferência" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Começar {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Alternar para o modo claro" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Alternar para o modo escuro" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Para examinar os corpos das requisições e respostas HTTP, use {ph0}Fiddler " +"Everywhere: capturas SAZ, MCP e habilidades públicas{ph1}. Exporte SAZ ou " +"HAR 1.2 para obter Evidence das capturas no REA offline, ou conecte o " +"servidor MCP do Everywhere para inspecionar o tráfego capturado com seu " +"agente." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Modelos especializados{ph0}Ensaio" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "A engenharia reversa precisa de um modelo maior?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"O que a reconstrução de Touhou sugere sobre modelos gerais, modelos " +"especializados e o aprendizado com o retorno do compilador." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Por N0zoM1z0 · 13 de outubro de 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Ir para o conteúdo" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" +"{ph0}Página inicial{ph1} / {ph2}Blog{ph3} / Modelos e engenharia reversa" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Ensaio" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "A engenharia reversa precisa de um modelo maior?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Por N0zoM1z0 · 13 de outubro de 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Pontos principais" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}A capacidade do modelo afeta quais hipóteses um agente de IA pode " +"propor.{ph1} Sessões posteriores resolveram problemas que trabalhos " +"anteriores haviam deixado sem solução." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Um compilador familiar oferece padrões concretos para um modelo " +"especializado aprender.{ph1} Algumas correspondências exatas de código de " +"máquina dependem de padrões de código-fonte específicos e reutilizáveis." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Inclua o conhecimento do repositório em uma comparação justa.{ph1} Um " +"modelo menor com boa recuperação de conhecimento pode já ter informações " +"suficientes para progredir." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Treine o modelo para escolher o próximo experimento útil e teste seu " +"verificador.{ph1} O feedback é útil apenas na medida em que o verificador " +"verifica as coisas certas." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Avalie os resultados verificados da reconstrução juntamente com o tempo" +" e o custo.{ph1} É isso que quero medir para o fluxo de trabalho completo do" +" agente de IA." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "Neste artigo" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}O que os modelos mais capazes mudaram{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Por que se especializar?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Onde essa experiência deve ser armazenada?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Aprendendo o próximo experimento útil{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Engenharia reversa e aprendizagem por reforço{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Quando o verificador está errado{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Uma comparação que vale a pena fazer{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Que tipo de agente de IA isso sugere?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "O que os modelos mais capazes mudaram" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Desde agosto de 2026 venho explorando o quanto de engenharia reversa um " +"agente pode realizar com acesso a um programa e uma forma de verificar seu " +"funcionamento. A maior parte da minha experiência vem da reconstrução de " +"jogos, especialmente Touhou. Como mudei de modelo, os repositórios " +"mantiveram um registro do que cada sessão conseguiu recuperar." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Grande parte desse trabalho visa a reconstrução exata: compilamos a fonte " +"mantida sob um conjunto de ferramentas histórico com versões fixas e " +"verificamos se ela reproduz a função alvo. Quando um modelo posterior é bem-" +"sucedido onde o trabalho anterior estagnou, as mudanças na origem mostram o " +"que tornou esse progresso possível." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "As variáveis temporárias precisavam de vidas sobrepostas" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Grande parte da lógica da função de ataque TH09 já havia sido reconstruída, " +"mas o compilador ainda armazenava resultados temporários de maneira " +"diferente do original. O problema restante era quanto tempo esses resultados" +" precisavam para permanecer vivos e quando seu armazenamento poderia ser " +"reutilizado." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Um {ph0}GPT-6-Sol registro de sessão{ph1} relatou essa incompatibilidade " +"após testar vários arranjos comuns de código-fonte. Quando {ph2}GPT-6.1-Sol " +"examinou o problema novamente{ph3}, propôs uma hipótese útil sobre o tempo " +"de vida dessas variáveis ​​temporárias." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"A função produziu resultados temporários e os copiou em posições de " +"animação. Em C++, um resultado temporário permanece ativo até que a " +"expressão que o utiliza termine. O agrupamento das operações reais em uma " +"expressão manteve esses resultados vivos juntos, de modo que o compilador " +"não pudesse mais reutilizar o mesmo armazenamento para todos eles." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Um resultado ainda compartilha o armazenamento com um valor usado " +"posteriormente para verificações de colisão. Dar a esse valor seu próprio " +"tempo de vida resolveu a sobreposição restante. Após vários experimentos " +"direcionados, {ph0}uma recompilação limpa da fonte confirmou que a função " +"completa correspondia a{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Estou interessado em saber como a descoberta e os testes se apoiaram. A " +"hipótese sobre a vida útil dos objetos temporários deu ao agente de IA uma " +"nova direção. O feedback do compilador ajudou a refinar essa hipótese em um " +"arranjo de código-fonte correspondente." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Um gráfico de fluxo de controle diferente" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Uma segunda função TH09 mostra por que essa nova direção pode ser " +"importante. Aqui, o obstáculo foi a forma como diversas filiais " +"compartilharam seu trabalho final. O trabalho anterior de " +"{ph0}GPT-6.1-Sol{ph1} fez com que partes da função correspondessem, mas as " +"ramificações ainda se uniram de maneira diferente do original." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra alterou o gráfico de fluxo de controle circundante{ph1}. Os" +" principais caminhos levaram agora a uma atualização e retorno final " +"partilhado. Nessa estrutura de origem, o compilador combinou as ramificações" +" da mesma forma que o original. A função completa correspondeu e uma " +"{ph2}verificação de reconstrução separada confirmou isso{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Mudar a representação abriu um espaço de pesquisa mais produtivo.{ph1} " +"Ambos os casos me dão um motivo para levar a sério a capacidade geral do " +"modelo: um agente pode continuar tentando variações locais por um longo " +"tempo antes de encontrar uma maneira melhor de expressar o trabalho " +"circundante." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"As sessões posteriores também herdaram o código anterior e os experimentos " +"fracassados já registrados. Esse trabalho acumulado fazia parte da vantagem " +"delas. O histórico permite examinar as descobertas e suas verificações; uma " +"comparação controlada ajudaria a separar o efeito do modelo do efeito da " +"experiência herdada." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"É isso que torna a questão interessante para mim. Algum progresso veio da " +"descoberta de uma nova representação. Grande parte do trabalho restante " +"envolveu testar diferentes arranjos de código-fonte em um compilador " +"familiar. Quanto disso requer ampla capacidade de raciocínio? Quanto um " +"modelo poderia aprender trabalhando repetidamente com esse compilador e " +"código?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Por que um modelo especializado de IA pode funcionar bem?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou nos dá uma razão concreta para esperar que essa experiência ajude. " +"Grande parte do código do jogo vem do mesmo autor, ZUN, portanto, hábitos " +"recorrentes são uma suposição inicial razoável. Os repositórios apoiam isso " +"com exemplos úteis: loops relacionados e arranjos auxiliares forneceram " +"hipóteses em todos os jogos." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Esses padrões de origem tornam-se mais específicos quando incluímos o " +"compilador. Sob uma determinada versão e conjunto de opções, pequenas " +"alterações na fonte podem produzir diferenças repetíveis no código de " +"máquina. Algumas dessas diferenças são surpreendentemente obscuras." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Em TH095, por exemplo, {ph0}até mesmo o nome de uma variável local pode " +"afetar o local onde VC7.1 a armazenou{ph1}. Mover sua declaração não " +"resolveu o layout de armazenamento. No entanto, uma função anterior revelou " +"um padrão de nomenclatura que afetou a escolha do compilador. Isso sugeriu " +"uma hipótese mais promissora para {ph2}reconstruir {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"A reutilização desse padrão para a variável de tamanho de arquivo produziu o" +" layout necessário sem adicionar armazenamento. A função completa então " +"correspondeu." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Este é um detalhe muito específico que um modelo de IA de uso geral pode não" +" saber quando encontra o problema pela primeira vez. Um modelo especializado" +" para este compilador poderia ver muitos desses casos e aprender quais " +"variações do código-fonte valem a pena testar primeiro." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"A oportunidade é especialmente clara em problemas de correspondência final " +"onde já entendemos o comportamento. Estamos então perguntando qual arranjo " +"comum de código-fonte este compilador transforma nas instruções observadas. " +"A especialização poderia ajudar o modelo a propor essas formas de forma mais" +" eficiente, enquanto o alvo ainda determina quais hipóteses sobreviverão." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Padrões úteis devem manter seu contexto. TH08 usa uma versão Visual C++ " +"anterior a TH095 e TH09. TH04 usa um compilador diferente da era DOS. Sua " +"{ph0}reconstrução do código do jogador{ph1} precisava de diferentes " +"hipóteses sobre os padrões do código-fonte e como o código compilado era " +"vinculado a um executável. Ter o mesmo autor nos dá uma expectativa inicial," +" mas cada alvo nos diz se se aplica. Um modelo especializado precisaria " +"distinguir esses contextos." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Onde essa experiência deve ser armazenada?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Antes de decidir ensinar esses padrões por meio do treinamento de modelos, " +"eu examinaria o conhecimento que já mantemos no repositório. No {ph0}ensaio " +"anterior{ph1}, escrevi sobre isso se tornar a memória de trabalho do " +"projeto. Essa memória inclui lições de compilador, juntamente com a fonte e " +"os experimentos fracassados ​​que os tornaram úteis." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Ao recuperar esse registro, um agente pode começar com um resultado " +"conhecido e inspecionar como o alcançamos. Também pode evitar alternativas " +"que já falharam no mesmo contexto. O ponto inicial melhora sem alterar os " +"parâmetros treinados do modelo." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Ao reconstruir a função de TH09 para criar inimigos, uma {ph0}sessão " +"GPT-6-Luna-max{ph1} tirou uma hipótese do código-fonte TH08 relacionado. " +"Esse código anterior sugeria como organizar o loop e lidar com falhas dentro" +" dele. As próprias evidências de TH09 forneceram detalhes específicos do " +"jogo. As reconstruções da fonte confirmaram que a função completa " +"correspondia." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"O modelo não sabia daquela peculiaridade do compilador\" e \"o modelo" +" não pôde usá-lo\" são problemas diferentes.{ph1} A recuperação pode " +"resolver o primeiro, mas transformar esse fato em um candidato útil ainda dá" +" trabalho. E se o código-fonte candidato falhar, o modelo deverá decidir o " +"que o resultado significa para sua próxima tentativa. Conhecer o padrão " +"relevante é apenas o começo desse processo." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Por esse motivo, eu incluiria um modelo menor de IA de uso geral com boa " +"recuperação em qualquer comparação. Fornecer a mesma biblioteca de " +"experiência nos ajudaria a identificar o que o treinamento agrega: melhor " +"geração de candidatos, melhores decisões após feedback ou ambos." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Aprendendo o próximo experimento útil" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Essas decisões após feedback são o que eu mais gostaria de estudar. Na " +"reconstrução agente, o modelo propõe uma explicação e a testa em relação ao " +"programa. Mesmo quando o código-fonte candidato falha, o resultado pode " +"restringir as possibilidades restantes e sugerir um próximo experimento mais" +" útil." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Considere novamente o exemplo dos resultados temporários. Sua fonte final " +"mostra o arranjo que funcionou, mas o caminho para essa fonte contém mais " +"informações. Cada um dos experimentos a seguir ajudou a identificar o que " +"ainda precisava ser mudado." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Experimentar" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "O que seu resultado nos ensinou" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Tente uma maneira diferente de copiar os resultados" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "O código de cópia muda, mas a função ainda é diferente." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Use os valores retornados diretamente" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"A cópia segue o padrão original, mas o armazenamento temporário ainda é " +"diferente." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Mantenha todas as variáveis temporárias válidas ao mesmo tempo" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Eles obtêm armazenamento separado, mas ainda se sobrepõe a um valor usado " +"posteriormente para verificações de colisão." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Mantenha o valor de verificação de colisão separado" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "Uma recompilação limpa da fonte confirma a correspondência completa." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Experimentos selecionados da reconstrução da função de ataque acima, " +"agrupados pelo que nos ensinaram." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Um registro de treinamento que mantenha essa sequência pode ensinar mais do " +"que apenas a fonte final. Ele conecta cada mudança proposta a um resultado " +"observado e à próxima decisão. Manter variações ineficazes também é " +"importante: elas informam a um agente posterior quais hipóteses já foram " +"testadas naquele contexto." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Eu gostaria que o modelo aprendesse como usar o feedback.{ph1} Um " +"resultado neutro é um motivo para reconsiderar a variação; uma " +"incompatibilidade alterada pode apontar para outra causa. Quando as edições " +"locais deixarem de ser informativas, o agente deverá ser capaz de revisitar " +"a representação da fonte ou inspecionar as evidências novamente." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Aprender a fazer essas escolhas requer autonomia. Às vezes, o próximo passo " +"útil é inspecionar outro chamador em vez de compilar outra edição. Uma " +"sequência rígida de reescritas necessárias eliminaria essa escolha, " +"juntamente com parte do comportamento que queremos que o modelo aprenda." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "" +"Por que a engenharia reversa é interessante para aprendizagem por reforço" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Uma reconstrução com escopo definido oferece um ambiente prático para " +"estudar essas escolhas. Com as versões do alvo e do compilador fixadas, " +"muitos experimentos de código-fonte dão feedback rápido e repetível. O " +"agente pode compilar um candidato, examinar as diferenças e escolher o " +"próximo passo." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"A aprendizagem por reforço poderia treinar esse processo de tomada de " +"decisão por meio do feedback que recebe. Um candidato aceito por meio de uma" +" verificação definida nos dá um resultado concreto, enquanto a sequência de " +"tentativas nos permite observar quanto trabalho foi necessário para alcançá-" +"lo." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Já existem pesquisas apoiando essa direção. {ph0}LLM4Decompile{ph1} estuda " +"modelos especializados para descompilação. {ph2}AutoDecompiler{ph3} treina o" +" refinamento em várias rodadas usando feedback do compilador e de execução. " +"Seus estudos se concentram na recuperação funcional. Para este trabalho, eu " +"os usaria como ponto de partida para a tarefa relacionada de encontrar uma " +"fonte que corresponda à saída de um compilador histórico." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Porém, para alcançar uma tarefa tão bem definida, talvez precisemos primeiro" +" estabelecer quais recursos uma função possui ou criar uma nova forma de " +"observar o comportamento do programa durante a execução. Em TH08, por " +"exemplo, uma {ph0}diferença de colisão levou de volta à forma como o " +"programa original lidava com cálculos de ponto flutuante{ph1}. Antes que o " +"agente pudesse testar uma correção útil, ele precisava decidir o que medir." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Isto sugere outro papel para um modelo amplamente capaz: em primeiro lugar, " +"ajudar a tornar o problema verificável. Uma vez que essa verificação exista," +" podemos investigar até onde uma política de pesquisa aprendida pode chegar " +"com ela." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Quando o verificador está errado" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Quando usamos uma verificação no treinamento, sua cobertura passa a fazer " +"parte do ambiente de aprendizagem. Chamo essa referência ou verificador de " +"oracle. Mesmo uma resposta repetível precisa ser entendida pelos aspectos " +"que ela realmente verifica." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 mostrou o quanto pode se esconder fora dessa cobertura. Algumas funções" +" reconstruídas passaram em suas comparações exatas com constantes flutuantes" +" erradas. O comparador ajustou os endereços realocados antes de verificar as" +" instruções, mas verificou os valores por trás desses endereços somente " +"quando eles foram explicitamente registrados para verificação. Outras " +"referências literais poderiam passar sem que seus valores fossem examinados." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Para resolver essa lacuna, uma {ph0}auditoria mais ampla{ph1} encontrou " +"constantes incorretas em funções que já haviam passado na verificação. Em um" +" cálculo, o código-fonte reconstruído adicionou {ph2}, enquanto o original " +"adicionou {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Um modelo recompensado pela verificação antiga poderia aprender a " +"produzir uma reconstrução incorreta.{ph1} Não treinamos um modelo RL usando " +"esse verificador. A falha que observamos estava na própria verificação. Mas " +"se usássemos isso como recompensa, o mesmo ponto cego passaria a fazer parte" +" do ambiente de aprendizagem." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Um teste funcional pode ter um ponto cego semelhante. {ph0}Pesquisas usando " +"difusão diferencial em descompiladores LLM{ph1} encontraram diferenças " +"comportamentais fora dos testes fornecidos. Portanto, precisamos entender um" +" teste aprovado em termos dos casos que ele exerce. Da mesma forma, uma " +"correspondência de instrução deve ser entendida em termos dos bytes e dos " +"dados que ela verifica." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Antes de usar qualquer tipo de verificação como recompensa, eu testaria com " +"resultados deliberadamente incorretos. Eu também manteria a aceitação final " +"separada do código-fonte que o agente de IA pode editar. O modelo deve " +"passar na verificação reconstruindo o programa corretamente. Caso contrário," +" simplesmente copiar uma matriz de bytes do destino poderia enganar um " +"sistema de pontuação ingênuo sem recuperar o código-fonte útil." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Aprimorar o aluno e melhorar seu verificador pertencem ao mesmo " +"problema de pesquisa.{ph1} À medida que o aluno melhora na otimização do " +"feedback que lhe damos, compreender esse feedback também se torna mais " +"importante." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Uma comparação que vale a pena fazer" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Com essas verificações implementadas, eu iniciaria a comparação em uma " +"família de tarefas fixa VC7.1. Primeiro, eu estabeleceria linhas de base " +"para um modelo forte de IA de uso geral e um modelo menor. Adicionar " +"conhecimento do repositório ao modelo menor mostraria quais mudanças na " +"recuperação. A partir daí, a especialização supervisionada e uma versão " +"treinada em RL nos permitiriam examinar o que o treinamento acrescenta." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Para tornar essas comparações informativas, cada modelo receberia as mesmas " +"evidências e ferramentas alvo. Para comparações específicas de treinamento, " +"eu também manteria o modelo base e o conhecimento disponível fixos. Testes " +"repetidos ajudariam a distinguir uma estratégia de busca confiável de uma " +"solução candidata que tivesse sucesso por acaso." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Eu separaria então duas condições iniciais: reconstruir uma função a partir " +"de suas instruções e fechar as últimas diferenças na fonte mantida. Um " +"modelo de IA especializado pode ser excelente na segunda tarefa, enquanto um" +" modelo de IA de uso geral faz grande parte do trabalho necessário para " +"alcançá-la. Medi-los separadamente revelaria essa divisão de trabalho." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Ambas as tarefas precisam de exemplos de teste excluídos do treinamento e " +"recuperação. Jogos Touhou relacionados compartilham o código do mecanismo. " +"Excluir um jogo do treinamento ainda poderia deixar funções quase idênticas " +"no conjunto de treinamento. Em vez disso, eu excluiria grupos inteiros de " +"código-fonte relacionado e manteria suas respostas verificadas fora dos " +"dados de treinamento e da biblioteca de recuperação." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Para estes exemplos, o resultado seria correspondências completas e " +"verificadas de forma independente. Orçamentos iguais para propostas de " +"candidatos ou tentativas de compilação ajudariam a comparar a qualidade da " +"pesquisa. Medir o tempo e o custo totais, incluindo a compilação, mostraria " +"se essa qualidade produz um fluxo de trabalho eficiente. Os custos de " +"formação devem ser medidos separadamente." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Ambas as medidas são importantes. Uma proposta barata pode levar a um fluxo " +"de trabalho caro se causar mais compilações que não fornecem informações " +"úteis. Por outro lado, um modelo mais lento pode ser mais econômico se " +"encontrar uma experiência útil mais cedo. A comparação deve incluir esses " +"custos." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"A contagem dos resultados aceitos também mantém o progresso intermediário em" +" perspectiva. Um TH09 {ph0}candidato para salvar repetição{ph1} parecia " +"promissor porque a função compilada tinha o tamanho esperado, mas uma " +"comparação completa ainda encontrou diferenças substanciais. Mudanças na " +"forma como o compilador organiza as instruções também podem fazer o " +"candidato parecer mais próximo do alvo, sem resolver o problema subjacente. " +"Esses diagnósticos podem orientar o próximo experimento, mas eu validaria " +"qualquer recompensa por “chegar mais perto” em relação à verificação de " +"aceitação total." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Eu estaria interessado no padrão desses resultados. Se um modelo de IA " +"especializado funciona bem em uma família de compiladores familiar, essa " +"vantagem sobreviverá a uma mudança no conjunto de ferramentas? E uma vez que" +" ambos os modelos de IA tenham uma boa recuperação, quanto o treinamento " +"ainda acrescenta? As respostas nos ajudariam a decidir onde cada tipo de " +"modelo é mais útil." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Que tipo de agente de IA isso sugere?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Se os modelos acabarem por ajudar em diferentes fases, um acordo útil poderá" +" ser um agente amplo com acesso a um modelo de IA especializado. Depois que " +"uma tarefa se torna uma pesquisa familiar do compilador, ela pode solicitar " +"candidatos ao modelo de IA especializado. Se os resultados deixarem de fazer" +" sentido, o agente mais amplo poderá retornar à evidência alvo ou investigar" +" a própria medição." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"Nesse arranjo, a especialização torna-se uma ferramenta que o agente pode " +"escolher à medida que a investigação se desenvolve. O agente mantém a " +"liberdade de mudar a direção que tornou possíveis os avanços anteriores." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Isto decorre naturalmente da mudança industrial que descrevi no ensaio " +"anterior. Ser capaz de realizar muito mais experimentos muda a forma como " +"organizamos o trabalho. Também nos dá uma razão para perguntar quais " +"decisões necessitam de um julgamento amplo e quais melhoram através da " +"experiência repetida com uma determinada arte." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Por enquanto, o modelo geral mais forte conquistou seu lugar no meu trabalho" +" ao resolver problemas que eu havia deixado em aberto. Esses sucessos me " +"fazem querer estudar o processo: quanto dependia da amplitude do modelo e " +"quanto poderia ser feito por um modelo treinado especificamente para esse " +"tipo de reconstrução?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Os repositórios nos fornecem uma maneira de testar a pergunta.{ph1} " +"Gostaria de usar esse registro para construir a comparação e ver o que " +"aprendemos." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Evidências e atribuição de modelo" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Os exemplos descrevem comparações históricas em nível de função registradas " +"nos commits vinculados. As verificações de tempo de execução de todo o jogo " +"são marcos separados. Os registros de origem e correspondentes foram " +"revisados em 13 de outubro de 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"O rótulo TH09 {ph0} significa GPT-6-Astra. O modelo associado a {ph1} mudou " +"ao longo do tempo, de modo que o rótulo por si só não consegue identificar o" +" modelo usado em uma execução específica. Nomes de modelos explícitos nos " +"outros commits citados fornecem a atribuição registrada. Esses históricos " +"não incluem medições consistentes de custo ou esforço para cada execução." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 tempos de vida do objeto temporário:{ph1} a {ph2}revisão de " +"contexto anterior{ph3} e a {ph4}reconstrução completa verificada por uma " +"recompilação limpa da origem{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front retorno de chamada:{ph1} {ph2}regiões de diagnóstico que não" +" correspondem{ph3}, {ph4}novo gráfico de fluxo de controle de Astra{ph5} e " +"sua {ph6}verificação de recompilação aceita{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Conhecimento do compilador:{ph1} {ph2}TH095 reutilização do " +"comportamento do bloco de identificadores{ph3}, {ph4}TH04 código-fonte do " +"jogador e ordem do vinculador{ph5} e {ph6}reconstrução completa de Luna da " +"função de criação de inimigo de TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Verificações e diagnósticos:{ph1} {ph2}TH08 auditoria de constante de " +"ponto flutuante{ph3}, {ph4}TH08 investigação numérica{ph5} e {ph6}TH09 " +"reconstrução para salvar replay{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"As comparações propostas de modelos especializados e treinamento RL são " +"experimentos futuros. As histórias do projeto os motivam. Nenhum modelo " +"especializado treinado foi avaliado para este ensaio." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "A engenharia reversa precisa de um modelo maior? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"O que a reconstrução Touhou me ensinou sobre modelos gerais, modelos " +"especializados e como aprender a propor melhores hipóteses a partir do " +"feedback do compilador." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Nesta página" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Modelos e ensaio de engenharia reversa" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Experimentos de reconstrução selecionados" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Voltar ao topo" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"As {ph0}notas detalhadas de evidências{ph1} incluem as comparações " +"registradas e o contexto dos experimentos." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Por N0zoM1z0 · 13 de outubro de 2026 · Rascunho para revisão" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Guia de instalação" diff --git a/website/locales/ru/messages.po b/website/locales/ru/messages.po index bb6945210..32b973c33 100644 --- a/website/locales/ru/messages.po +++ b/website/locales/ru/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Главная{ph1} страница / Блог" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Блог." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Мысли о реверс-инжиниринге." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Реконструкция игры{ph0}Сочинение" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Промышленная революция в области реверс-инжиниринга" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "Чему меня научило руководство по обновлению и реконструкции TH08, TH095 и " "TH04 об агентах, проверке и знаниях, которые используются в разных проектах." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Прочтите статью" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Автор: N0zoM1z0 · 10 октября 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "REA и агентами искусственного интеллекта." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -135,112 +138,117 @@ msgstr "" "REA — Узнайте, как работает программное обеспечение. Обратное проектирование" " с помощью вашего программиста." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Главная REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Основная навигация" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA на GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Присоединиться к REA в Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Подписаться на REA в X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -249,35 +257,35 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Главная{ph1} страница / {ph2}Блог{ph3} / Реконструкция Тохоу" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Эссе · Реконструкция Тохоу" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Промышленная революция в области реверс-инжиниринга." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Автор: N0zoM1z0 · 10 октября 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Главное" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -290,7 +298,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -304,7 +312,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -317,7 +325,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -330,7 +338,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -340,65 +348,65 @@ msgstr "" "{ph0}Мы находимся на заре промышленной революции в RE.{ph1} Методы все еще " "разрабатываются. Нам еще многое предстоит изучить." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Как опыт соединяет" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Управление{ph1} персоналом · Цель и критерии приемлемости" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Самостоятельность" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Агент" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Выберите эксперимент.{ph0}Выдвиньте гипотезу." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Проверка" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Эталон проверки" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Тестирование на{ph0}конкретные ссылки." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Репозиторий" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Рабочая память" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -407,7 +415,7 @@ msgstr "Кодекс, доказательства,{ph0}проверки и ур #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -416,26 +424,26 @@ msgstr "Несоответствие{ph0}{ph1}Пересмотрите гипо #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Лучше{ph0}{ph1}отправная точка{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Повторное использование" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Пройти{ph1} · Сохранить результат и его доказательства" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -444,14 +452,14 @@ msgstr "" "Каждый следующий проект становится лучшей отправной точкой. Это включает в " "себя исправление проверок, когда мы обнаруживаем пробелы." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "В этой статье" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -459,7 +467,7 @@ msgstr "{ph0}Август 2026 года{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -467,7 +475,7 @@ msgstr "{ph0} TH08 : продолжение{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -475,7 +483,7 @@ msgstr "{ph0}Два подхода{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -483,7 +491,7 @@ msgstr "{ph0} TH095 : рецептура{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -491,7 +499,7 @@ msgstr "{ph0} TH04 : различные архитектуры{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -499,7 +507,7 @@ msgstr "{ph0}От точного к удобочитаемому{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -507,18 +515,18 @@ msgstr "{ph0}Промышленный сдвиг{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Что становится возможным{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Что изменилось в августе 2026 года" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -533,7 +541,7 @@ msgstr "" "времени на следующую функцию. Это также означало, что я держал в голове все " "более объемную картину." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -547,7 +555,7 @@ msgstr "" "полезен в других областях, но в каждой области необходимо установить, что " "можно проверить с помощью надежных ссылок." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -560,7 +568,7 @@ msgstr "" "программе и обычным инструментам разработки. Touhou reconstruction " "предоставила мне значительный проект, в котором я мог это выяснить." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -578,7 +586,7 @@ msgstr "" "уделять больше внимания направлению проекта и тому, заслуживают ли доверия " "его проверки." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -589,7 +597,7 @@ msgstr "" "том, что останется после текущего проекта. Будет ли в следующей игре полезно" " все, что мы только что узнали?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08 : опора на человеческий труд" @@ -598,7 +606,7 @@ msgstr "TH08 : опора на человеческий труд" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -612,7 +620,7 @@ msgstr "" "существенную основу. Это пришло вместе со знанием конструкции и историей " "вклада, которую я сохранил в продолжении." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -624,7 +632,7 @@ msgstr "" " журнале были зарегистрированы исходные данные для всех 1107 " "идентифицированных игровых функций." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -636,7 +644,7 @@ msgstr "" "веб-версия. 64-разрядная версия Linux для собственной версии вышла 30 " "августа." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -652,7 +660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -670,12 +678,12 @@ msgstr "" "ожидаемого состояния. Агент предлагает объяснение и проверяет его; " "несоответствие дает ему возможность исследовать что-то конкретное." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Точное совпадение с неправильной константой" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -687,7 +695,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -700,7 +708,7 @@ msgstr "" "проигрывателя была проверена на уровне {ph0}. В оригинале использовалось " "значение {ph1} - порог максимальной мощности." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -715,13 +723,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}Тем не менее, функция уже прошла точное сравнение.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -736,7 +744,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -753,7 +761,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -769,7 +777,7 @@ msgstr "" " Было обнаружено еще двенадцать неправильных ссылок в пяти принятых " "функциях." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -783,7 +791,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -793,7 +801,7 @@ msgstr "" "{ph0}Ссылка для проверки (oracle) также нуждалась в восстановлении.{ph1} Ее " "исправление было частью обновления игры." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -811,7 +819,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -828,7 +836,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -838,7 +846,7 @@ msgstr "" "{ph0}Успешный запуск пакета позволил нам восстановить код и улучшить среду " "для следующего пакета.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Две разные идеи реконструкции" @@ -847,7 +855,7 @@ msgstr "Две разные идеи реконструкции" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -859,7 +867,7 @@ msgstr "" " рода работой. В уведомлении сообщается, что дальнейшая разработка будет " "вестись в частном порядке до завершения. В одном отрывке говорится:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -869,7 +877,7 @@ msgstr "" "интеллекта) в этой области, основанный на нашей работе, создает плохую " "картину для будущих усилий по декомпиляции…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -887,7 +895,7 @@ msgstr "" "касаются того, как должна проходить реконструкция и как следует оценивать " "вклад." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -901,7 +909,7 @@ msgstr "" " имело значение, потому что большая часть рассуждений возникала во время его" " работы." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -913,7 +921,7 @@ msgstr "" "может использовать эти знания для проведения следующего расследования " "самостоятельно." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -928,7 +936,7 @@ msgstr "" "человек мог проанализировать, почему мы выбрали ту или иную реализацию, даже" " если большую часть работы выполнил агент." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -941,7 +949,7 @@ msgstr "" "связи с этим возникают серьезные вопросы о кредитоспособности. Это также " "меняет то, что необходимо знать разработчикам, прежде чем принимать вклад." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -957,7 +965,7 @@ msgstr "" "неверны. Различные сообщества могут выбирать, какую часть этих изменений они" " хотят взять на себя." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -982,7 +990,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -995,14 +1003,14 @@ msgstr "" "является сокращенной выдержкой. {ph4}Титры и происхождение{ph5} TH08 " "указывают на границу продолжения." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095 : опыт начинает накапливаться" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1017,7 +1025,7 @@ msgstr "" " знали гораздо больше о том, как начать реконструкцию и как поддерживать ее " "в рабочем состоянии." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1030,7 +1038,7 @@ msgstr "" "программа была подключена. Реконструкция Windows i386 была отмечена как " "играбельная 10 сентября, примерно через двенадцать дней после инициализации." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1041,7 +1049,7 @@ msgstr "" "могла бы извлечь выгоду из работы над другой игрой. Опыт уже присутствовал в" " инструментах и в том, как был организован проект." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1056,7 +1064,7 @@ msgstr "" "нужно увидеть, как они работают вместе. Этот урок помог нам сформулировать " "подход к построению всей программы TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1070,7 +1078,7 @@ msgstr "" "может использовать результат, не повторяя расследование, которое привело к " "нему." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1085,7 +1093,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1097,7 +1105,7 @@ msgstr "" "игры.{ph1} В следующем проекте мы можем потратить больше усилий на то, чтобы" " внести что-то действительно новое в его цель." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1110,7 +1118,7 @@ msgstr "" " работу. Им не нужно восстанавливать всю историю проекта, чтобы выяснить, " "почему исходный код выглядит именно так." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "" @@ -1120,7 +1128,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1137,7 +1145,7 @@ msgstr "" "Существующая {ph2}работа{ph3} по ReC98 также дала нам ценные знания и " "исходные материалы." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1150,7 +1158,7 @@ msgstr "" "настоящее время используется собственный 64-разрядный порт. При установке " "рабочей версии DOS сначала указывается ссылка на этот порт." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1163,7 +1171,7 @@ msgstr "" "Но агент по-прежнему мог довести вопрос до результата и использовать этот " "результат для следующего эксперимента." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1178,7 +1186,7 @@ msgstr "" "доказательства и чеки будут доступны, агент сможет проработать вопрос во " "многом так же, как это было с заголовком Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1190,7 +1198,7 @@ msgstr "" "определила проблему; рабочий процесс по-прежнему давал нам возможность ее " "решить." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1207,7 +1215,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1218,12 +1226,12 @@ msgstr "" "тестирование{ph1} · {ph2}64-разрядный порт{ph3}. Порт находится в " "разработке." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "От точного кода к читаемому коду" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1232,7 +1240,7 @@ msgstr "" "Как только реконструкция завершится, я хочу, чтобы кто-то еще смог это " "понять." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1247,7 +1255,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1265,7 +1273,7 @@ msgstr "" "источником, чтобы следующий человек мог понять, откуда взялась эта " "интерпретация." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1280,14 +1288,14 @@ msgstr "" "это состояние. Чтобы безопасно изменить поведение, нам нужно восстановить " "связь, стоящую за старым доступом к памяти." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Порядок, который я сейчас использую, таков:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1303,7 +1311,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1320,7 +1328,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1336,7 +1344,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1351,7 +1359,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1368,7 +1376,7 @@ msgstr "" "восстановленная программа по-прежнему строит и ведет себя корректно в " "соответствии с выбранными нами путями." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1382,7 +1390,7 @@ msgstr "" "доступны, агенту не удастся провести расследование, прежде чем проводить " "дальнейший рефакторинг." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1400,7 +1408,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1419,7 +1427,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1430,12 +1438,12 @@ msgstr "" "позволяет использовать восстановленные знания.{ph1} Затем порт может " "использовать и то, и другое." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Что делает это промышленным сдвигом" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1449,7 +1457,7 @@ msgstr "" "совершенный инструмент мог бы помочь в любой последующей работе, которая в " "нем нуждалась." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1463,7 +1471,7 @@ msgstr "" "ждать, пока я назначу каждый шаг, большая часть работы остается в моем " "распоряжении." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1476,7 +1484,7 @@ msgstr "" " ему понять ошибку достаточно хорошо, чтобы повторить попытку. Мне все еще " "нужно решить, соответствуют ли собранные данные этапу проекта." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1492,7 +1500,7 @@ msgstr "" "предлагаемый им источник и посмотреть, соответствует ли его объяснение " "действительности." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1510,7 +1518,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1531,7 +1539,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1548,7 +1556,7 @@ msgstr "" "инструменте, мы должны устранить его и пересмотреть результаты, на которые " "он повлиял. Следующий проект может унаследовать более мощный инструмент." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1564,7 +1572,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1576,7 +1584,7 @@ msgstr "" " дает проектам возможность совместно проводить проверки и извлекать уроки. " "Работа над одной игрой может улучшить стартовые условия для другой." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1588,12 +1596,12 @@ msgstr "" "Совершенствование этих инструментов влияет на то, как много может сделать " "следующий человек — или следующий агент." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Проекты, которые мы теперь можем рассмотреть" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1604,7 +1612,7 @@ msgstr "" "увлекательной для реинжиниринга и все равно требовать от меня больше " "внимания, чем я мог бы ей уделить. Многие проекты так и останутся идеями." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1621,7 +1629,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1632,7 +1640,7 @@ msgstr "" "обратная связь и накопленные знания позволили бы агенту надежно работать с " "ней?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1643,12 +1651,12 @@ msgstr "" "бы в покое. Каждый из них может улучшить наш подход к следующему. Я хочу " "продолжать изучать, как далеко это может нас завести." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Основные этапы и источники реализации проекта" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1683,7 +1691,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1717,7 +1725,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1736,7 +1744,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1760,7 +1768,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1782,7 +1790,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1799,7 +1807,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1821,7 +1829,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1835,7 +1843,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1858,27 +1866,27 @@ msgstr "" " агентов искусственного интеллекта и о том, как знания объединяются в TH08, " "TH095 и PC-98, TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Опыт, накопленный в период между проектами" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Эссе о реконструкции Тохоу" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -1887,18 +1895,18 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Главная{ph1}{ph2} страница/{ph3}Лаборатория скорости динозавров" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Проверить → перестроить → изменить" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Восстановите скоростное правило динозавра." @@ -1907,7 +1915,7 @@ msgstr "Восстановите скоростное правило диноз #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1919,15 +1927,15 @@ msgstr "" "скоростью. {ph0}REA вернул запущенный скрипт;{ph1} мы использовали его " "правило для создания этой мини-игры с {ph2}регулируемой скоростью.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "На этой странице" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1935,7 +1943,7 @@ msgstr "{ph0}Играйте и меняйте скорость{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1943,7 +1951,7 @@ msgstr "{ph0}Прочтите восстановленное правило{ph1} #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1951,18 +1959,18 @@ msgstr "{ph0}Проверьте реконструкцию{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Попробуйте провести анализ{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Играйте и меняйте скорость" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1974,49 +1982,49 @@ msgstr "" "на фиксированную скорость. Выберите восстановленное правило, чтобы начать с " "6 и постепенно увеличивать скорость снова." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Играть в воссозданную версию" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Играть" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Прыжок ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Начать заново" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Скорость" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Используйте правило восстановленного ускорения" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Первоначальное правило: начинайте с 6, затем увеличивайте до 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Перемещайте ползунок, чтобы установить собственную скорость. Пробел или " "прыжок убирают кактус." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2025,7 +2033,7 @@ msgstr "" "Включите JavaScript для воспроизведения реконструкции. Приведенный выше код " "и пояснения остаются читаемыми." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Прочитал возвращенный скрипт REA" @@ -2033,7 +2041,7 @@ msgstr "Прочитал возвращенный скрипт REA" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2048,7 +2056,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2058,18 +2066,18 @@ msgstr "" "Заданы следующие параметры: {ph0}, {ph1} и МАКСИМАЛЬНАЯ {ph2}. Игра " "запускает эту ветку в обновлении без каких-либо коллизий." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Используйте то же правило в новой игре" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Копировать" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2086,18 +2094,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}Скачайте правила скорости{ph1} · {ph2}Прочитайте код игры{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Проверьте реконструкцию" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2108,27 +2116,27 @@ msgstr "" "препятствиями и автоматическим планированием. Сравните эти записанные " "скорости с воспроизведением восстановленного правила." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Обновления" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Оригинальная игра" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Реконструированное правило" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Запустите проверку скорости" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2137,14 +2145,14 @@ msgstr "" "Значения округлены до трех знаков после запятой. Ветвление проверяет перед " "добавлением, поэтому конечное приращение может быть чуть выше 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Попробуйте провести анализ самостоятельно" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2153,7 +2161,7 @@ msgstr "{ph0}Настройте REA{ph1} с помощью вашего аген #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2162,7 +2170,7 @@ msgstr "" "Выполните {ph0}действия по подключению к браузеру{ph1}, используя {ph2} в " "качестве URL-адреса страницы." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2179,7 +2187,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2191,7 +2199,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий аг #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2205,7 +2213,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2220,7 +2228,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2246,12 +2254,12 @@ msgstr "" "Прочитайте правила скорости в игре про динозавров с помощью REA, перестройте" " их, затем измените скорость и играйте." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Реконструкция скорости динозавра" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2260,52 +2268,52 @@ msgstr "" "Мини-игра про динозавров. Используйте кнопку перехода или нажмите пробел, " "пока игра сосредоточена." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Скопируйте восстановленное правило скорости" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Запрос на копирование результатов анализа динозавров" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Главная{ph1} страница / Часто задаваемые вопросы" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ по REA." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Настройка, обновления, анализ и устранение неполадок." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Темы" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2313,7 +2321,7 @@ msgstr "{ph0}Настройка и обновления{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2321,7 +2329,7 @@ msgstr "{ph0}Анализ{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2329,31 +2337,31 @@ msgstr "{ph0}Диагностика{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Данные и обмен ими{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Настройка и обновления" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Как установить REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Терминал · настройка агента" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Копировать" @@ -2361,7 +2369,7 @@ msgstr "Копировать" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2375,12 +2383,12 @@ msgstr "" "файлу и вопрос. Требования и шаги первого анализа описаны в {ph0}руководстве" " по настройке{ph1}." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Какие агенты кодирования могут использовать REA?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2395,18 +2403,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Подключите свой кодирующий агент{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Как обновить REA?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2414,13 +2422,13 @@ msgid "" msgstr "" "REA релизы часто, включая исправления ошибок. Если вы установили CLI с npm:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Терминал · установлен CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2430,14 +2438,14 @@ msgstr "" "Выполните команду обновления настроек, указанную в обновлении. Если вы " "настраиваете свой агент через {ph0}, запустите:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Терминал · настройка агента обновления" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2449,14 +2457,14 @@ msgstr "" "фиксированную версию пакета. Повторите настройку, чтобы агент перешёл на " "новую версию. Для разового вызова CLI добавьте нужную команду после {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Устанавливается навык из навыков.этого достаточно?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2469,24 +2477,24 @@ msgstr "" "соответствующий навык, затем перезапустите свой агент, чтобы он мог вызвать " "инструменты." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Анализ" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Что я могу проанализировать с помощью REA?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Начните с того программного обеспечения, которое у вас есть:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2498,7 +2506,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2510,7 +2518,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2520,7 +2528,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2532,12 +2540,12 @@ msgstr "" "APK для Android, встроенного ПО и упакованных ресурсов. {ph0}Смотрите " "примеры проведенных исследований{ph1}." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Нужен ли мне Hopper, Ghidra или IDA?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2549,7 +2557,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2562,12 +2570,12 @@ msgstr "" "сервер определяют, какого провайдера можно использовать. {ph0}Настройте " "анализ программ с машинным кодом{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Могу ли я использовать REA без кодирующего агента?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2576,14 +2584,14 @@ msgstr "" "Да. В CLI используются те же рабочие процессы анализа. Для локального " "приложения JavaScript или Electron:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Терминал · статический анализ приложений" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2594,13 +2602,13 @@ msgstr "" "{ph0}Используйте CLI{ph1} для параметров установки." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Какой код возвращает REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2615,7 +2623,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2627,12 +2635,12 @@ msgstr "" " тестирования реализации. {ph0}Расчет{ph1} DX-Ball и {ph2}проверка флага " "CTF{ph3} показывают, как работает этот процесс." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Что спросить у помощника?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2649,7 +2657,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2657,7 +2665,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий аг #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2667,18 +2675,18 @@ msgstr "" "Замените путь на целевой. В {ph0}руководствах{ph1} приведены подсказки для " "примеров в native, Electron и браузере." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Диагностика" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Почему мой агент не может видеть инструменты REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2688,7 +2696,7 @@ msgstr "" "Перезапустите или повторно подключите свой агент после настройки. Проверьте " "его регистрацию REA в {ph0}; для Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Терминал · проверьте одного клиента" @@ -2696,7 +2704,7 @@ msgstr "Терминал · проверьте одного клиента" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2707,14 +2715,14 @@ msgstr "" "Если в отчете отображается отсутствие или устаревшая регистрация, запустите " "программу установки для этого клиента:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Терминал · исправление настроек одного клиента" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2726,14 +2734,14 @@ msgstr "" "успешно, но инструменты по-прежнему отсутствуют, проверьте ошибку " "подключения клиента MCP. {ph0}Дополнительная диагностика настройки{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Нужно ли мне сначала запускать Hopper?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2746,14 +2754,14 @@ msgstr "" "демонстрационный режим или активацию лицензии. {ph0}Смотрите раздел " "Настройка собственного провайдера{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Что делать, если я нашёл ошибку?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2765,7 +2773,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2777,17 +2785,17 @@ msgstr "" "систему, тип устройства, шаги для воспроизведения и вывод ошибки. Укажите " "имя поставщика, если проблема связана с анализом программ с машинным кодом." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Данные и обмен ими" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "Загружает ли REA мое приложение?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2797,7 +2805,7 @@ msgstr "" " этим результатам применяется политика в отношении данных, установленная его" " поставщиком моделей." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Как я могу поделиться примером или внести свой вклад?" @@ -2806,7 +2814,7 @@ msgstr "Как я могу поделиться примером или внес #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2822,7 +2830,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2848,77 +2856,77 @@ msgstr "" "Ответы на распространенные вопросы REA: установка, обновления, инструменты " "анализа, средства программирования, устранение неполадок и обмен примерами." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Часто задаваемые вопросы о REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Скопировать установочную команду REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Скопировать команду обновления REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Команда обновления настройки агента копирования" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Скопировать команду анализа REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Запрос на копирование примера анализа" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Скопировать команду диагностики клиента" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Команда настройки в области копирования" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Главная{ph1} / Ваше первое расследование" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Узнайте, куда отправляются{ph0}экспортированные заметки." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2927,14 +2935,14 @@ msgstr "" "Используйте REA для проверки небольшого приложения, нажмите на кнопку " "\"Экспорт заметок\" и проверьте одну деталь самостоятельно." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "В этом упражнении" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2942,7 +2950,7 @@ msgstr "{ph0}1. Настройка{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2950,7 +2958,7 @@ msgstr "{ph0}2. Спросите об экспорте{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2958,7 +2966,7 @@ msgstr "{ph0}3. Следуйте ответу{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2966,13 +2974,13 @@ msgstr "{ph0}4. Проверьте прогноз{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Задайте еще один вопрос{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Подключите своего агента к REA." @@ -2985,29 +2993,29 @@ msgstr "1. Подключите своего агента к REA." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Копировать" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Или запустите эту команду в своем терминале:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -3016,14 +3024,14 @@ msgstr "" "Ознакомьтесь с планом, одобрите настройку, затем перезапустите свой агент. " "Вы уже подключены? Продолжение ниже." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Спросите, где записан CSV" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3035,7 +3043,7 @@ msgstr "" "кнопкой {ph0}экспорта заметок{ph1}. Ваш агент может проверить его код, не " "устанавливая и не запуская Electron." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3046,14 +3054,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Пример загрузки ZIP-файла{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3064,12 +3072,12 @@ msgstr "" "самостоятельно. Укажите путь к папке {ph0} и задайте тот же вопрос об " "экспорте." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Следуйте ответу обратно к коду" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Ищите краткое объяснение со ссылками на файлы и строки:" @@ -3078,7 +3086,7 @@ msgstr "Ищите краткое объяснение со ссылками н #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3090,12 +3098,12 @@ msgstr "" "CSV и записывает {ph1} в папку загрузок пользователя. Это столбцы {ph2} и " "{ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "От кнопки до устройства записи файлов" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3104,7 +3112,7 @@ msgstr "" "Статический анализ REA сопоставляет сообщение с его обработчиком. Адресат " "считывается из кода." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3116,19 +3124,19 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "" "{ph0}Посмотрите полную трассировку кода и записанный результат{ph1} REA." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Проверьте прогноз" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3137,19 +3145,19 @@ msgstr "" "Столбцы CSV разделены запятой. Что происходит, когда заголовок заметки сам " "по себе содержит запятую или кавычки?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Проведите проверку самостоятельно" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Откройте терминал в распакованной папке {ph0}:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3159,17 +3167,17 @@ msgstr "" "или Zsh. Ваш агент может запустить тот же JavaScript в оболочке вашей " "платформы." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Задайте еще один вопрос" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Попробуйте продолжить тот же разговор:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3178,7 +3186,7 @@ msgstr "" "Что произойдет, если файл не может быть записан? Вернитесь на страницу, " "указанную в сообщении об ошибке." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3191,7 +3199,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3205,7 +3213,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3219,7 +3227,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3244,65 +3252,65 @@ msgstr "" "спросите, куда отправляются экспортированные заметки, и проверьте " "форматирование CSV с примером заголовка." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Ваше первое расследование REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Скопировать запрос на установку REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Команда настройки копирования" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Запрос на копирование заметок для расследования" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Скопировать запрос проверки CSV" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Команда проверки форматирования копии" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Главная{ph1} страница / Начало работы" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Настройте REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3310,49 +3318,49 @@ msgstr "" "Подключите REA к вашему программисту или проверьте локальное приложение с " "вашего терминала." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Откройте терминал и проверьте:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Терминал" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Копировать" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3365,7 +3373,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3376,17 +3384,17 @@ msgstr "" "отключен\"{ph1}, когда вы запустите {ph2}, запустите это один раз и " "повторите попытку:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Если вы используете Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Иначе:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Закройте терминал, откройте его снова, затем:" @@ -3394,7 +3402,7 @@ msgstr "Закройте терминал, откройте его снова, #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3406,7 +3414,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3418,7 +3426,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3428,14 +3436,14 @@ msgstr "" "Предпочитаете обычный установщик? Загрузите версию LTS с сайта " "{ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Параметры настройки" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3443,7 +3451,7 @@ msgstr "{ph0}Подключите свой кодирующий агент{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3451,7 +3459,7 @@ msgstr "{ph0}Используйте CLI{ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3459,18 +3467,18 @@ msgstr "{ph0}Настройка анализа программ с машинн #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Получение помощи{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Подключите свой кодирующий агент" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3482,12 +3490,12 @@ msgstr "" "Grok Build и другие поддерживаемые клиенты MCP. Коннектор Grok Bot добавлен " "из его чата." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Новичок в кодировании агентов?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3499,7 +3507,7 @@ msgstr "" "выполнять команды, а также запрашивает их, прежде чем вносить изменения. " "REA предоставляет ему инструменты для обратного проектирования." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3511,7 +3519,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3524,7 +3532,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3537,7 +3545,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3547,7 +3555,7 @@ msgstr "" "{ph0}{ph1} OpenCode{ph2}{ph3} , с открытым исходным кодом. Подключите " "поставщика модели по вашему выбору." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3564,18 +3572,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Или запустите программу настройки самостоятельно" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Как мне открыть терминал?" @@ -3584,7 +3592,7 @@ msgstr "Как мне открыть терминал?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3600,7 +3608,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3614,7 +3622,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3629,7 +3637,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3639,7 +3647,7 @@ msgstr "" "Введите команду с помощью {ph0} {ph1} ( macOS : {ph2} {ph3}; Linux для " "терминалов: {ph4} {ph5} {ph6}), затем нажмите Enter." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3651,12 +3659,12 @@ msgstr "" "копию существующей конфигурации. Перед применением изменений программа " "запрашивает доступ." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "После завершения установки перезагрузите клиент." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Как мне перезапустить мой клиент?" @@ -3665,7 +3673,7 @@ msgstr "Как мне перезапустить мой клиент?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3682,7 +3690,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3692,7 +3700,7 @@ msgstr "" "{ph0}Терминальные агенты{ph1} ( Claude Code , Codex , Gemini CLI ): выйдите " "из сеанса и запустите его снова." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3702,7 +3710,7 @@ msgstr "" "приложения JavaScript или Electron вы можете начать с:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3713,12 +3721,12 @@ msgstr "" "входа, вызовы и зависимости, а также исходные местоположения для ваших " "результатов." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Замените путь на ваш локальный целевой объект." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Как мне получить полный путь к папке?" @@ -3727,7 +3735,7 @@ msgstr "Как мне получить полный путь к папке?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3742,7 +3750,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3754,7 +3762,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3764,17 +3772,17 @@ msgstr "" "{ph0}Любая система:{ph1} перетащите папку в окно терминала, и появится путь " "к ней." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "В терминале заключите путь, содержащий пробелы, в кавычки." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Используйте CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3783,14 +3791,14 @@ msgstr "" "Проанализируйте папку приложения JavaScript или Electron или архив ASAR, не " "запуская приложение:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Статический анализ приложений" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3800,13 +3808,13 @@ msgstr "" "Замените путь на каталог вашего извлеченного приложения или файл {ph0}. В " "Windows здесь работает путь, например {ph1}." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Где мне найти asar-файл приложения?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3817,7 +3825,7 @@ msgstr "Приложения Electron обычно хранят его в пап #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3829,7 +3837,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3842,14 +3850,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} часто {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3857,7 +3865,7 @@ msgstr "" "Некоторые приложения устанавливаются в другом месте. Найдите в папке " "приложения {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3869,31 +3877,31 @@ msgstr "" "которые REA не может разрешить." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Если вы хотите, чтобы в вашей оболочке была постоянная команда {ph0}:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Установите CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Продолжайте читать руководство по применению JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Настройка анализа программ с машинным кодом" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3903,12 +3911,12 @@ msgstr "" " и настройте один из приведенных ниже инструментов, затем укажите REA свой " "исполняемый файл или библиотеку." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Выберите инструмент: Ghidra, Hopper или IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3920,17 +3928,17 @@ msgstr "" "требуется собственный декомпилятор для архитектуры вашего хоста. Задайте " "пути перед запуском программы установки:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Подключите вашу установку Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Подключение Ghidra · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3942,12 +3950,12 @@ msgstr "" "В Linux arm64 вам может потребоваться отдельно собрать собственный " "декомпилятор Ghidra." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Подключите Ghidra к Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3959,19 +3967,19 @@ msgstr "" "NTFS. Используйте существующую установку Ghidra 12.1.x и 64-разрядную версию" " JDK 21 или новее:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Подключение Ghidra · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "" "Замените эти два пути вашими установками, затем просмотрите план установки." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3981,7 +3989,7 @@ msgstr "" "установки; она обнаружит существующую установку или предложит план установки" " для вашего одобрения." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3990,7 +3998,7 @@ msgstr "" "На macOS перед автоматическим анализом выполните первый запуск Hopper, " "выбрав демонстрационный режим или активацию лицензии." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -4002,7 +4010,7 @@ msgstr "" "безголовой базы данных. Анализ Linux и macOS без учета данных остается " "непроверенным." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Подключите существующую регистрацию IDA MCP" @@ -4012,7 +4020,7 @@ msgstr "Подключите существующую регистрацию IDA #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4024,13 +4032,13 @@ msgstr "" " файле JSON. Также принимается существующий {ph3}объект mcpServers с записью" " {ph4}. Укажите REA в этом файле перед установкой:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Подключение IDA · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4048,7 +4056,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4060,29 +4068,29 @@ msgstr "" "CLI. Для агента включите {ph1} в среду регистрации REA и выберите IDA при " "открытии двоичного файла." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Для существующей настройки Ghidra проверьте функцию с помощью:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Функциональный анализ" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "Замените {ph0} на имя функции или адрес, который вы хотите проверить." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Как работают сеансы анализа программ с машинным кодом" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4095,7 +4103,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4105,18 +4113,18 @@ msgstr "" "{ph0}Следуйте примеру анализа программ с машинным кодом{ph1}, чтобы увидеть," " как результат функции приводит к восстановленному вычислению." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Получение помощи" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Если ваш агент не видит REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4126,27 +4134,27 @@ msgstr "" "Перезапустите или повторно подключите клиент после установки. Проверьте его " "REA-соединение с {ph0}; для Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Проверьте одного клиента" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Если поставщик услуг нуждается во внимании" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Проверьте, каким провайдером вы пользуетесь. Для Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Проверьте одного поставщика" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4157,7 +4165,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4170,7 +4178,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4184,7 +4192,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4198,7 +4206,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4222,112 +4230,112 @@ msgstr "" "приложением JavaScript или Electron с терминала. Настройка, первые вопросы и" " инструкции для местных провайдеров." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Скопируйте проверку версии Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Скопируйте команду установки Node.js для Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Скопировать команду политики выполнения PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Скопировать команду установки Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Скопируйте команду установки fnm для macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Скопируйте 24 команды Node.js для macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Скопируйте команду установки fnm для Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Скопируйте 24 команды Node.js для Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA руководство по началу работы" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Скопировать запрос на установку REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Команда настройки агента копирования" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Скопировать команду анализа JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Скопировать команду установки CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Скопировать команду подключения Ghidra для macOS и Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Скопируйте подключение Ghidra для Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Скопируйте подключение IDA для Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Скопировать команду анализа собственной функции" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Скопировать команду диагностики клиента" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Команда диагностики поставщика копирования" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -4336,20 +4344,20 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Главная{ph1} страница / {ph2}Руководства{ph3} / Обзор браузера" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Посмотрим, что произойдет{ph0}когда вы нажмете." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4358,14 +4366,14 @@ msgstr "" "Используйте небольшое браузерное приложение для подключения действия, его " "сетевого запроса и JavaScript, который создает загрузку." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "В этом руководстве" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4373,7 +4381,7 @@ msgstr "{ph0}Приведенный пример{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4381,7 +4389,7 @@ msgstr "{ph0}Откройте браузер{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4389,7 +4397,7 @@ msgstr "{ph0}Спросите своего агента{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4397,13 +4405,13 @@ msgstr "{ph0}Захват из CLI{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Прочитайте запрос и скрипт{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Что происходит, когда вы нажимаете кнопку Экспортировать?" @@ -4413,7 +4421,7 @@ msgstr "Что происходит, когда вы нажимаете кноп #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4425,7 +4433,7 @@ msgstr "" "При нажатии на нее загружается файл {ph4}, две заметки форматируются как CSV" " и начинается загрузка." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "От клика до загрузки CSV" @@ -4436,7 +4444,7 @@ msgstr "От клика до загрузки CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4452,7 +4460,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4470,7 +4478,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4480,17 +4488,17 @@ msgstr "" "{ph0}03 · Ваш агент{ph1}{ph2} прочитал экспортный код{ph3}{ph4}, " "подключающий наблюдаемый запрос к {ph5} в {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Запустите запись, прежде чем нажать кнопку Экспортировать заметки." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Откройте Chrome с удаленной отладкой" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4499,21 +4507,21 @@ msgstr "" "Откройте размещенный на хостинге пример Notes, используя отдельный профиль " "браузера и локальный порт для отладки. На Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Запустите примерный браузер" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Копировать" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4523,7 +4531,7 @@ msgstr "" " или Windows . Вы можете заменить URL-адрес страницы на другую страницу, " "которую хотите просмотреть." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4532,7 +4540,7 @@ msgstr "" "REA подключается к этому существующему браузеру. Вы сохраняете контроль над " "страницей, выполняете действие и по завершении закрываете браузер." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Попросите своего агента посмотреть одно действие" @@ -4545,7 +4553,7 @@ msgstr "Попросите своего агента посмотреть одн #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4557,7 +4565,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий аг #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4569,7 +4577,7 @@ msgstr "" "устроен CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4579,7 +4587,7 @@ msgstr "" "Пример запроса. Укажите вашему агенту конечную точку отладки, {ph0} и URL-" "адрес страницы. Пусть он запустит запись до того, как вы нажмете." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4590,23 +4598,23 @@ msgstr "" "считывает полученные данные. Затем он может проверить сценарий, лежащий в " "основе экспорта." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Или захват с терминала" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Найдите целевой идентификатор страницы:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Найдите нужную страницу" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4616,14 +4624,14 @@ msgstr "" "Выберите целевой объект с помощью URL-адреса, приведенного в примере Notes. " "Замените {ph0} ниже на его идентификатор, затем запустите:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Запечатлейте следующие десять секунд" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4634,7 +4642,7 @@ msgstr "" "\"{ph0}Экспортировать заметки{ph1}\" в этом браузере. Результат появится " "после завершения просмотра." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4645,49 +4653,49 @@ msgstr "" "течение этого окна и форму ответа в формате JSON. Предыдущие запросы не " "входят в этот список." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Прочитайте запрос и экспортируйте скрипт" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Записано с помощью REA 4.1.0 на примере local Notes" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Зафиксированный факт" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Ценность" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Запрос" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Ответ" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Инициатор запроса" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} · сценарий" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Структура ответа" @@ -4695,19 +4703,19 @@ msgstr "Структура ответа" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} с полями {ph1} и {ph2}" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Прочитайте загруженные скрипты" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4719,7 +4727,7 @@ msgstr "" "чтобы увидеть, как используются данные:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4732,7 +4740,7 @@ msgstr "" "при этом щелчке запрашивался файл {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4744,7 +4752,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4769,65 +4777,65 @@ msgstr "" "Наблюдайте за экспортом заметок с помощью REA: выберите страницу браузера, " "зафиксируйте щелчок, просмотрите запрос и следуйте сценарию экспорта." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Наблюдение в браузере" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Скопируйте и запустите пример браузера" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Запрос на копирование примера" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Скопируйте найденную страницу" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Скопируйте запись на следующие десять секунд" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Копировать читать загруженные скрипты" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Главная{ph1} страница / Путеводители" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Направляющие REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4836,37 +4844,37 @@ msgstr "" "Проанализируйте встроенную функцию, экспорт Electron или запрос браузера. " "Каждое руководство содержит подсказку, код и результаты." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Первое расследование" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Настройка REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Подключите свой кодировщик или используйте REA с терминала." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Начните работу с REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Программы с машинным кодом" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Восстановление расчета положения звука слева/справа" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4876,22 +4884,22 @@ msgstr "" "следуйте за вызывающим пользователем, прочитайте числовые константы и " "проверьте восстановленный C." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Руководство по анализу программ с машинным кодом" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript и Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Следите за экспортом CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4901,14 +4909,14 @@ msgstr "" "предварительной загрузки и основного процесса. Используйте REA для " "подключения API, IPC-канала и средства записи файлов." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Руководство по JavaScript и Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4916,17 +4924,17 @@ msgstr "" "Чтобы создать более крупное упакованное приложение, воспользуйтесь " "{ph0}мостом буфера{ph1} обмена Notion." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Поведение браузера" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Наблюдайте за щелчком" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4935,7 +4943,7 @@ msgstr "" "Откройте пример working Notes, запишите запрос на экспорт и найдите код, " "который преобразует его ответ в загрузку." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Руководство по наблюдению за браузером" @@ -4954,12 +4962,12 @@ msgstr "" "Изучите REA на кратких примерах: собственные вычисления, экспорт Electron, " "CSV и запрос из браузера." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -4968,7 +4976,7 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" @@ -4976,13 +4984,13 @@ msgstr "" "{ph0}Главная{ph1} страница / {ph2}Руководства{ph3} / JavaScript и Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Проследите экспорт Electron {ph0} CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4991,14 +4999,14 @@ msgstr "" "Выполните нажатие кнопки на странице API, через Electron IPC, для записи " "файлов CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "В этом руководстве" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -5006,7 +5014,7 @@ msgstr "{ph0}Приведенный пример{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5014,7 +5022,7 @@ msgstr "{ph0}Спросите своего агента{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -5022,7 +5030,7 @@ msgstr "{ph0}Отслеживание экспортного кода{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5030,20 +5038,20 @@ msgstr "{ph0}Попробуйте на примере{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Проверьте устройство записи CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Куда девается “Экспорт заметок”?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5056,7 +5064,7 @@ msgstr "" "выполняется переход к основному процессу и записывается CSV . Поведение " "распределено по нескольким файлам." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "Экспорт CSV в рамках процессов Electron" @@ -5070,7 +5078,7 @@ msgstr "Экспорт CSV в рамках процессов Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5088,7 +5096,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5105,7 +5113,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5118,13 +5126,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} форматирует заметки → {ph1} записывает файлы для {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5135,14 +5143,14 @@ msgstr "" "открытый API. Путь выводится из кода; при перехвате во время выполнения " "можно проверить, что выполняется." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Спросите об экспорте CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5160,14 +5168,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Копировать" @@ -5178,7 +5186,7 @@ msgstr "Копировать" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5189,7 +5197,7 @@ msgstr "" "экспортирую заметки в это приложение. Где создан CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5197,7 +5205,7 @@ msgid "" "{ph0}." msgstr "Пример запроса. Укажите абсолютный путь к папке приложения или {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5208,17 +5216,17 @@ msgstr "" " процессов. Ваш агент использует эту карту, чтобы сузить область поиска до " "функции экспорта." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Отслеживание экспортного кода" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Страница вызывает небольшой API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5229,7 +5237,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5241,7 +5249,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5252,7 +5260,7 @@ msgstr "" "форматируются, и основной процесс записывает файл {ph1} в папку загрузок " "пользователя." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5262,7 +5270,7 @@ msgstr "" "Расположение исходных текстов соответствует выводам API, канала и " "обработчика." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Проанализируйте этот пример самостоятельно" @@ -5270,25 +5278,25 @@ msgstr "Проанализируйте этот пример самостоят #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Пример загрузки ZIP-файла{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Просмотрите шесть исходных файлов" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Статический анализ приложений" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5299,7 +5307,7 @@ msgstr "" "канал и один соответствующий обработчик в {ph0}. Местоположения источников " "указаны в {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5310,13 +5318,13 @@ msgstr "" "каталог или путь к ASAR. Агент может использовать буквенную строку, имя API " "или IPC-канал с помощью инструментов отслеживания функций REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Проверьте устройство записи CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5326,7 +5334,7 @@ msgstr "" "Следуйте {ph0} в его обработчик. Какие входные данные поступают в CSV writer" " и что произойдет, если запись файла завершится неудачей?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5342,7 +5350,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5356,7 +5364,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5370,7 +5378,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5396,32 +5404,32 @@ msgstr "" "предварительной загрузки и обработчика IPC с помощью REA. Включает " "загружаемые файлы примеров и проверенный результат анализа." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript и Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Запрос на копирование примера" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Копирование статического анализа приложения" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -5430,7 +5438,7 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5439,13 +5447,13 @@ msgstr "" "машинным кодом" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "Восстановить данные DX-Ball{ph0}расчет положения звука слева/справа." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5454,14 +5462,14 @@ msgstr "" "Просмотрите исходные инструкции, определите входные данные и константы, " "затем проверьте восстановленный C." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "В этом руководстве" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5469,7 +5477,7 @@ msgstr "{ph0}Приведенный пример{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5477,7 +5485,7 @@ msgstr "{ph0}Спросите своего агента{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5485,7 +5493,7 @@ msgstr "{ph0}Ознакомьтесь с результатами REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5493,18 +5501,18 @@ msgstr "{ph0}Восстановите и проверьте{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Используйте свой собственный двоичный файл{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Рассчитать расположение стереозвука слева / справа" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5515,7 +5523,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5527,7 +5535,7 @@ msgstr "" "функции {ph1}. REA также возвращает свои инструкции и вызывающие " "устройства, которые дают агенту возможность найти недостающую арифметику." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Вы знакомы с этими условиями?" @@ -5536,7 +5544,7 @@ msgstr "Вы знакомы с этими условиями?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5548,7 +5556,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5561,7 +5569,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5574,7 +5582,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5586,7 +5594,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5596,7 +5604,7 @@ msgstr "" "{ph0}Константы:{ph1} фиксированные числа, хранящиеся в программе, " "считываемые как необработанные байты и декодируемые." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Три улики, один расчет" @@ -5607,7 +5615,7 @@ msgstr "Три улики, один расчет" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5625,7 +5633,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5643,7 +5651,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5653,7 +5661,7 @@ msgstr "" "{ph0}03 · Байты данных{ph1}{ph2} Числовые константы{ph3}{ph4}, на которые " "ссылаются байты, декодируются как {ph5}, {ph6} и масштабное значение.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5662,7 +5670,7 @@ msgstr "" "REA предоставляет инструкции, связь между вызовами функций и байты. Агент " "интерпретирует их вместе." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Спросите о поведении" @@ -5671,7 +5679,7 @@ msgstr "Спросите о поведении" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5682,19 +5690,19 @@ msgstr "" " анализа программ с машинным кодом{ph3} предоставьте локальный исполняемый " "файл и вопрос:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Какой инструмент анализа мне следует использовать?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA нужен один из них для чтения собственных программ:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5708,7 +5716,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5721,7 +5729,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5732,7 +5740,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5748,14 +5756,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Копировать" @@ -5766,7 +5774,7 @@ msgstr "Копировать" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5776,7 +5784,7 @@ msgstr "" "{ph0}\"{ph1}{ph2}Используйте REA, чтобы узнать, как DX-Ball рассчитывает " "расположение стереозвука. Объясните расчет и покажите код.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5788,7 +5796,7 @@ msgstr "" " копию или задайте такой же вопрос о другой небольшой программе Windows, " "которая у вас есть." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Как мне получить полный путь к файлу?" @@ -5797,7 +5805,7 @@ msgstr "Как мне получить полный путь к файлу?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5812,7 +5820,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5824,7 +5832,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5834,17 +5842,17 @@ msgstr "" "{ph0}Любая система:{ph1} перетащите файл в окно терминала, и появится путь к" " нему." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Ознакомьтесь с результатами REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Прочитайте входные данные" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5854,13 +5862,13 @@ msgstr "" " плавающей запятой. Это входные данные, отсутствующие в первом представлении" " псевдокода." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Следуйте за звонящим" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5871,12 +5879,12 @@ msgstr "" "координата плитки умножалась на 30; добавление {ph0} (20) дает положение " "кирпича на экране." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Прочитайте указанные константы" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5885,12 +5893,12 @@ msgstr "" "Арифметика ссылается на эти адреса. Считывание байтов позволяет получить " "фактические значения; порядок команд сообщает агенту, как они используются." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Запишите и проверьте восстановленную функцию" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5901,7 +5909,7 @@ msgstr "" "до преобразования в целое число. При вычислении центр экрана оказывается в " "центре стереополя." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5914,20 +5922,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Смотрите полное исследование и сравнение сборки с C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Попробуйте это с вашим собственным двоичным кодом" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5942,7 +5950,7 @@ msgstr "" "обрабатывается этот файл?” или “Какая функция выполняет это действие в " "меню?”." -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5951,13 +5959,13 @@ msgstr "" "Если вы уже знаете название функции или адрес, вы можете запросить его из " "терминала. Для настроенной установки Ghidra:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Функциональный анализ" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5971,7 +5979,7 @@ msgstr "" "свой сеанс. Запросы вашего агента MCP повторно используют импортированный " "двоичный файл, пока этот сеанс открыт." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5996,50 +6004,50 @@ msgstr "" "следуйте за вызывающим пользователем, считывайте константы и проверяйте " "восстановленный C." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Анализ программ с машинным кодом" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Запрос на копирование примера" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Анализ функции копирования" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Перейти к содержанию" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Настройка REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6047,7 +6055,7 @@ msgstr "{ph0}Настройка REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6055,7 +6063,7 @@ msgstr "{ph0}Что такое ОГОНЬ?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6063,7 +6071,7 @@ msgstr "{ph0}Как помогает REA{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6071,7 +6079,7 @@ msgstr "{ph0}Игра в динозавров{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6079,7 +6087,7 @@ msgstr "{ph0}Калькулятор{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6087,7 +6095,7 @@ msgstr "{ph0}Попробуйте REA{ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6095,7 +6103,7 @@ msgstr "{ph0}Узнать больше{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6103,25 +6111,25 @@ msgstr "{ph0}Помощь и обратная связь{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Сообщество{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Обратное проектирование с помощью вашего агента по кодированию" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Узнайте, как{ph0}работает программа." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6132,7 +6140,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6140,13 +6148,13 @@ msgstr "Уже знакомы с RE? {ph0}Перейти к руководств #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Хотите копнуть глубже? {ph0}Читать блог →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Вставьте этот запрос в своего ИИ-помощника для программирования:" @@ -6159,38 +6167,38 @@ msgstr "Вставьте этот запрос в своего ИИ-помощн #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Копировать" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Или выполните эту команду в терминале:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Проверьте и одобрите план изменений, затем перезапустите помощника." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Что такое обратная разработка?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6205,7 +6213,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6217,7 +6225,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6225,7 +6233,7 @@ msgstr "До REA · Вы исследуете {ph0}самостоятельно{ #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6233,7 +6241,7 @@ msgstr "{ph0}01{ph1} Декодирование ветвей" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6241,7 +6249,7 @@ msgstr "{ph0}02{ph1} Отслеживание вызовов" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6251,20 +6259,20 @@ msgstr "{ph0}03{ph1} Восстановите правило" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Оригинальные выбранные инструкции для x64 ·{ph1}{ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 · В каком филиале?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6274,29 +6282,29 @@ msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Два перехода в одно и то же место. Что это за " "операторы?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Найдите идентификаторы команд, затем пометьте ветвь." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Разделить ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Умножить ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Что делают вызываемые функции?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6306,24 +6314,24 @@ msgstr "" "“100 - это чисто. Вызовы - это просто адреса. {ph0}Какой из них делится? " "Какое значение входит в?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Проверьте вспомогательные функции и проследите сохраненные значения." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Делить" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 · Каково это правило?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6333,19 +6341,19 @@ msgstr "" "“Этот путь умножается на другие входные данные. Таким образом, {ph0}10% " "означает 10% от 200{ph1} после +”." -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Назовите операнды и проверьте оба пути к операторам." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Наглядное рассуждение эксперта" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6357,20 +6365,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "С REA · Вы спрашиваете {ph0}своего помощника{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Всего один запрос." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6384,21 +6392,21 @@ msgstr "Задайте помощнику вопрос {ph0}обычными с #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Пример подсказки · Калькулятор" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Пример ответа · основан на результатах исследования" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6406,29 +6414,29 @@ msgid "" msgstr "" "После + кнопка % выводит {ph0}процентное значение от первого числа.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA предоставляет" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Инструкции обработчика, декомпилированный код и вызовы." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Помощник объясняет" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Какая ветвь применяется, что она вычисляет и как ее перестроить." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6441,7 +6449,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6451,37 +6459,37 @@ msgstr "" "{ph0}Давайте рассмотрим два примера.{ph1} Измените скорость игры, затем " "вернитесь в калькулятор и перестройте его кнопку %." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Пример 01 · Игра в динозавров Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Почему динозавр ускоряется?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Цель" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Перестраивайте игру с {ph0}регулируемой скоростью.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Зачем его перепроектировать?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6492,49 +6500,49 @@ msgstr "" "игре{ph1}: как быстро оно начинается, насколько увеличивается и когда " "прекращается." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Играть в воссозданную версию" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Играть" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Прыжок ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Начать заново" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Скорость" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Используйте правило восстановленного ускорения" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Первоначальное правило: начинайте с 6, затем увеличивайте до 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Перемещайте ползунок, чтобы установить собственную скорость. Пробел или " "прыжок убирают кактус." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6543,14 +6551,14 @@ msgstr "" "Включите JavaScript для воспроизведения реконструкции. Приведенный выше код " "и пояснения остаются читаемыми." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA вернул" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6569,7 +6577,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6582,7 +6590,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6596,7 +6604,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6609,7 +6617,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6619,12 +6627,12 @@ msgstr "" "{ph0}Начните с 6.{ph1} Добавляйте 0,001 при каждом обновлении без сбоев, " "пока скорость ниже 13.{ph2}{ph3}{ph4}{ph5}" -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Откройте лабораторию скорости →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Что делает каждая часть" @@ -6635,7 +6643,7 @@ msgstr "Что делает каждая часть" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6651,7 +6659,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6668,7 +6676,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6678,13 +6686,13 @@ msgstr "" "{ph0}03 · Вы{ph1}{ph2} меняете скорость и играете{ph3}{ph4} с оригинальным " "ускорением, затем выбираете свой собственный темп.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Ознакомьтесь со сценарием, проверками и тем, как попробовать анализ" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6694,7 +6702,7 @@ msgstr "" "REA проверил версию HTTP-браузера через локальное отладочное соединение и " "вернул загруженный {ph0}, включая его исходный код и дайджест." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6708,7 +6716,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6725,7 +6733,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6743,7 +6751,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6752,19 +6760,19 @@ msgstr "" "{ph0}Проверенный код скорости{ph1} · {ph2}Авторы Chromium · Лицензия " "BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Пример 02 · Калькулятор Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Воссоздайте кнопку % калькулятора." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6775,7 +6783,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6786,29 +6794,29 @@ msgstr "" "проверяем установленное приложение, чтобы определить, к какому числу " "применяется процентное соотношение." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Попробуйте произвести расчет" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Сбросить" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% от 200 = 20. Тогда 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Интерактивная иллюстрация проверяемого процентного правила." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6820,7 +6828,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6834,7 +6842,7 @@ msgstr "В этом примере {ph0}, а {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6850,7 +6858,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6862,7 +6870,7 @@ msgstr "" "Windows. Восстановите правила после + и ×, затем создайте небольшой " "калькулятор, который использует оба параметра.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "С +" @@ -6870,13 +6878,13 @@ msgstr "С +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Возьмем 10% от первого числа.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "С ×" @@ -6884,13 +6892,13 @@ msgstr "С ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Превратите 10% в 0,1200{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "От установленного приложения к рабочей кнопке %" @@ -6902,7 +6910,7 @@ msgstr "От установленного приложения к рабочей #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6919,7 +6927,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6931,12 +6939,12 @@ msgstr "" "правила{ph3}{ph4}, сверяет ветвь с исходным кодом Microsoft, затем " "попробуйте + и ×, указанные выше.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Посмотрите реальный код и то, как был проверен ответ" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6957,7 +6965,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6967,17 +6975,17 @@ msgstr "" "{ph0}Процент реализации{ph1} · {ph2}Тестовые примеры Microsoft{ph3} · " "Руководство по {ph4}встроенной настройке{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Ваше первое расследование" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Попробуйте REA в небольшом приложении." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6986,12 +6994,12 @@ msgstr "" "Загрузите наш пример Notes, проследите его экспорт CSV и проверьте один " "измененный ввод." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Попробуйте руководствоваться приведенным примером" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Хотите разобраться глубже?" @@ -7000,7 +7008,7 @@ msgstr "Хотите разобраться глубже?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7020,13 +7028,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Пример запроса · Веб-сайт" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Да, вот этот." @@ -7039,7 +7047,7 @@ msgstr "Да, вот этот." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7054,7 +7062,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7068,24 +7076,24 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Смотрите тематическое исследование DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "" "Для выполнения этапов настройки и анализа выберите свой целевой объект:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Программы с машинным кодом" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7094,17 +7102,17 @@ msgstr "" "Проверяйте функции, строки, ссылки и связи между вызовами функций в " "исполняемых файлах и библиотеках." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Руководство по анализу программ с машинным кодом" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript и Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7113,17 +7121,17 @@ msgstr "" "Отображайте модули, маршруты, IPC и собственные зависимости из папки " "приложения или архива ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Рабочие процессы приложений" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Активность в браузере и во время выполнения" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7132,12 +7140,12 @@ msgstr "" "Фиксируйте активность выбранного браузера или процесса, а затем сравнивайте " "результаты в разных запусках." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Руководство по наблюдению за браузером" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Есть вопросы?" @@ -7148,7 +7156,7 @@ msgstr "Есть вопросы?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7159,12 +7167,12 @@ msgstr "" "нами по Discord{ph3} или {ph4}откройте выпуск{ph5} GitHub, чтобы узнать об " "ошибках и запросах функций." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Вступить в сообщество" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7188,27 +7196,27 @@ msgstr "" "помощью вашего coding agent. Следуйте четким инструкциям и попробуйте " "интерактивные примеры с REA." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Скопировать запрос на установку REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Команда настройки копирования" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Следуйте инструкциям ручного калькулятора для анализа" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Процентный вопрос калькулятора копирования" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7217,37 +7225,37 @@ msgstr "" "Мини-игра про динозавров. Используйте кнопку перехода или нажмите пробел, " "пока игра сосредоточена." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Запрос на копирование результатов анализа динозавров" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Выберите способ расчета" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Запрос на анализ с помощью калькулятора копирования" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Запрос на копирование проекта веб-сайта" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Запрос на копирование реконструкции игры" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -7256,25 +7264,25 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Главная{ph1} страница / {ph2}Витрины{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Практический пример · Аутентификатор Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Откуда Аутентификатор{ph0}генерировать код авторизации?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7284,17 +7292,17 @@ msgstr "" "вычисления в Android APK , а затем перестройте их с помощью часов, которыми " "вы можете управлять." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 · Android · Официальный релиз APK · 6,9 МБ" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Посмотреть Aegis на GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "От APK до кода, который вы можете воспроизвести" @@ -7305,7 +7313,7 @@ msgstr "От APK до кода, который вы можете воспрои #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7323,7 +7331,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7341,7 +7349,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7353,14 +7361,14 @@ msgstr "" "Ознакомьтесь с кодом.{ph3}{ph4}Новая демонстрация браузера воспроизводит " "правило и проверяет его на соответствие общедоступным ссылкам.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "В этом тематическом исследовании" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7368,7 +7376,7 @@ msgstr "{ph0}Спросите своего агента{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7376,7 +7384,7 @@ msgstr "{ph0}Попробуйте воспользоваться генерат #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7384,7 +7392,7 @@ msgstr "{ph0}Найдите код с помощью REA{ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7392,7 +7400,7 @@ msgstr "{ph0}Ознакомьтесь с расчетом{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7400,20 +7408,20 @@ msgstr "{ph0}Проверьте реконструкцию{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Проверьте APK самостоятельно{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Спросите своего агента" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7432,21 +7440,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Копировать" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7456,14 +7464,14 @@ msgstr "" "Пример запроса для загруженного APK с настроенным анализом REA для Android. " "{ph0}Получите APK и настройки анализа ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Попробуйте воспользоваться генератором кода" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7475,33 +7483,33 @@ msgstr "" "кода номер блока объединяется с ключом учетной записи. Один и тот же ключ и " "блок генерируют один и тот же код." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Переведите стрелки часов на 60 секунд вперед" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Время" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "секунд" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Наши регулируемые примерные часы" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30-секундный блок" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Блок" @@ -7510,35 +7518,35 @@ msgstr "Блок" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 секунд{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Сгенерированный код" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Ключ учетной записи + блокировка → шесть цифр" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Примерное время, в секундах" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 секунд" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 секунд" @@ -7547,7 +7555,7 @@ msgstr "60 секунд" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7559,7 +7567,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7569,7 +7577,7 @@ msgstr "" "Ключ является фиксированным, общедоступные {ph0}тестовые данные RFC " "6238{ph1}. В демонстрации реализован расчет, восстановленный из APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7578,18 +7586,18 @@ msgstr "" "На диаграмме показан результат за 59 секунд. Включите JavaScript, чтобы " "изменить время." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Найдите код с помощью REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Сократите APK до трех классов" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7600,14 +7608,14 @@ msgstr "" "индикатору выполнения и импортированным учетным записям. TOTP означает " "одноразовый пароль, основанный на времени." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Подключите генератор к дисплею приложения" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7618,7 +7626,7 @@ msgstr "" "метод. При проверке {ph0} на дисплее отображается вызов {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7628,14 +7636,14 @@ msgstr "" "Запросы показывают сокращенный путь ввода. В именах результирующих классов " "отсутствует распространенный префикс {ph0}." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Ознакомьтесь с расчетом" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7649,7 +7657,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7657,7 +7665,7 @@ msgstr "{ph0}Временной блок 01{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7665,7 +7673,7 @@ msgstr "{ph0}02{ph1} Клавиша + блок" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7673,7 +7681,7 @@ msgstr "{ph0}03{ph1} Шесть цифр" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7685,7 +7693,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7699,7 +7707,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7713,7 +7721,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7724,7 +7732,7 @@ msgstr "" "отображения. Правая панель представляет собой пояснительное резюме. " "{ph0}Код Aegis соответствует GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Внутри генератора" @@ -7733,7 +7741,7 @@ msgstr "Внутри генератора" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7743,7 +7751,7 @@ msgstr "" "Выпущенный APK переводит {ph0} в {ph1}. REA следует за вызовом из {ph2} и " "возвращает это тело; исходный источник вызывает вспомогательный {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7760,20 +7768,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Сравните с соответствующим источником выпуска{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Проверьте реконструкцию" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7786,29 +7794,29 @@ msgstr "" "тестовых примеров{ph1}, включая границы временных блоков и коды, " "начинающиеся с нуля." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Примерное время" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Шестизначный код" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 секунд" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 секунды" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7818,17 +7826,17 @@ msgstr "" "Генератор также соответствует шести опубликованным ссылочным вариантам SHA-1" " в {ph0}RFC 6238{ph1}. Проверьте их реализацию в браузере:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Выполнять проверку ссылок" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Ознакомьтесь с демонстрационным расчетом" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7837,7 +7845,7 @@ msgstr "" "В контрольных случаях используются восьмизначные значения. Проверка также " "подтверждает их шестизначные результаты." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7846,14 +7854,14 @@ msgstr "" "Для проверки используются извлеченные методы Java и новая демонстрация. " "Android APK был проверен статически." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Проверьте APK самостоятельно" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7865,7 +7873,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7876,18 +7884,18 @@ msgstr "" "Выберите его с помощью {ph0} или {ph1}. В данном случае использовался JDK " "21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Наведите курсор REA на файл поставщика и проверьте APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7900,7 +7908,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7910,7 +7918,7 @@ msgstr "" "Следующий вопрос: {ph0}что происходит, когда в учетной записи используются " "восемь цифр или другой интервал времени?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Источники" @@ -7926,7 +7934,7 @@ msgstr "Источники" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7940,7 +7948,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" @@ -7948,7 +7956,7 @@ msgstr "" "{ph0}Справочные примеры RFC 6238{ph1} · {ph2}Демонстрационные тестовые " "данные{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7973,37 +7981,37 @@ msgstr "" "Проверить Aegis Андроид APK с REA, восстановить его шестизначный логин-код " "расчетов и попробовать реконструкция с регулируемым часы." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Тематическое исследование Aegis APK" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Скопировать запрос в качестве примера Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Следуйте инструкциям по вводу регистрационного кода" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Скопировать команду проверки APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -8012,26 +8020,26 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Главная{ph1} страница / {ph2}Витрины{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Тематическое исследование · DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Найдите флаг в{ph0}двоичном формате CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8042,19 +8050,19 @@ msgstr "" "преобразуйте его правила в уравнения и найдите входные данные, которые " "{ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "" "устройство для проверки флажков в маскированных квадратах · Простое · Linux " "x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Просмотрите оригинальную задачу" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "От двоичного кода к проверенному ответу" @@ -8065,7 +8073,7 @@ msgstr "От двоичного кода к проверенному ответ #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8083,7 +8091,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8101,7 +8109,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8113,7 +8121,7 @@ msgstr "" "Исправить!{ph3}{ph4}Уравнения решаются скриптом на Python. REA фиксирует " "исходную программу, принимающую результат.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." @@ -8121,14 +8129,14 @@ msgstr "" "Задача написана Джозефом и опубликована в официальном репозитории " "DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "В этом тематическом исследовании" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8136,7 +8144,7 @@ msgstr "{ph0}Найдите проверочный код{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8144,7 +8152,7 @@ msgstr "{ph0}Прочитайте одну маску{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8152,7 +8160,7 @@ msgstr "{ph0}Сборка в читаемый код{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8160,7 +8168,7 @@ msgstr "{ph0}Решите уравнения{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8168,20 +8176,20 @@ msgstr "{ph0}Проверьте ответ{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Попробуйте сами{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Найдите проверочный код" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8200,17 +8208,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Копировать" @@ -8221,7 +8229,7 @@ msgstr "Копировать" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8233,7 +8241,7 @@ msgstr "" " Объясните, как работают проверки, затем проверьте ответ с помощью исходной " "программы.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8242,12 +8250,12 @@ msgstr "" "Пример запроса с загруженной задачей, доступной локально, и подключенным " "поставщиком программ для анализа машинного кода." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Следуйте инструкциям по вводу для перехода к его функции" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8256,14 +8264,14 @@ msgstr "" "Ссылка дает агенту возможность провести расследование, даже несмотря на то, " "что исходные имена функций исполняемого файла были удалены." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Ознакомьтесь с программой проверки и двумя ее помощниками" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8275,7 +8283,7 @@ msgstr "" "маску, суммирует выбранные коды и сравнивает результат с сохраненным числом." " Его шаги размером {ph0} байт по {ph1} байт дают 26 масок." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8285,12 +8293,12 @@ msgstr "" "объекту сокращен для отображения; адреса относятся к импортированному " "изображению REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Одна проверка выявляет один символ" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8304,7 +8312,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." @@ -8312,7 +8320,7 @@ msgstr "" "При седьмой проверке выбирается только одна позиция. {ph0}Откройте " "рисунок{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Считайте маску и ее цель из двоичного файла" @@ -8321,7 +8329,7 @@ msgstr "Считайте маску и ее цель из двоичного ф #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8333,12 +8341,12 @@ msgstr "" " означает -21. Целью является целое число в порядке убывания. Вместе эти " "байты сообщают агенту, что {ph2}, так что этот символ равен {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "От инструкций к удобочитаемому чеку" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8349,7 +8357,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8357,7 +8365,7 @@ msgstr "{ph0}01{ph1} Начало" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8365,7 +8373,7 @@ msgstr "{ph0}02{ph1} Выберите" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8373,7 +8381,7 @@ msgstr "{ph0}03{ph1} Добавить" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8381,18 +8389,18 @@ msgstr "{ph0}04{ph1} Продвижение" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Сравнить" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA · выбранные оригинальные инструкции" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Читаемая сводка C · one-check" @@ -8400,7 +8408,7 @@ msgstr "Читаемая сводка C · one-check" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8408,7 +8416,7 @@ msgstr "{ph0}01 · Начните с нуля.{ph1} {ph2} содержит те #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8420,7 +8428,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8432,7 +8440,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8446,7 +8454,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8456,7 +8464,7 @@ msgstr "" "{ph0}05 · Сравнить с сохраненным целевым значением.{ph1} Вызывающий абонент " "получает сумму в {ph2}. Несоответствие становится {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8466,12 +8474,12 @@ msgstr "" "устройства. C - это пояснительная записка с описательными названиями и " "сглаженным циклом из 36 ячеек." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Решите 26 уравнений" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8483,13 +8491,13 @@ msgstr "" "Перекрывающиеся выборки дают уравнения, которые может решить небольшой " "скрипт на Python." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Отрывок из Python · solver" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8503,19 +8511,19 @@ msgstr "" "используется {ph0} с буквами, цифрами, символами подчеркивания и фигурными " "скобками. Полная загрузка включает все 26 масок и целевых объектов." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Загрузите полный решатель" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Проверьте ответ с помощью оригинальной программы" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8528,47 +8536,47 @@ msgstr "" "{ph1} приводит к получению первой суммы 1440 вместо 1441, и программа " "отклоняет ее." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Ввод" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Наблюдаемый результат" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Код выхода" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Флаг решателя" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Один персонаж изменен" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Отобразить восстановленный флаг и захваченные выходные данные" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA · исходный программный результат" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Флаг копирования" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8578,12 +8586,12 @@ msgstr "" "организаторами метаданных задачи, который был проверен после решения " "двоичной задачи." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Идентификация источника, цели и детали анализа" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8594,7 +8602,7 @@ msgstr "" "использованием REA 4.1.0 и Ghidra 12.1.4 на Linux x64. Двоичный файл " "представляет собой урезанный x86-64 ELF, объемом 15 248 байт." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8617,7 +8625,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8628,12 +8636,12 @@ msgstr "" "{ph2}Метаданные и флаг конкурса{ph3} · {ph4}Примечания к доказательствам " "REA{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Попробуйте сами" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8643,13 +8651,13 @@ msgstr "" " выше инструкцией, чтобы провести расследование с помощью своего агента, или" " запустите прилагаемый сценарий." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Терминал · решить и запустить" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8661,7 +8669,7 @@ msgstr "" "Для решения требуется Python и {ph0}. Для запуска исходного исполняемого " "файла требуется Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Настройте REA с помощью вашего агента по кодированию" @@ -8682,28 +8690,28 @@ msgstr "" " DOWNDERCTF. Найдите функции проверки, извлеките маски и сравните " "восстановленный флаг с исходной программой." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Практический пример проверки флагов CTF" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Запрос на копирование примера CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "" "Уравнение маски CTF; прокрутка по горизонтали на экранах меньшего размера" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8714,42 +8722,42 @@ msgstr "" "14. Только эта ячейка вносит свой вклад в сумму. Ее обязательный код - 55, " "что означает, что символ равен 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Выполните проверку CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Скопируйте сборку CTF" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Копируемый чек CTF для чтения" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Скопируйте выдержку из CTF-решателя" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Копировать восстановленный флаг" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Копирование команд решателя CTF" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -8758,25 +8766,25 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Главная{ph1} страница / {ph2}Витрины{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Тематическое исследование · DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Восстанавливаем DX-Ball {ph0}из его исполняемого файла." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8786,14 +8794,14 @@ msgstr "" "выпущенной в 1996 году. REA помогает агенту проверять оригинал, по одной " "функции за раз." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows для i386 · с · REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8805,14 +8813,14 @@ msgstr "" " вызывающие устройства и данные для чтения; проект реконструкции реализует и" " тестирует результат. {ph0}Открыть рисунок{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "В этом тематическом исследовании" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8820,7 +8828,7 @@ msgstr "{ph0}Проект{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8828,7 +8836,7 @@ msgstr "{ph0}Звуковая панорама{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8836,23 +8844,23 @@ msgstr "{ph0}Проверка результата{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Продолжайте работу{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "поддерживаемые функции C" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "сравнение с исходным кодом" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "функции с соответствующими скомпилированными байтами" @@ -8863,7 +8871,7 @@ msgstr "функции с соответствующими скомпилиро #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8873,12 +8881,12 @@ msgstr "" "Контрольная точка проекта: 7 октября 2026 года. {ph0}Журнал выполнения{ph1} " "работ · {ph2}Тестовый охват{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Проект до сих пор" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8893,12 +8901,12 @@ msgstr "" "которую можно играть, физикой мяча и весла, управлением усилениями и " "интеграцией Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Определение положения звука слева/справа при расчете" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8917,17 +8925,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Копировать" @@ -8938,7 +8946,7 @@ msgstr "Копировать" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8948,7 +8956,7 @@ msgstr "" "{ph0}\"{ph1}{ph2}Используйте REA, чтобы узнать, как DX-Ball рассчитывает " "расположение стереозвука. Объясните расчет и покажите код.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8959,7 +8967,7 @@ msgstr "" "файлом. В приведенном ниже исследовании показаны запросы REA и " "доказательства, лежащие в основе ответа." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8974,7 +8982,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8988,12 +8996,12 @@ msgstr "" "с плавающей запятой. Это несоответствие дало агенту конкретную причину " "продолжить расследование." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "Первое представление декомпилятора" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -9003,18 +9011,18 @@ msgstr "" "инструкций можно увидеть входные данные и вычисления, которые используются " "для этого вызова." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Ответы на три вопроса с помощью REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Восстановите недостающие входные данные" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9025,14 +9033,14 @@ msgstr "" "вызывающими элементами. Здесь {ph0} предоставляет целочисленный ввод, " "отсутствующий в представлении декомпилятора." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Следуйте за вызывающим абонентом, чтобы понять вводимые данные" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9043,12 +9051,12 @@ msgstr "" "предыдущих инструкциях tile_x масштабируется {ph0}на 30; добавление 20 дает " "экранную координату кирпича, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Считайте значения, стоящие за адресами памяти" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9058,12 +9066,12 @@ msgstr "" "панорамирования. Теперь у агента есть значения, необходимые для выражения на" " языке Си." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "От выводов REA до C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9074,7 +9082,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9082,7 +9090,7 @@ msgstr "{ph0}Вход 01{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9090,7 +9098,7 @@ msgstr "{ph0}02{ph1} Умножить" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9098,7 +9106,7 @@ msgstr "{ph0}03{ph1} Вычесть" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9106,18 +9114,18 @@ msgstr "{ph0}Шкала 04{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Возвращение" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Оригинальная выдержка из x86 ·" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Реконструированный C" @@ -9127,7 +9135,7 @@ msgstr "Реконструированный C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9147,7 +9155,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9164,7 +9172,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9182,7 +9190,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9199,7 +9207,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9212,7 +9220,7 @@ msgstr "" "преобразует результат в {ph4}; исходные сравнения с x86 проверяют " "возвращаемое значение." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9223,23 +9231,23 @@ msgstr "" "арифметике и возврату. В приведенный ниже полный список также включены " "промежуточные хранилища, настройка и очистка функций." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Полная сборка и подтверждающие доказательства" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "Результат REA · 0x406400–0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Что предоставляет вызывающий абонент" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9249,54 +9257,54 @@ msgstr "" "Функция brick-hit в {ph0} масштабирует свою координату плитки на 30, " "добавляет 20, а затем перемещает ее перед вызовом:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "То, что читают данные, устанавливает" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "Считывается байт REA, декодируемый как удвоение в порядке убывания" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Адрес" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Ценность" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Используется для" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Первое умножение" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Вычитание" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} изначально" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Сохраненные весы для поддонов" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9312,7 +9320,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9322,12 +9330,12 @@ msgstr "" "{ph0}Поддерживаемый источник{ph1} · {ph2}Заметки о расследовании и ссылки на" " доказательства{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Проверка восстановленной функции" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9337,12 +9345,12 @@ msgstr "" "совпадают с исходными, а скомпилированные байты соответствуют исполняемому " "файлу." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3 205 случаев нарушения поведения" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9353,12 +9361,12 @@ msgstr "" " сохраненным значением C. Они охватывают все целочисленные позиции от 0 до " "640 в пяти масштабах панорамирования: 0, 0,5, 1, 20 и -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 совпадающих байта" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9370,7 +9378,7 @@ msgstr "" "применения рассмотренных изменений и проверки констант, на которые даны " "ссылки." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9385,18 +9393,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Ознакомьтесь с подробностями воспроизведения компилятором{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Продолжайте расследование" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9408,7 +9416,7 @@ msgstr "" "восстановите их состояние и зависимости, а затем сравните реализацию с " "исходной." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9418,7 +9426,7 @@ msgstr "" "инструкциям по настройке DX-Ball project и укажите соответствующую исходную " "цель. Затем запустите:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "При оформлении заказа DX-Ball" @@ -9427,7 +9435,7 @@ msgstr "При оформлении заказа DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9441,7 +9449,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9457,7 +9465,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9482,7 +9490,7 @@ msgstr "" "поддерживаемых тестов на C, исходных x86 и сопоставления скомпилированных " "байтов функций." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9490,7 +9498,7 @@ msgstr "" "DX-Ball sound-исследование панорамирования; горизонтальная прокрутка на " "экранах меньшего размера" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9506,70 +9514,70 @@ msgstr "" "от исходного x86 в 3205 случаях и с помощью компилятора VC4.0 " "воспроизводится на соответствие 63 байтам." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Тематическое исследование реконструкции DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Запрос на копирование примера" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Следите за расчетом положения звука слева/справа" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Скопируйте фрагмент оригинальной сборки" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Функция копирования звука-панорамирование" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Скопируйте полную сборку sound-pan" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Скопировать команду анализа DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Главная{ph1} страница / Витрины" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "Тематические исследования REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9578,17 +9586,17 @@ msgstr "" "Android, игры, Electron и конкурс CTF с кодом, цифрами и проверенными " "результатами." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android · Анализ APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Как аутентификатор генерирует код входа в систему" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9599,22 +9607,22 @@ msgstr "" "Проследите за методами генерации с помощью REA, затем посмотрите на " "демонстрационные часы, чтобы понять, почему код меняется каждые 30 секунд." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Ознакомьтесь с тематическим исследованием Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF · Анализ программ с машинным кодом" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Решите проблему с проверкой флага CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9625,22 +9633,22 @@ msgstr "" "функции, преобразуйте маски и суммы в уравнения, затем проверьте флажок " "\"решено\" с помощью исходной программы." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Ознакомьтесь с тематическим исследованием CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Нативная · Реконструкция" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball рассчитывает положение звука слева/справа" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9652,22 +9660,22 @@ msgstr "" "приводят к созданию небольшой функции C, которая проверяется на соответствие" " исходному поведению и всем 63 скомпилированным байтам." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Ознакомьтесь с тематическим исследованием DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron · Отслеживание объектов" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Как Notion копирует текст и HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9679,22 +9687,22 @@ msgstr "" "посмотрите, как маленький HTML-маркер связывает данные расширенного блока с " "копией." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Ознакомьтесь с тематическим исследованием Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS · Реконструкция" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Как TH04 целится в кольцо из пуль" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9705,17 +9713,17 @@ msgstr "" " его операции умножения, деления и координации с понятным C++, а затем " "посмотрите, как они создают кольцо, направленное на игрока." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Ознакомьтесь с тематическим исследованием TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Пошаговые руководства" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9724,7 +9732,7 @@ msgstr "" "В руководствах описываются собственные вычисления, экспорт Electron и запрос" " к браузеру. Каждое из них начинается с запроса и конкретной цели." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Ознакомьтесь с руководствами" @@ -9744,12 +9752,12 @@ msgstr "" "Android authenticator, DX-Ball, Notion, TH04 и средства проверки флага " "DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -9758,25 +9766,25 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Главная{ph1} страница / {ph2}Витрины{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Тематическое исследование · Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Как Notion копирует{ph0}текст и HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9785,12 +9793,12 @@ msgstr "" "Проследите вызов буфера обмена из API страницы Notion, через предварительную" " загрузку и основной процесс, в программу записи буфера обмена Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Рабочий стол Notion 7.6.1 · JavaScript · REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Мост внутри настольного пакета Notion" @@ -9802,7 +9810,7 @@ msgstr "Мост внутри настольного пакета Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9819,7 +9827,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9836,7 +9844,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9854,7 +9862,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9865,13 +9873,13 @@ msgstr "" "записывает предоставленный текст и HTML-код.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Один канал соединяет две стороны: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9881,14 +9889,14 @@ msgstr "" "загрузки и в основном процессе. При разрешении оболочек обнаруживаются " "вызовы Electron, стоящие за этими именами." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "В этом тематическом исследовании" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9896,7 +9904,7 @@ msgstr "{ph0}Следуйте по мосту из буфера обмена{ph1 #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9904,19 +9912,19 @@ msgstr "{ph0}Сохранение структуры блока{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Дополнительные примеры и источники{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Где выполняется операция копирования?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9936,17 +9944,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Копировать" @@ -9957,7 +9965,7 @@ msgstr "Копировать" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9968,7 +9976,7 @@ msgstr "" "текст и HTML в системный буфер обмена. Показывайте код на каждом " "шаге.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9977,12 +9985,12 @@ msgstr "" "Пример запроса с локальным пакетом приложений Notion, доступным вашему " "программисту." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA находит, с чего начать чтение" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9993,13 +10001,13 @@ msgstr "" "доступный для страницы, и вызов, который отправляет запрос IPC. Оба " "результата представлены с диапазонами исходных текстов в уменьшенном пакете:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA выводы → два места для открытия" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10014,7 +10022,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10028,12 +10036,12 @@ msgstr "" "точную информацию для поиска в основном пакете. В четырех приведенных ниже " "выдержках показан маршрут, по которому он подключается." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Четыре коротких фрагмента кода" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -10042,13 +10050,13 @@ msgstr "" "Упрощенный по сравнению с пакетным JavaScript, с удобочитаемыми именами " "переменных. Несвязанные элементы опущены." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Начните с API, доступного для этой страницы" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10058,13 +10066,13 @@ msgstr "" "Этот участник предоставляет название канала. Реализация {ph0} сообщает нам, " "как запрос завершает обработку страницы." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Устраните оболочку предварительной загрузки" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10074,14 +10082,14 @@ msgstr "" "Возвращаемая функция перенаправляет аргументы через IPC запроса и ответа " "Electron. Теперь мы можем искать {ph0} на стороне основного процесса." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Проверьте, как зарегистрирован получатель" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10091,12 +10099,12 @@ msgstr "" "Основной процесс использует другую оболочку. Его метод {ph0} регистрирует " "{ph1} для этого канала." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Найдите запись и проверьте ее отправителя" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10107,13 +10115,13 @@ msgstr "" "данные в API буфера обмена Electron. Канал и две разрешенные оболочки " "подключают открытый метод к этому вызову." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Как скопированный блок сохраняет свою структуру?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10124,27 +10132,27 @@ msgstr "" "данные блока локально и вставляет идентификатор в скопированный HTML-код, " "чтобы связать их." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "HTML-ссылки на сохраненные данные блоков" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Прочитайте HTML-идентификатор" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Найдите тот же локальный идентификатор" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Восстановить данные блока Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10154,7 +10162,7 @@ msgstr "" "восстанавливает данные блока, если идентификаторы совпадают; устаревшая " "запись возвращает только текст и HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10163,24 +10171,24 @@ msgstr "" "При вставке Notion ищет HTML-идентификатор и сравнивает его с сохраненной " "копией. Совпадающие идентификаторы восстанавливают данные блока." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Формат буфера обмена, записанный из веб-ресурсов, кэшированных 13 июля 2026 " "года." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Дополнительные примеры и источники" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Другой пример: таблицы уценки" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10189,12 +10197,12 @@ msgstr "" "Notion преобразует Markdown в блочные данные. В этом примере показано, как " "таблица преобразуется в заголовок и строки данных." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Таблица с помощью анализатора уценки Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10203,13 +10211,13 @@ msgstr "" "Записанный вывод из извлеченного анализатора Markdown. Таблица преобразуется" " в строки и ячейки." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Другой путь: автономное подключение к SQLite" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10223,7 +10231,7 @@ msgstr "" "визуализации, а другой - служебному процессу SQLite. Последующие пакеты " "инструкций и результаты передаются через этот порт." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10233,7 +10241,7 @@ msgstr "" " данных и почему при отслеживании только первоначального IPC-запроса не " "учитывается последующий диалог." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Источники и как читать выдержки" @@ -10241,7 +10249,7 @@ msgstr "Источники и как читать выдержки" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10259,7 +10267,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10275,7 +10283,7 @@ msgstr "" "модули и небольшие модули управления; их выходные данные описывают эти " "тесты, а не захваченный сеанс пользовательского интерфейса рабочего стола." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10290,7 +10298,7 @@ msgstr "" "подключаются путем считывания их реализаций-оболочек в пакете." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10308,7 +10316,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10322,7 +10330,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10348,52 +10356,52 @@ msgstr "" "IPC-оболочку и основной процесс, с краткими выдержками кода и ознакомьтесь с" " его богатым форматом буфера обмена." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Тематическое исследование Notion Electron" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Скопировать запрос на анализ Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Скопировать фрагмент предварительной загрузки Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Скопировать фрагмент кода Notion для вызова оболочки" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Скопировать фрагмент оболочки обработчика Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Скопировать фрагмент приемника из буфера обмена Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Восстановление расширенных данных буфера обмена при вставке" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Наверх" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Перейти к содержанию" @@ -10402,25 +10410,25 @@ msgstr "Перейти к содержанию" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Главная{ph1} страница / {ph2}Витрины{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Тематическое исследование · Тохоу 4: История земли лотосов" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Реконструкции TH04 с{ph0}узоры пули." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10430,17 +10438,17 @@ msgstr "" "проверки исходной функции DOS, затем следуйте ее инструкциям на " "удобочитаемом C++." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 · 16-разрядная версия DOS · C++ и сборка" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Посмотреть реконструкцию TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "От оригинальных инструкций к проверенному источнику" @@ -10451,7 +10459,7 @@ msgstr "От оригинальных инструкций к проверенн #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10468,7 +10476,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10486,7 +10494,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10502,7 +10510,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10514,7 +10522,7 @@ msgstr "" "записанных компилятором, проверки охватывают код генерации маркеров, " "содержащий этот вспомогательный элемент.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10523,14 +10531,14 @@ msgstr "" "REA возвращает исходный код и результаты его анализа. Проект TH04 " "предоставляет поддерживаемые проверки исходного кода и компилятора." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "В этом тематическом исследовании" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10538,7 +10546,7 @@ msgstr "{ph0}Кольцо с пулями{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10546,7 +10554,7 @@ msgstr "{ph0}Что возвращает REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10554,7 +10562,7 @@ msgstr "{ph0}Сборка на C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10562,18 +10570,18 @@ msgstr "{ph0}Проверка источника{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Полный проект{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Как кольцо нацеливается на игрока" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10593,16 +10601,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодирующий агент" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Копировать" @@ -10613,7 +10621,7 @@ msgstr "Копировать" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10624,7 +10632,7 @@ msgstr "" "пуль и направляет его на игрока. Объясните расчет и покажите " "код.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10634,7 +10642,7 @@ msgstr "" "локально." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10648,7 +10656,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10658,12 +10666,12 @@ msgstr "" "Иллюстрация восстановленного математического расчета угла для счета 16, " "направления игрока 40 и поворота шаблона 0. {ph0}Открыть рисунок{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Шаблон запуска в восстановленном источнике" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Нападение Элли на кольцо · отрывок из источника" @@ -10672,7 +10680,7 @@ msgstr "Нападение Элли на кольцо · отрывок из и #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10682,13 +10690,13 @@ msgstr "" "В этих строках выбирается шаблон перед настройкой сложности и " "производительности. {ph0}Прочитайте источник атаки{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Что возвращает REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10700,12 +10708,12 @@ msgstr "" " возвращает свои инструкции, псевдокод и ссылки. Три части этого результата " "объясняют закономерность." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Проверьте образ DOS, прежде чем читать его код" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10715,7 +10723,7 @@ msgstr "" "предоставленному исполняемому файлу. Путь, указанный выше, сокращен для " "отображения." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Прочитайте надпись на кольце \"умножай и дели\"" @@ -10723,7 +10731,7 @@ msgstr "Прочитайте надпись на кольце \"умножай #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10736,12 +10744,12 @@ msgstr "" "источников, которые указаны в поле {ph2}. Полная последовательность " "приведена ниже." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Найдите, где рисунок поворачивается в сторону игрока" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10754,12 +10762,12 @@ msgstr "" "кольцевому углу. Имена источников делают эти адреса удобочитаемыми; REA " "позволяет агенту проверять исходные операции, стоящие за ними." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "От ассемблера к удобочитаемому C++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10772,7 +10780,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10780,7 +10788,7 @@ msgstr "{ph0}Индекс 01{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10788,7 +10796,7 @@ msgstr "{ph0}02{ph1} Пространство" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10796,7 +10804,7 @@ msgstr "{ph0}03{ph1} Цель" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10804,18 +10812,18 @@ msgstr "{ph0}04{ph1} Вращать" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Магазин" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA · оригинальные 16-разрядные инструкции" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Читаемый C++ · краткое описание aimed-ring" @@ -10823,7 +10831,7 @@ msgstr "Читаемый C++ · краткое описание aimed-ring" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10838,7 +10846,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10854,7 +10862,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10869,7 +10877,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10884,7 +10892,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10898,7 +10906,7 @@ msgstr "" "же, как это происходит при преобразовании беззнаковых байт. Окружающий " "источник также преобразует этот угол и скорость в скорость вращения." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10910,7 +10918,7 @@ msgstr "" "Приведенные ниже проверки компилятора применяются к поддерживаемому " "исходному тексту в связанном проекте." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Ознакомьтесь с сохраняемым кольцом и прицелитесь в источник" @@ -10927,7 +10935,7 @@ msgstr "Ознакомьтесь с сохраняемым кольцом и п #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10937,12 +10945,12 @@ msgstr "" "{ph0}Кольцевой макрос{ph1} · {ph2}Цель и источник скорости{ph3} · " "{ph4}Представление угла{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Проверка поддерживаемого источника" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10952,12 +10960,12 @@ msgstr "" "маркеров, включая этот помощник, с помощью закрепленного набора инструментов" " Turbo C++ 4.0J." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 совпадающих байта" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10966,12 +10974,12 @@ msgstr "" "Скомпилированный код генерации маркеров соответствует 2139-байтовому разделу" " исходного исполняемого файла." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Две чистые сборки" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10984,7 +10992,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." @@ -10992,59 +11000,59 @@ msgstr "" "Записано 3 октября 2026 года. {ph0}Ознакомьтесь с проверками " "компилятора{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Идентификация цели и объем анализа" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Первоначальная цель" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0} , 156 258 байт, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Вспомогательная запись" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} в загруженном изображении REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Смещение исходного файла" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, возвращаемый параметром {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Проверка записанного кода" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 · 7 октября 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11055,7 +11063,7 @@ msgstr "" "отображение и перекрывающееся перемещение." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11070,7 +11078,7 @@ msgstr "" "приведенные выше, находятся в этих сообщенных диапазонах." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11087,7 +11095,7 @@ msgstr "" " в манифесте репозитория, при этом независимое происхождение нетронутого " "дампа все еще открыто." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11098,12 +11106,12 @@ msgstr "" "хронометраж и поведение аппаратного обеспечения PC-98 проверяются во время " "выполнения в проекте реконструкции отдельно." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "Полная реконструкция TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11116,7 +11124,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11128,7 +11136,7 @@ msgstr "{ph0}Изучите репозиторий TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11144,7 +11152,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11160,7 +11168,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11186,22 +11194,22 @@ msgstr "" "за сборкой и восстановленным C++, чтобы увидеть, как расставлено кольцо пуль" " и как они нацелены на игрока." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "На этой странице" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "Тематическое исследование по маркировке TH04" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Скопировать запрос в качестве примера TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11209,7 +11217,7 @@ msgstr "" "TH04 фиксированные и нацеленные пулевые кольца; прокрутка по горизонтали на " "экранах меньшего размера" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11223,27 +11231,27 @@ msgstr "" "игрока. В обоих случаях расстояние между точками составляет 16 угловых " "единиц, или 22,5 градуса." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Скопировать шаблон запуска TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Следуйте расчету прицельного кольца TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Скопируйте фрагмент сборки TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Копировально-читаемый расчет прицельного кольца" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Наверх" @@ -11354,7 +11362,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Фиксированная скорость: {speed} вращения." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11364,7 +11372,7 @@ msgstr "" "контролируемой проверке в оригинальной игре, если округлить их до трех " "знаков после запятой." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11731,592 +11739,600 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Одинаковое расстояние: 256 ÷ 16 = 16 угловых единиц = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Примеры" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Блог" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Начать" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Руководства" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Исходный код" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Лицензия MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Вступить в сообщество" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Подписаться в X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA · выбранный источник скрипта" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Исходный код" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Ожидаемый результат форматирования" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Инструкции" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Вызывающий абонент" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Константы" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Функция C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Кнопка" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API предварительной загрузки" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "МПК" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Файл CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Ваш щелчок" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Захваченный запрос" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Экспорт скрипта" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA результат · сводка.выдержка из ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA выдержка из инструкции · 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA запрос вызывающего абонента · 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "" "Результаты в байтах REA · интерпретируются как удвоения в порядке убывания" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Восстановленный отрывок из C ·" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Посмотрите, как работает REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Витрины →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Выбранные настройки из проверенного скрипта" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Читаемая сводка об обработчике %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA · выбранные оригинальные инструкции" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Идентификаторы операторов · Исходный код Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Подписывайтесь на @reatools на X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Агент → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → агент · выбранные результаты" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → агент · методы и вызывающие абоненты" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA · выбранный декомпилированный Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Читаемое резюме · интерпретация агента" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA · generateOTP, полный корпус" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Скачать Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Скачать Android analysis provider" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Агент → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → агент · выбранные результаты" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → агент · выбранные инструкции" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Агент → REA · прочитано_байт" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → агент · седьмые записи" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Оригинальный исполняемый файл · SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Скачайте оригинальную игру challenge" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Скачать решатель" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "Результат REA · фрагмент псевдокода" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Агент → REA · функция {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → агент · отрывок из инструкции" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → агент · отрывок из сообщения о звонящем" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Агент → REA · два {ph0}запроса на чтение в байтах" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Результаты в байтах REA · декодируются как двойные" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Начните со своей собственной цели" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Генерация кода" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Восстановленное правило" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Регулируемые часы" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Двоичный" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Проверяющий код" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Уравнения" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Правильно!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Выполнимый" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Выводы REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Восстановленный C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Утверждение" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Упакованное приложение" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Открытый API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Оболочки IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Буфер обмена" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Исходный код DOS" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Инструкции по REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Расчет угла наклона" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Пулевое кольцо" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Открытый API страницы" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Вызов IPC средства визуализации" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Отправлено в системный буфер обмена" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Сохранено локально с помощью Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Ввод данных для уценки" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Вывод структурированного синтаксического анализатора · выдержка" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Проанализируйте свое собственное приложение" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Агент → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → агент · выбранные поля" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Агент → REA · функция {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → агент · отрывок из инструкции" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Результат той же функции · выдержка из aim" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Соответствующий поддерживаемый C++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Кольцевой макрос · Ветвь TH04, фрагмент" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Угол и скорость · выдержка из источника" @@ -12348,7 +12364,7 @@ msgstr "Перевод обновляется. Пока прочтите эту #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12366,7 +12382,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12387,7 +12403,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12408,7 +12424,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12427,7 +12443,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12446,7 +12462,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12457,14 +12473,14 @@ msgstr "" "сайт для меня.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Реконструкция · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12475,7 +12491,7 @@ msgstr "" "кодирующий агент и ознакомьтесь с предлагаемыми изменениями." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12484,7 +12500,7 @@ msgstr "Приведенный пример · {ph0} и npm · Ваш кодир #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12503,7 +12519,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12519,7 +12535,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12538,7 +12554,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12549,7 +12565,7 @@ msgstr "" "форматирования в {ph7} и записывает файл.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12564,7 +12580,7 @@ msgstr "{ph0} · строки 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12578,7 +12594,7 @@ msgstr "" "результат.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12590,7 +12606,7 @@ msgstr "" "{ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12598,7 +12614,7 @@ msgstr "{ph0} · CSV форматировщик" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12608,7 +12624,7 @@ msgstr "" "входит {ph1}npm ." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12616,7 +12632,7 @@ msgstr "У вас нет {ph0} или вы не уверены?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12629,7 +12645,7 @@ msgstr "" "найдена\", установите {ph1} 24 LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12643,7 +12659,7 @@ msgstr "{ph0} · пример выдержки из источника" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12654,9 +12670,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12664,7 +12680,7 @@ msgstr "{ph0} · пример источника" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12679,7 +12695,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12692,7 +12708,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12705,7 +12721,7 @@ msgstr "Например: {ph0}почему калькулятор выдаёт #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12716,7 +12732,7 @@ msgstr "" "{ph3} дают 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12725,7 +12741,7 @@ msgstr "REA · загружено {ph0} · выбранные строки" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12743,7 +12759,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12762,7 +12778,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12775,28 +12791,28 @@ msgstr "" "небольшую демонстрацию, в которой можно менять время.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} · Член API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} · Помощник IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "main/{ph0} · помощник обработчика" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12806,12 +12822,1419 @@ msgstr "main/{ph0} · приемник буфера обмена" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Начать {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Переключить на светлую тему" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Переключить на тёмную тему" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Для изучения тел запросов и ответов HTTP используйте {ph0}Fiddler " +"Everywhere: захваты SAZ, MCP и общедоступные навыки{ph1}. Экспортируйте SAZ " +"??? HAR 1.2 для получения Evidence захвата в REA без подключения к сети или " +"подключите MCP-сервер Everywhere, чтобы исследовать записанный трафик вместе" +" с агентом." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Специализация моделей{ph0}Эссе" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Нужна ли для обратной разработки более крупная модель?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Что реконструкция Touhou помогает понять об универсальных и " +"специализированных моделях и обучении на обратной связи от компилятора." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Автор N0zoM1z0 · 13 октября 2026 г." + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Перейти к содержанию" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" +"{ph0}Главная страница{ph1} / {ph2}Блог{ph3} / Модели и реверс-инжиниринг" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Эссе" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Нужна ли реверс-инжинирингу модель большего размера?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Автор N0zoM1z0 · 13 октября 2026 г." + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Главное" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Возможности модели влияют на то, какие гипотезы может предложить ИИ-" +"агент.{ph1} На последующих занятиях решались проблемы, которые ранее " +"оставались нерешенными." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Знакомый компилятор предлагает конкретные шаблоны для изучения " +"специализированной модели.{ph1} Некоторые точные совпадения машинного кода " +"зависят от конкретных многократно используемых шаблонов исходного кода." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Включите знания репозитория в справедливое сравнение.{ph1} Меньшая " +"модель с хорошим извлечением знаний может уже иметь достаточно информации " +"для достижения прогресса." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Обучите модель выбирать следующий полезный эксперимент и протестируйте " +"ее средство проверки.{ph1} Обратная связь полезна только в той степени, в " +"которой средство проверки проверяет правильные вещи." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Оцените проверенные результаты реконструкции, а также время и " +"стоимость.{ph1} Это то, что я хочу измерить для всего рабочего процесса ИИ-" +"агента." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "В этой статье" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Что изменили более сильные модели{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Зачем специализироваться?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Где следует хранить этот опыт?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Изучаем следующий полезный эксперимент{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Обратное проектирование и обучение с подкреплением{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Когда программа проверки ошибается{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Сравнение, которое стоит провести{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}О каком ИИ-агенте идет речь?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Что изменили более сильные модели" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"С августа 2026 года я изучаю, какой объем реверс-инжиниринга может провести " +"агент, имея доступ к программе и способ проверки ее работы. Большая часть " +"моего опыта связана с реконструкцией игр, особенно Touhou. Поскольку я менял" +" модели, в репозиториях фиксировалось, что удалось восстановить в каждом " +"сеансе." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Большая часть этой работы направлена на точную реконструкцию: мы компилируем" +" поддерживаемый исходный код с помощью исторической цепочки инструментов с " +"фиксированными версиями и проверяем, воспроизводит ли он целевую функцию. " +"Когда более поздняя модель оказывается успешной там, где предыдущие работы " +"застопорились, изменения в исходном коде показывают, что сделало этот " +"прогресс возможным." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Временным переменным требовалось перекрывающееся время жизни." + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Большая часть логики функции атаки TH09 уже была реконструирована, но " +"компилятор по-прежнему сохранял временные результаты иначе, чем оригинал. " +"Оставшаяся проблема заключалась в том, как долго эти результаты должны " +"оставаться живыми и когда их хранилище можно будет использовать повторно." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Запись сеанса {ph0}GPT-6-Sol{ph1} сообщила об этом несоответствии после " +"тестирования нескольких обычных схем исходного кода. Когда {ph2}GPT-6.1-Sol " +"снова изучил проблему{ph3}, он предложил полезную гипотезу о времени жизни " +"этих временных переменных." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"Функция выдавала временные результаты и копировала их в позиции анимации. В " +"C++ временный результат остается активным до тех пор, пока выражение, " +"использующее его, не завершится. Группировка реальных операций в одно " +"выражение сохраняла эти результаты вместе, поэтому компилятор больше не мог " +"повторно использовать одно и то же хранилище для всех них." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Один из результатов по-прежнему разделял хранилище со значением, которое " +"позже использовалось для проверок на коллизии. Предоставление этому значению" +" собственного времени жизни решило оставшееся перекрытие. После нескольких " +"целевых экспериментов {ph0}чистая перекомпиляция из исходного кода " +"подтвердила, что полная функция соответствует{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Меня интересует, как открытие и испытания поддержали друг друга. Гипотеза о " +"времени жизни временных объектов дала агенту ИИ новое направление. Отзывы " +"компилятора помогли усовершенствовать эту гипотезу и привести ее в " +"соответствие с исходным кодом." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Другой граф потока управления" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Вторая функция TH09 показывает, почему это новое направление может иметь " +"значение. Здесь препятствием было то, как несколько филиалов делились своей " +"итоговой работой. В более ранней работе {ph0}GPT-6.1-Sol{ph1} части функции " +"совпадали, но ветви по-прежнему соединялись иначе, чем в оригинале." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra изменил окружающий граф потока управления{ph1}. Основные " +"пути теперь вели к общему финальному обновлению и возврату. В этой исходной " +"структуре компилятор объединил ветки так же, как в оригинале. Полная функция" +" совпала, и {ph2}отдельная проверка перестроения подтвердила это{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Изменение представления открыло более продуктивное пространство " +"поиска.{ph1} Оба случая дают мне повод серьезно отнестись к общим " +"возможностям модели: агент может долго пробовать локальные варианты, прежде " +"чем найти лучший способ выразить окружающую работу." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"В то же время более поздние сеансы начинались с более раннего источника и " +"фиксировали сбои. Этот накопленный труд был частью их преимущества. История " +"позволяет нам проверять открытия и их проверки; контролируемое сравнение " +"поможет отделить эффект модели от унаследованного ею опыта." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Именно это делает вопрос для меня интересным. Некоторый прогресс был " +"достигнут благодаря поиску нового представительства. Большая часть " +"оставшейся работы заключалась в тестировании различных вариантов исходного " +"кода на знакомом компиляторе. Насколько это требует широких умственных " +"способностей? Насколько многому может научиться модель, неоднократно работая" +" с этим компилятором и кодом?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Почему специализированная модель ИИ может преуспеть?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou дает нам конкретную причину ожидать, что этот опыт поможет. Большая " +"часть игрового кода принадлежит одному и тому же автору, ZUN, поэтому " +"повторяющиеся привычки — разумное исходное предположение. Репозитории " +"подтверждают это полезными примерами: связанные циклы и вспомогательные " +"механизмы служат источником гипотез для разных игр." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Эти исходные шаблоны становятся более конкретными, когда мы подключаем " +"компилятор. В конкретной версии и наборе опций небольшие изменения в " +"исходном коде могут привести к повторяющимся различиям в машинном коде. " +"Некоторые из этих различий на удивление неясны." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Например, в TH095 {ph0}даже имя локальной переменной может влиять на то, где" +" VC7.1 ее хранит{ph1}. Перемещение его декларации не решило проблему с " +"расположением хранилища. Однако более ранняя фоновая функция выявила шаблон " +"именования, который повлиял на выбор компилятора. Это предложило более " +"многообещающую гипотезу для {ph2}реконструкции {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Повторное использование этого шаблона для переменной размера файла позволило" +" получить требуемый макет без увеличения объема памяти. Затем полная функция" +" совпала." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Это очень специфическая деталь, о которой модель ИИ общего назначения может " +"не знать, когда впервые сталкивается с проблемой. Модель, специализированная" +" для этого компилятора, могла бы увидеть множество таких случаев и " +"определить, какие варианты исходного кода стоит протестировать в первую " +"очередь." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Эта возможность особенно очевидна в задачах окончательного сопоставления, " +"где мы уже понимаем поведение. Затем мы спрашиваем, какую обычную структуру " +"исходного кода этот компилятор превращает в наблюдаемые инструкции. " +"Специализация может помочь модели более эффективно предлагать эти формы, в " +"то время как цель по-прежнему определяет, какие гипотезы выживут." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Полезные шаблоны должны сохранять свой контекст. TH08 использует более " +"раннюю версию Visual C++, чем TH095 и TH09. TH04 использует другой " +"компилятор эпохи DOS. Его {ph0}реконструкция кода игрока{ph1} требовала " +"различных гипотез о шаблонах исходного кода и о том, как скомпилированный " +"код связывается с исполняемым файлом. Наличие одного и того же автора дает " +"нам первоначальное ожидание, но каждая цель говорит нам, применимо ли оно. " +"Специализированная модель должна будет различать эти контексты." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Где следует хранить этот опыт?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Прежде чем принять решение об обучении этим шаблонам посредством обучения " +"моделей, я бы посмотрел на знания, которые мы уже храним в репозитории. В " +"{ph0}предыдущем эссе{ph1} я писал о том, что оно стало рабочей памятью " +"проекта. Эта память включает в себя уроки компилятора, а также исходники и " +"неудачные эксперименты, которые сделали их полезными." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Получив эту запись, агент может начать с известного результата и проверить, " +"как мы его достигли. Это также позволяет избежать альтернатив, которые уже " +"потерпели неудачу в том же контексте. Начальная точка улучшается без " +"изменения обученных параметров модели." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"При реконструкции функции TH09 по созданию врагов сеанс {ph0}GPT-6-Luna-" +"max{ph1} взял гипотезу из соответствующего исходного кода TH08. Этот более " +"ранний код предлагал, как организовать цикл и обрабатывать сбои внутри него." +" Собственные доказательства TH09 предоставили подробности, касающиеся " +"конкретной игры. Перестройки из исходного кода подтвердили, что вся функция " +"совпадает." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"Модель не знала об этой особенности компилятора\" и \"модель не могла" +" ее использовать\" — это разные проблемы.{ph1} Извлечение может решить " +"первую, но превращение этого факта в полезного кандидата все равно требует " +"работы. И если исходный код-кандидат терпит неудачу, модель должна решить, " +"что означает результат для ее следующей попытки. Знание соответствующей " +"закономерности — это только начало этого процесса." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"По этой причине я бы включил в любое сравнение меньшую модель ИИ общего " +"назначения с хорошей воспроизводимостью. Предоставление ему той же " +"библиотеки опыта поможет нам определить, что дает обучение: лучшее " +"генерирование кандидатов, лучшие решения после обратной связи или и то, и " +"другое." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Изучаем следующий полезный эксперимент" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Эти решения после получения обратной связи — это то, что мне больше всего " +"хотелось бы изучить. При агентной реконструкции модель предлагает объяснение" +" и проверяет его на соответствие программе. Даже если исходный код-кандидат " +"дает сбой, результат может сузить оставшиеся возможности и предложить более " +"полезный следующий эксперимент." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Снова рассмотрим пример временных результатов. Его окончательный источник " +"показывает сработавшую схему, но путь к этому источнику содержит больше " +"информации. Каждый из следующих экспериментов помог определить, что еще " +"необходимо изменить." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Эксперимент" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Чему нас научил его результат" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Попробуйте другой способ скопировать результаты" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Код копирования меняется, но функция по-прежнему отличается." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Используйте возвращаемые значения напрямую" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"Копирование следует исходному шаблону, но временное хранилище все равно " +"отличается." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Сохраняйте все временные переменные действительными одновременно" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Они получают отдельное хранилище, но одно из них по-прежнему перекрывает " +"значение, используемое позже для проверок коллизий." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Держите значение проверки столкновений отдельно" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Чистая перекомпиляция из исходного кода подтверждает полное совпадение." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Избранные эксперименты из приведенной выше реконструкции атакующей функции, " +"сгруппированные по тому, чему они нас научили." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Запись обучения, в которой сохраняется эта последовательность, может научить" +" большему, чем один только окончательный источник. Он связывает каждое " +"предлагаемое изменение с наблюдаемым результатом и следующим решением. " +"Сохранение неэффективных вариантов также имеет значение: они сообщают " +"следующему агенту, какие гипотезы уже были проверены в этом контексте." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Я бы хотел, чтобы модель научилась использовать обратную связь.{ph1} " +"Нейтральный результат — повод пересмотреть вариант; измененное " +"несоответствие может указывать на другую причину. Когда локальные изменения " +"перестают быть информативными, агент должен иметь возможность вернуться к " +"исходному представлению или снова проверить доказательства." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Чтобы научиться делать такой выбор, требуется автономия. Иногда полезным " +"следующим шагом является проверка другого вызывающего объекта, а не " +"компиляция еще одного редактирования. Жесткая последовательность необходимых" +" переписываний устранит этот выбор вместе с частью поведения, которому мы " +"хотим, чтобы модель научилась." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "Чем реверс-инжиниринг интересен для обучения с подкреплением" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Реконструкция с заданными границами даёт практическую среду для изучения " +"этих решений. Когда версии цели и компилятора зафиксированы, многие " +"эксперименты с исходным кодом дают быструю, воспроизводимую обратную связь. " +"Агент может скомпилировать кандидат, изучить различия и выбрать следующий " +"шаг." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Обучение с подкреплением могло бы тренировать этот процесс принятия решений " +"посредством получаемой обратной связи. Кандидат, принятый посредством " +"определенной проверки, дает нам конкретный результат, а последовательность " +"попыток позволяет нам наблюдать, сколько работы потребовалось для его " +"достижения." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Уже есть исследования, подтверждающие это направление. " +"{ph0}LLM4Decompile{ph1} изучает модели, предназначенные для декомпиляции. " +"{ph2}AutoDecompiler{ph3} обучает многоэтапному уточнению с использованием " +"компилятора и обратной связи при выполнении. Их исследования сосредоточены " +"на функциональном восстановлении. В этой работе я бы использовал их в " +"качестве отправной точки для решения соответствующей задачи по поиску " +"источника, соответствующего выводам исторического компилятора." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Однако для решения такой четко определенной задачи нам, возможно, сначала " +"придется установить, какими ресурсами владеет функция, или разработать новый" +" способ наблюдения за поведением программы во время выполнения. Например, в " +"TH08 {ph0}разность коллизий привела к тому, как исходная программа " +"обрабатывала вычисления с плавающей запятой{ph1}. Прежде чем агент смог " +"протестировать полезную поправку, он должен был решить, что именно измерять." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Это предполагает еще одну роль модели с широкими возможностями: в первую " +"очередь помочь сделать проблему проверяемой. Как только эта проверка " +"появится, мы сможем выяснить, насколько далеко может зайти изученная " +"политика поиска." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Когда программа проверки ошибается" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Когда проверка используется для обучения, её охват становится частью среды " +"обучения. Я называю такой эталон или проверяющий инструмент оракулом. Даже " +"воспроизводимый ответ нужно понимать в пределах того, что он действительно " +"проверяет." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 показал, как много может скрываться за пределами этого покрытия. " +"Некоторые реконструированные функции прошли точное сравнение с неправильными" +" плавающими константами. Компаратор корректировал перемещенные адреса перед " +"проверкой инструкций, но проверял значения, стоящие за этими адресами, " +"только тогда, когда они были явно записаны для проверки. Другие буквальные " +"ссылки могут пройти без проверки их значений." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Чтобы устранить этот пробел, {ph0}более широкий аудит{ph1} обнаружил " +"неправильные константы в функциях, которые уже прошли проверку. В одном " +"расчете в реконструированный исходный код добавлен {ph2}, тогда как в " +"исходный добавлен {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Модель, получившая награду в результате старой проверки, могла " +"научиться производить неверную реконструкцию.{ph1} Мы не обучали модель RL с" +" помощью этой проверки. Сбой, который мы наблюдали, заключался в самой " +"проверке. Но если бы мы использовали это в качестве награды, то же самое " +"слепое пятно стало бы частью среды обучения." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Функциональный тест может иметь аналогичное «слепое пятно». " +"{ph0}Исследование с использованием дифференциального фаззинга в " +"декомпиляторах LLM{ph1} выявило различия в поведении за пределами " +"предоставленных тестов. Поэтому нам необходимо понимать прохождение теста с " +"точки зрения случаев, в которых он проводится. Точно так же совпадение " +"инструкций следует понимать с точки зрения байтов и данных, которые оно " +"проверяет." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Прежде чем использовать какой-либо вид проверки в качестве награды, я бы " +"протестировал ее с заведомо неверными результатами. Я также хотел бы хранить" +" окончательное принятие отдельно от исходного кода, который может " +"редактировать агент ИИ. Модель должна пройти проверку путем правильного " +"восстановления программы. В противном случае простое копирование массива " +"байтов из целевого объекта может обмануть наивную систему оценки без " +"восстановления полезного исходного кода." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Улучшение модели и улучшение её проверяющего инструмента — части одной " +"исследовательской задачи.{ph1} Чем лучше модель оптимизирует получаемую " +"обратную связь, тем важнее понимать саму эту связь." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Сравнение, которое стоит провести" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Имея эти проверки, я бы начал сравнение с фиксированного семейства задач " +"VC7.1. Во-первых, я бы установил базовые показатели для сильной модели ИИ " +"общего назначения и для более мелкой модели. Добавление знаний о репозитории" +" в меньшую модель покажет, какие изменения происходят в извлечении. Отсюда " +"контролируемая специализация и версия, обученная RL, позволят нам изучить, " +"что добавляет обучение." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Чтобы сделать эти сравнения информативными, каждая модель должна получить " +"одни и те же целевые доказательства и инструменты. Для сравнений по " +"конкретному обучению я бы также оставил фиксированной базовую модель и " +"доступные знания. Повторные испытания помогут отличить надежную стратегию " +"поиска от возможного решения, которое окажется успешным случайно." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Затем я бы разделил два начальных условия: восстановление функции из ее " +"инструкций и закрытие последних нескольких различий в поддерживаемом " +"исходном коде. Специализированная модель ИИ может превосходно справиться со " +"второй задачей, в то время как модель ИИ общего назначения выполняет большую" +" часть работы, необходимой для ее достижения. Измерение их по отдельности " +"выявило бы такое разделение работы." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Обе задачи требуют тестовых примеров, исключенных из обучения и поиска. " +"Связанные игры Touhou имеют общий код движка. Исключение одной игры из " +"обучения может привести к тому, что в обучающем наборе останутся почти " +"идентичные функции. Вместо этого я бы исключил целые группы связанного " +"исходного кода и исключил бы их проверенные ответы как из обучающих данных, " +"так и из библиотеки поиска." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"В этих примерах результатом будут полные, независимо проверенные совпадения." +" Равные бюджеты для предложений-кандидатов или попыток компиляции помогут " +"сравнить качество поиска. Измерение общего времени и затрат, включая " +"компиляцию, покажет, обеспечивает ли это качество эффективный рабочий " +"процесс. Затраты на обучение следует оценивать отдельно." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Оба измерения имеют значение. Дешевое предложение может привести к " +"дорогостоящему рабочему процессу, если оно приведет к увеличению количества " +"компиляций, не содержащих полезной информации. И наоборот, более медленная " +"модель может быть более экономичной, если она быстрее обнаружит полезный " +"эксперимент. Сравнение должно включать эти затраты." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Подсчет принятых результатов также позволяет учитывать промежуточный " +"прогресс. Один TH09 {ph0}кандидат на воспроизведение-сохранение{ph1} " +"выглядел многообещающе, поскольку скомпилированная функция имела ожидаемый " +"размер, но полное сравнение все же выявило существенные различия. Изменения " +"в том, как компилятор организует инструкции, также могут создать " +"впечатление, что кандидат ближе к цели, не решая при этом основную проблему." +" Такая диагностика может помочь в следующем эксперименте, но я бы сопоставил" +" любую награду за «приближение» с полной приемочной проверкой." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Меня бы заинтересовала закономерность этих результатов. Если " +"специализированная модель ИИ хорошо работает в знакомом семействе " +"компиляторов, сохранится ли это преимущество при изменении инструментальной " +"цепочки? И как только обе модели ИИ будут хорошо воспроизводиться, сколько " +"еще добавится обучение? Ответы помогут нам решить, где тот или иной тип " +"модели наиболее полезен." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "О каком ИИ-агенте идет речь?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Если модели окажутся полезными на разных этапах, полезным механизмом может " +"стать широкий агент с доступом к специализированной модели ИИ. Как только " +"задача становится привычным поиском компилятора, он может запросить " +"кандидатов у специализированной модели ИИ. Если результаты перестанут иметь " +"смысл, более широкий агент может вернуться к целевым данным или исследовать " +"само измерение." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"В таком случае специализация становится инструментом, который агент может " +"выбирать по мере развития расследования. Агент сохраняет свободу менять " +"направление, которое сделало возможными предыдущие прорывы." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Это естественным образом следует из промышленного сдвига, который я описал в" +" предыдущем эссе. Возможность проводить больше экспериментов меняет то, как " +"мы организуем работу. Это также дает нам повод задаться вопросом, какие " +"решения требуют широкого суждения, а какие улучшаются за счет повторного " +"опыта работы с конкретным ремеслом." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Пока самая сильная универсальная модель заслужила место в моём рабочем " +"процессе, решив проблемы, которые прежде оставались нерешёнными. Эти успехи " +"побуждают меня изучить процесс внимательнее: какая часть зависела от широты " +"её возможностей, а какую могла бы выполнить модель, обученная именно такой " +"реконструкции?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Репозитории дают нам возможность проверить вопрос.{ph1} Я хотел бы " +"использовать эту запись для сравнения и посмотреть, что мы узнаем." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Доказательства и атрибуция моделей" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"В примерах описаны исторические сравнения на уровне функций, записанные в " +"связанных коммитах. Проверки во время выполнения всей игры — это отдельные " +"этапы. Источник и соответствующие записи были проверены 13 октября 2026 " +"года." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"Метка TH09 {ph0} означает GPT-6-Astra. Модель, связанная с {ph1}, со " +"временем изменилась, поэтому сама по себе метка не может идентифицировать " +"модель, использованную в конкретном прогоне. Явные названия моделей в других" +" цитируемых коммитах обеспечивают записанную атрибуцию. Эти истории не " +"включают в себя последовательные измерения затрат или усилий для каждого " +"запуска." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 время жизни временных объектов:{ph1} {ph2}предыдущая проверка " +"контекста{ph3} и {ph4}полная реконструкция, подтвержденная чистой " +"перекомпиляцией из исходного кода{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"Обратный вызов {ph0}TH09 Front:{ph1} {ph2}диагностические области, которые " +"не соответствуют{ph3}, {ph4}Astra новому графу потока управления{ph5} и его " +"{ph6}принятой проверке перекомпиляции{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Знание компилятора:{ph1} {ph2}TH095 повторное использование поведения " +"сегмента идентификаторов{ph3}, {ph4}TH04 исходный код игрока и порядок " +"компоновщика{ph5} и полная реконструкция {ph6}Luna функции создания врагов " +"TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Проверки и диагностика:{ph1} {ph2}TH08 аудит констант с плавающей " +"запятой{ph3}, {ph4}TH08 численное исследование{ph5} и {ph6}TH09 " +"реконструкция с сохранением повторов{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Предлагаемые сравнения специализированных моделей и обучение RL — это " +"будущие эксперименты. Их мотивирует история проектов. Для этого эссе не " +"оценивалась обученная специализированная модель." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Нужна ли реверс-инжинирингу модель большего размера? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Чему реконструкция Touhou научила меня об общих моделях, специализированных " +"моделях и умении предлагать лучшие гипотезы на основе отзывов компилятора." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "На этой странице" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Эссе «Модели и реверс-инжиниринг»" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Избранные эксперименты по реконструкции" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Наверх" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}Подробные записи о доказательствах{ph1} содержат результаты сравнений и" +" контекст экспериментов." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Автор: N0zoM1z0 · 13 октября 2026 г. · Черновик для обсуждения" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Руководство по установке" diff --git a/website/locales/th/messages.po b/website/locales/th/messages.po index 29d211973..45c67209b 100644 --- a/website/locales/th/messages.po +++ b/website/locales/th/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}บ้าน{ph1} /บล็อก" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "บล็อก" -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "ความคิดเกี่ยวกับวิศวกรรมย้อนกลับ" #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "ฟื้นฟูเกม{ph0}เรียงความ" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "การปฏิวัติอุตสาหกรรมในวิศวกรรมย้อนกลับ" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "สิ่งที่คู่มือใหม่และ " "reconstructingTH08,TH095และTH04สอนฉันเกี่ยวกับเจ้าหน้าที่ปลายทางและความรู้นั่นรประกอบที่อีกฝั่งยิ่งสนง.โครงการ." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "อ่านบทความ" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "โดย N0zoM1z0 ·10 ตุลาคม 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "และเจ้าหน้าที่ปัญญาประดิษฐ์" #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -134,112 +137,117 @@ msgid "" msgstr "" "REA-หาวิธีการทำงานของซอฟต์แวร์ วิศวกรรมย้อนกลับกับตัวแทนการเขียนโค้ดของคุณ" -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "หน้าแรก REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "เมนูหลัก" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA บน GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "เข้าร่วม REA บน Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "ติดตาม REA บน X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -248,35 +256,35 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}บ้าน{ph1} / {ph2}บล็อก{ph3} /ฟื้นฟู" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "เรียงความ" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "การปฏิวัติอุตสาหกรรมในวิศวกรรมย้อนกลับ" -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "โดย N0zoM1z0 ·10 ตุลาคม 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "ประเด็นสำคัญ" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -288,7 +296,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -301,7 +309,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -314,7 +322,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -326,7 +334,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -336,65 +344,65 @@ msgstr "" "{ph0}เราอยู่ในยุคแรกของการปฏิวัติอุตสาหกรรมของรี{ph1} " "วิธีการยังคงเป็นรูปเป็นร่าง มีเหลืออีกมากมายให้สำรวจ" -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "วิธีสารประกอบประสบการณ์" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}ทิศทางของมนุษย์{ph1} *เป้าหมายและเกณฑ์การยอมรับ" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "อิสระในการทำงาน" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "ผู้ช่วย AI" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "เลือกการทดสอบ{ph0}เสนอสมมติฐาน" -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "การตรวจสอบ" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "เกณฑ์อ้างอิงสำหรับตรวจสอบ" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "ทดสอบกับ{ph0}การอ้างอิงคอนกรีต" -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "คลังโค้ด" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "หน่วยความจำของงาน" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -403,7 +411,7 @@ msgstr "รหัส,หลักฐาน,{ph0}ตรวจสอบและ #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -412,26 +420,26 @@ msgstr "ไม่ตรงกัน{ph0}{ph1}แก้ไขสมมติฐ #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "ดีกว่า{ph0}{ph1}จุดเริ่มต้น{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "นำกลับมาใช้" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}ผ่าน{ph1} *เก็บผลและหลักฐาน" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -440,14 +448,14 @@ msgstr "" "แต่ละโครงการออกต่อไปด้วยจุดเริ่มต้นที่ดีขึ้น " "ซึ่งรวมถึงการแก้ไขเช็คเมื่อเราค้นพบช่องว่าง" -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "ในบทความนี้" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -455,7 +463,7 @@ msgstr "{ph0}สิงหาคม 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -463,7 +471,7 @@ msgstr "{ph0}TH08:ความต่อเนื่อง{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -471,7 +479,7 @@ msgstr "{ph0}สองวิธี{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -479,7 +487,7 @@ msgstr "{ph0}TH095:การทบต้น{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -487,7 +495,7 @@ msgstr "{ph0}TH04:สถาปัตยกรรม{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -495,7 +503,7 @@ msgstr "{ph0}จากที่แน่นอนที่จะอ่านไ #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -503,18 +511,18 @@ msgstr "{ph0}การเปลี่ยนแปลงอุตสาหกร #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}สิ่งที่เป็นไปได้{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "สิ่งที่เปลี่ยนแปลงในเดือนสิงหาคม 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -528,7 +536,7 @@ msgstr "" "การต่อไปหมายถึงการใช้จ่ายมากขึ้นของเวลาของตัวเองในการทำงานต่อไป " "มันยังหมายถึงการเก็บภาพขนาดใหญ่มากขึ้นในหัวของฉัน." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -541,7 +549,7 @@ msgstr "" "นั่นคือประสบการณ์ที่อยู่เบื้องหลังบทความนี้. " "วิธีการที่จะมีประโยชน์อื่นๆแต่แต่ละเขตข้อมูลความต้องการที่จะสร้างสิ่งที่มันสามารถตรวจ" -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -553,7 +561,7 @@ msgstr "" "ผมอยากเห็นว่าตัวแทนจะสามารถเข้าถึงโปรแกรมและเครื่องมือพัฒนาสามัญได้ไกลแค่ไหน" " การฟื้นฟูทูโฮทำให้ผมมีโครงการมากมายที่จะหาคำตอบได้" -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -569,7 +577,7 @@ msgstr "" "มันอาจจะเขียนการวินิจฉัยขนาดเล็กและใช้ผลในการตัดสินใจว่าจะลองต่อไป " "ให้มันว่าเสรีภาพสร้างความแตกต่าง:ฉันสามารถใช้ความสนใจมากขึ้นในทิศทางของโครง" -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -580,7 +588,7 @@ msgstr "" "แล้วผมก็เริ่มสงสัยว่าอะไรจะรอดพ้นจากโครงการปัจจุบัน " "เกมต่อไปจะได้รับประโยชน์จากทุกอย่างที่เราเพิ่งได้เรียนรู้?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08:อาคารในการทำงานของมนุษย์" @@ -589,7 +597,7 @@ msgstr "TH08:อาคารในการทำงานของมนุษ #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -603,7 +611,7 @@ msgstr "" "แหล่งข่าวสาธารณะของพวกเขาทำให้ฉันมีรากฐานที่สำคัญ " "มันมาพร้อมกับความรู้เกี่ยวกับการสร้างและประวัติของการมีส่วนร่วมที่ผมเก็บรักษาไว้ใน" -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -614,7 +622,7 @@ msgstr "" "ความต่อเนื่องของฉันเริ่มต้นในวันที่ 13 สิงหาคม โดย 19 " "สิงหาคมบัญชีแยกประเภทที่บันทึกไว้สำหรับทุก 1,107 ระบุฟังก์ชั่นเกม" -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -625,7 +633,7 @@ msgstr "" "สิงหาคมประมาณสิบเอ็ดวันหลังจากที่ต่อเนื่องเริ่ม ฉบับเว็บตาม เดอะพื้นเมือง " "Linux ปล่อย 64 บิตมาถึงเมื่อวันที่ 30 สิงหาคม" -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -639,7 +647,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -656,12 +664,12 @@ msgstr "" "ตรวจสอบรันไทม์สามารถบอกเราว่าเส้นทางที่ใช้สิทธิถึงสถานะที่คาดไว้ " "ตัวแทนเสนอคำอธิบายและทดสอบมัน;ไม่ตรงกันให้มันบางสิ่งบางอย่างที่เฉพาะเจาะจงใน" -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "ตรงกับค่าคงที่ผิดพอดี" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -672,7 +680,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -684,7 +692,7 @@ msgstr "" " แหล่งที่มาที่สร้างขึ้นใหม่ตรวจสอบอำนาจของผู้เล่นกับ {ph0}. ต้นฉบับที่ใช้ " "{ph1} เกณฑ์สูงสุด-อำนาจ" -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -698,13 +706,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}แต่ฟังก์ชั่นที่มีอยู่แล้วผ่านการเปรียบเทียบที่แน่นอน{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -718,7 +726,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -735,7 +743,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -750,7 +758,7 @@ msgstr "" "จุดลอยตัวอ้างอิงอย่างต่อเนื่อง " "มันพบอีกสิบสองอ้างอิงที่ไม่ถูกต้องในห้าฟังก์ชั่นที่ยอมรับ" -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -763,7 +771,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -773,7 +781,7 @@ msgstr "" "{ph0}การเขียนข้อความโฆษณา,การเขียนในนามคนอื่น,บทความ{ph1} " "ซ่อมมันเป็นส่วนหนึ่งของการซ่อมเกม" -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -790,7 +798,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -805,7 +813,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -814,7 +822,7 @@ msgid "" msgstr "" "{ph0}ชุดที่ประสบความสำเร็จให้เราทั้งการกู้คืนรหัสและสภาพแวดล้อมที่ดีกว่าสำหรับชุดต่อไป.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "สองความคิดที่แตกต่างกันของการฟื้นฟู" @@ -823,7 +831,7 @@ msgstr "สองความคิดที่แตกต่างกันข #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -835,7 +843,7 @@ msgstr "" "ทำให้ความขัดแย้งกับชนิดของงานนี้อย่างชัดเจน " "ประกาศประกาศว่าการพัฒนาต่อไปจะเกิดขึ้นเอกชนจนกว่าจะเสร็จสิ้น หนึ่งทางอ่าน:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -843,7 +851,7 @@ msgid "" msgstr "" "การเพิ่มขึ้นของกริฟเตอร์(ไอรวบรวมและพอร์ต)ในพื้นที่นี้การจากการทำงานของเราสีภาพที่ไ…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -859,7 +867,7 @@ msgstr "" "ผมเคารพความพยายามที่อยู่เบื้องหลังมัน " "ความขัดแย้งที่ฉันต้องการจะหารือเกี่ยวกับวิธีการฟื้นฟูควรดำเนินการและวิธีการมีส่วนร่วม" -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -871,7 +879,7 @@ msgstr "" " โครงการหนึ่งต้องอาศัยความเชี่ยวชาญของบุคคลนั้นอย่างมาก " "ความไว้วางใจในผู้สนับสนุนที่สำคัญเพราะมากของเหตุผลที่เกิดขึ้นในขณะที่พวกเขาทำงา" -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -881,7 +889,7 @@ msgstr "" "โครงการที่มีอยู่แล้วรักษาความรู้ในแหล่งที่มาของพวกเขาและสร้างเครื่องมือ " "สิ่งที่เปลี่ยนแปลงสำหรับผมก็คือเจ้าหน้าที่สามารถใช้ความรู้นั้นเพื่อติดตามการสืบสวนต่อไปได้ด้วยตัวเอง" -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -895,7 +903,7 @@ msgstr "" "การฟื้นฟูที่นำเสนอแล้วมีเพื่อความอยู่รอดการตรวจสอบที่เกี่ยวข้อง " "ฉันต้องการให้บุคคลอื่นสามารถที่จะตรวจสอบว่าทำไมเราเลือกการดำเนินงาน,แม้ว่าตัวแ" -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -908,7 +916,7 @@ msgstr "" "ที่ทำให้เกิดคำถามจริงเกี่ยวกับเครดิต " "การเปลี่ยนแปลงสิ่งที่ผู้ดูแลจำเป็นต้องรู้ก่อนที่จะยอมรับการมีส่วนร่วม" -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -923,7 +931,7 @@ msgstr "" "คนยังคงมีการออกแบบกระบวนการและรับรู้เมื่อผลผลิตที่ไม่ถูกต้อง " "ชุมชนต่างๆสามารถเลือกได้ว่าพวกเขาต้องการเปลี่ยนแปลงมากแค่ไหน" -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -947,7 +955,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -960,14 +968,14 @@ msgstr "" "ใบเสนอราคาเป็นข้อความที่ตัดตอนมาที่สั้นลง TH08ของ " "{ph4}เครดิตและแหล่งที่มา{ph5} บันทึกขอบเขตความต่อเนื่อง" -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095:ประสบการณ์เริ่มต้นการทบต้น" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -981,7 +989,7 @@ msgstr "" "สิงหาคมกับศูนย์ยืนยันฟังก์ชั่นเกมในบัญชีแยกประเภท เรายังคงต้องเรียนรู้เกม " "แต่เรารู้อยู่แล้วมากขึ้นเกี่ยวกับวิธีการเริ่มต้นการฟื้นฟูและวิธีการที่จะให้มันย้าย" -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -995,7 +1003,7 @@ msgstr "" "ฟื้นฟูถูกทำเครื่องหมายเล่นได้เมื่อวันที่ 10 " "กันยายนประมาณสิบสองวันหลังจากการเริ่มต้น" -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1006,7 +1014,7 @@ msgstr "" "เป้าหมายใหม่จะได้รับประโยชน์จากการทำงานที่ทำในเกมอื่น. " "ประสบการณ์ที่มีอยู่แล้วในเครื่องมือและในวิธีการที่โครงการได้รับการจัด" -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1020,7 +1028,7 @@ msgstr "" " เราต้องเห็นพวกเขาทำงานด้วยกัน บทเรียนนั้นช่วยสร้างวิธีการที่เราเข้าหา " "TH095ทั้งโปรแกรมสร้าง" -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1032,7 +1040,7 @@ msgstr "" "เมื่อมันกลายเป็นตรวจสอบว่าเซสชั่นอื่นสามารถทำงานก็สามารถให้ความช่วยเหลือหลังจ" " ตัวแทนต่อไปสามารถใช้ผลลัพธ์โดยไม่ต้องทำซ้ำการสืบสวนที่นำไปสู่มัน" -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1046,7 +1054,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1057,7 +1065,7 @@ msgstr "" "{ph0}วิธีการที่จะกลายเป็นส่วนหนึ่งของวัสดุเริ่มต้นสำหรับเกมถัดไป{ph1} " "เราสามารถใช้ความพยายามของโครงการต่อไปมากขึ้นกับสิ่งที่เป็นจริงใหม่เกี่ยวกับเป้าหมาย" -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1069,7 +1077,7 @@ msgstr "" "Theyตรวจสอบการตัดสินใจและเรียกใช้การตรวจสอบก่อนที่จะดำเนินการต่อการทำงา " "พวกเขาไม่ได้มีการสร้างประวัติของโครงการทั้งหมดเพื่อหาเหตุผลที่แหล่งที่มาที่มีลักษณะ" -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04:เวิร์กโฟลว์มีชีวิตอยู่สถาปัตยกรรมที่แตกต่างกัน" @@ -1078,7 +1086,7 @@ msgstr "TH04:เวิร์กโฟลว์มีชีวิตอยู่ #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1094,7 +1102,7 @@ msgstr "" "กเขา ที่อยู่ {ph2}เรค 98{ph3} " "ให้ความรู้ที่มีคุณค่าและวัสดุแหล่งที่มาที่นี่ด้วย" -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1107,7 +1115,7 @@ msgstr "" "งานปัจจุบันเป็นพอร์ตพื้นเมือง 64 บิต " "การสร้างเวอร์ชันดอสทำงานก่อนทำให้พอร์ตการสื่อสารนั้นมีการอ้างอิง" -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1119,7 +1127,7 @@ msgstr "" "นอกจากนี้ยังมีการเปลี่ยนแปลงคอมไพเลอร์และรันไทม์กับที่เราตรวจสอบการทำงานของ " "แต่ตัวแทนยังคงสามารถทำตามคำถามผ่านไปยังผลลัพธ์และให้ผลลัพธ์ที่เป็นแนวทางในการทดลองต่อไป" -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1134,7 +1142,7 @@ msgstr "" "เมื่อหลักฐานและการตรวจสอบที่มีอยู่ตัวแทนสามารถทำงานผ่านคำถามมากที่สุดเท่าที่มันไ" " Windows ชื่อเรื่อง" -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1145,7 +1153,7 @@ msgstr "" "การเปลี่ยนแปลงแพลตฟอร์มอย่างมีนัยสำคัญไม่ได้บังคับให้เราเริ่มต้นใหม่ด้วยวิธีการใหม่ในการทำงาน" " สถาปัตยกรรมกำหนดปัญหาเวิร์กโฟลว์ยังคงให้เราวิธีแก้ปัญหา" -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1162,7 +1170,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1172,19 +1180,19 @@ msgstr "" "รัฐโครงการณวันที่ 10 ตุลาคม 2026: {ph0}การฟื้นฟูและทดสอบด้วยตนเอง{ph1} · " "{ph2}พอร์ต 64 บิต{ph3}. ท่าเรือยังคงอยู่ในการพัฒนา" -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "จากโค้ดที่แน่นอนไปยังโค้ดที่อ่านได้" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "เมื่อการฟื้นฟูการทำงานผมต้องการให้คนอื่นที่จะสามารถที่จะเข้าใจมัน" -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1197,7 +1205,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1213,7 +1221,7 @@ msgstr "" "จากนั้นเราสามารถให้ชื่อที่มีความหมายและประเภทที่เหมาะกับหลักฐาน " "เราให้เหตุผลกับแหล่งที่มาเพื่อให้คนต่อไปสามารถดูว่าการตีความที่มาจากไหน" -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1228,14 +1236,14 @@ msgstr "" "บิตในการตัดสินใจว่าวัตถุที่ควรจะเป็นเจ้าข " "ที่จะย้ายพฤติกรรมได้อย่างปลอดภัยเราจำเป็นต้องกู้คืนความสัมพันธ์ที่อยู่เบื้องหลังการเข้" -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "คำสั่งที่ผมใช้ตอนนี้คือ:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1251,7 +1259,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1267,7 +1275,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1283,7 +1291,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1297,7 +1305,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1313,7 +1321,7 @@ msgstr "" " " "การตรวจสอบที่สองว่าโปรแกรมที่สร้างขึ้นใหม่ยังคงสร้างและทำงานอย่างถูกต้องตามเส้นทางที่เราออกกำลังกาย" -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1326,7 +1334,7 @@ msgstr "" "การเปลี่ยนแปลงความเป็นเจ้าของสามารถออกจากสองส่วนของเกมโดยใช้สำเนาที่แตกต่ " "การเก็บรักษาทั้งสองตรวจสอบให้ตัวแทนคอนกรีตล้มเหลวในการตรวจสอบก่อนที่จะดำเนิ" -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1343,7 +1351,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1361,7 +1369,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1372,12 +1380,12 @@ msgstr "" "การฟื้นฟูความหมายทำให้ความรู้ที่กู้คืนใช้งานได้{ph1} " "พอร์ตแล้วสามารถสร้างทั้งสอง" -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "อะไรทำให้เกิดการเปลี่ยนแปลงทางอุตสาหกรรม" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1389,7 +1397,7 @@ msgstr "" "เมื่อตัวแทนสามารถดำเนินการมากของการสอบสวนไปข้างหน้า,การปรับปรุงสภาพแวดล้ " "เครื่องมือที่ดีกว่าจะช่วยให้มีทุกฟังก์ชันในภายหลังที่จำเป็น." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1402,7 +1410,7 @@ msgstr "" " ตัวแทนต้องการอิสรภาพมากพอที่จะทำตามผลลัพธ์ที่ไม่คาดคิด " "ถ้าต้องรอให้ดิฉันกำหนดแต่ละขั้นงานส่วนใหญ่ยังคงเกี่ยวข้องกับความสนใจของดิฉัน." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1415,7 +1423,7 @@ msgstr "" "ตรวจสอบล้มเหลวจะช่วยให้มันเข้าใจความผิดพลาดดีพอที่จะลองอีกครั้ง. " "ฉันยังต้องตัดสินใจว่าหลักฐานที่สะสมจะสนับสนุนโครงการนี้หรือไม่" -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1429,7 +1437,7 @@ msgstr "" "โครงการฟื้นฟูวัสดุคอมไพเลอร์และการตรวจสอบการอ้างอิงของตัวเอง " "ตัวแทนสามารถใช้ผู้ที่จะทดสอบแหล่งที่มาที่นำเสนอและดูว่าคำอธิบายของมันถือขึ้น" -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1447,7 +1455,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1466,7 +1474,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1482,7 +1490,7 @@ msgstr "" "เมื่อเราพบข้อบกพร่องในเครื่องมือที่ใช้ร่วมกัน,เราต้องซ่อมแซมและทบทวนผลที่ได้รับผลก" " โครงการถัดไปแล้วสามารถสืบทอดเครื่องมือที่แข็งแกร่ง" -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1497,7 +1505,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1509,7 +1517,7 @@ msgstr "" "รงการที่ใช้ร่วมกันเพื่อดำเนินการตรวจสอบและบทเรียนของพวกเขาไปข้างหน้า. " "ทำงานในหนึ่งเกมสามารถปรับปรุงเงื่อนไขเริ่มต้นอีก" -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1521,12 +1529,12 @@ msgstr "" "ปรับปรุงเครื่องมือเหล่านั้นจะเปลี่ยนแปลงจำนวนคนถัดไป-หรือตัวแทนถัดไป-" "สามารถทำได้." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "โครงการที่เราสามารถพิจารณาได้ในขณะนี้" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1537,7 +1545,7 @@ msgstr "" "เกมอาจจะน่าสนใจที่จะย้อนกลับวิศวกรและยังคงต้องการมากขึ้นของความสนใจของตัวเอ " "หลายโครงการจะอยู่ความคิด" -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1553,7 +1561,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1563,7 +1571,7 @@ msgstr "" "ตอนนี้ผมมองไปที่โปรแกรมที่ไม่คุ้นเคยและขอให้: " "{ph0}อะไรการเข้าถึงข้อเสนอแนะและความรู้ที่สะสมจะช่วยให้ตัวแทนทำงานเกี่ยวกับเรื่องนี้{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1574,12 +1582,12 @@ msgstr "" "แต่ละคนสามารถปรับปรุงวิธีการที่เราเข้าใกล้ต่อไป " "ผมอยากสืบต่อไปว่ามันพาเราไปได้ไกลแค่ไหน" -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "ความคืบหน้าโครงการและแหล่งที่มา" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1612,7 +1620,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1646,7 +1654,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1664,7 +1672,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1688,7 +1696,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1711,7 +1719,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1727,7 +1735,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1749,7 +1757,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1763,7 +1771,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1783,27 +1791,27 @@ msgstr "" "N0zoM1z0สะท้อนถึงป้อนเองย้อนกลับวิศวกรรม,Touhou ชิ้นกับ AI " "เจ้าหน้าที่และความรู้รประกอบที่ข้ามTH08,TH095และPC-98TH04." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "ประสบการณ์การทำงานระหว่างโครงการ" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "เรียงความการฟื้นฟู" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -1812,18 +1820,18 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}บ้าน{ph1}{ph2}/{ph3}ห้องปฏิบัติการความเร็วไดโนเสาร์" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "ตรวจสอบ→สร้าง→เปลี่ยน" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "สร้างกฎความเร็วของไดโนเสาร์" @@ -1832,7 +1840,7 @@ msgstr "สร้างกฎความเร็วของไดโนเส #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1844,15 +1852,15 @@ msgstr "" "ส่งคืนสคริปต์ที่กำลังทำงานอยู่;{ph1} เราใช้กฎในการสร้างมินิเกมนี้ด้วย " "{ph2}ปรับความเร็ว{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "ในหน้านี้" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1860,7 +1868,7 @@ msgstr "{ph0}เล่นและเปลี่ยนความเร็ว{ #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1868,7 +1876,7 @@ msgstr "{ph0}อ่านกฎการกู้คืน{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1876,18 +1884,18 @@ msgstr "{ph0}ตรวจสอบการฟื้นฟู{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}ลองวิเคราะห์{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "เล่นและเปลี่ยนความเร็ว" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1898,48 +1906,48 @@ msgstr "" "ย้ายแถบเลื่อนความเร็วที่จะลองเกมที่ช้าลงหรือเร็วขึ้น;มันสลับไปยังความเร็วคงที่" " เลือกกฎการกู้คืนที่จะเริ่มต้นที่ 6 และค่อยๆเร่งอีกครั้ง" -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "เล่นเกมที่สร้างขึ้นใหม่" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "เล่น" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "กระโดด ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "เริ่มใหม่" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "ความเร็ว" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "ใช้กฎการเร่งการกู้คืน" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "กฎเดิม:เริ่มต้นที่ 6 จากนั้นเพิ่มขึ้นถึง 13" -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "เลื่อนแถบเลื่อนเพื่อตั้งค่าความเร็วของคุณเอง พื้นที่หรือกระโดดล้างแคคตัส" -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -1947,7 +1955,7 @@ msgid "" msgstr "" "เปิดใช้งาน JavaScript เพื่อเล่นการฟื้นฟู รหัสและคำอธิบายข้างต้นยังคงอ่านได้" -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "อ่านสคริปต์ REA กลับมา" @@ -1955,7 +1963,7 @@ msgstr "อ่านสคริปต์ REA กลับมา" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1969,7 +1977,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1979,18 +1987,18 @@ msgstr "" "การตั้งค่าคือ {ph0}, {ph1} และ {ph2}. " "เกมวิ่งสาขานี้ในการปรับปรุงโดยไม่มีการปะทะกัน" -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "ใช้กฎเดียวกันในเกมใหม่" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "คัดลอก" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2006,18 +2014,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}ดาวน์โหลดกฎความเร็ว{ph1} · {ph2}อ่านรหัสเกม{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "ตรวจสอบการฟื้นฟู" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2027,27 +2035,27 @@ msgstr "" "เราเรียกว่าฟังก์ชั่นการปรับปรุงเกมเดิมที่มีอุปสรรคและการตั้งเวลาอัตโนมัติปิดการใช้งาน" " เปรียบเทียบความเร็วที่บันทึกไว้กับรีเพลย์ของกฎการกู้คืน" -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "อัพเดท" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "เกมเดิม" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "กฎที่สร้างขึ้นใหม่" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "เรียกใช้การตรวจสอบความเร็ว" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2056,14 +2064,14 @@ msgstr "" "ค่าปัดเศษเป็นสามทศนิยม " "สาขาตรวจสอบก่อนที่จะเพิ่มเพื่อให้เพิ่มขึ้นสุดท้ายสามารถใช้ความเร็วสูงกว่า 13" -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "ลองวิเคราะห์ด้วยตัวคุณเอง" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2072,14 +2080,14 @@ msgstr "{ph0}ตั้งค่า REA{ph1} กับตัวแทนการ #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "ตาม {ph0}ขั้นตอนการเชื่อมต่อเบราว์เซอร์{ph1} ใช้ {ph2} น้าเว็บ" -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2095,7 +2103,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2107,7 +2115,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเ #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2120,7 +2128,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2135,7 +2143,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2160,64 +2168,64 @@ msgid "" msgstr "" "อ่านกฎความเร็วของเกมไดโนเสาร์ด้วย REA สร้างมันแล้วเปลี่ยนความเร็วและเล่น" -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "ฟื้นฟูความเร็วไดโนเสาร์" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "ไดโนเสาร์มินิเกม ใช้ปุ่มกระโดดหรือกดพื้นที่ในขณะที่เกมจะมุ่งเน้น" -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "คัดลอกกฎความเร็วที่สร้างขึ้นใหม่" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "คัดลอกไดโนเสาร์พร้อมท์วิเคราะห์" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}บ้าน{ph1} /คำถามที่พบบ่อย" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REAคำถามที่พบบ่อย" -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "การตั้งค่าการอัปเดตการวิเคราะห์และการแก้ไขปัญหา" -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "หัวข้อ" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2225,7 +2233,7 @@ msgstr "{ph0}การตั้งค่าและการปรับปร #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2233,7 +2241,7 @@ msgstr "{ph0}การวิเคราะห์{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2241,31 +2249,31 @@ msgstr "{ph0}การแก้ไขปัญหา{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}ข้อมูลและการแบ่งปัน{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "การตั้งค่าและการปรับปรุง" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "ติดตั้ง REA อย่างไร?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "เทอร์มินัล*การตั้งค่าตัวแทน" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "คัดลอก" @@ -2273,7 +2281,7 @@ msgstr "คัดลอก" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2287,13 +2295,13 @@ msgstr "" "จากนั้นระบุพาธไฟล์และคำถาม " "ดูข้อกำหนดและขั้นตอนวิเคราะห์ครั้งแรกได้ใน{ph0}คู่มือการตั้งค่า{ph1}" -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "ซึ่งตัวแทนการเขียนโค้ดสามารถใช้ REA?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2308,32 +2316,32 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}เชื่อมต่อตัวแทนการเข้ารหัสของคุณ{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "อัปเดต REA อย่างไร?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " "npm:" msgstr "REA การแก้ไขข้อผิดพลาด รือไม่ CLI ด้วย npm:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "เทอร์มินัล*ติดตั้งแล้ว CLI" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2343,14 +2351,14 @@ msgstr "" "เรียกคำสั่งปรับปรุงการตั้งค่าที่แสดงหลังอัปเดต หากตั้งค่าผู้ช่วยด้วย {ph0} " "ให้เรียก:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "เทอร์มินัล*รีเฟรชการตั้งค่าตัวแทน" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2363,7 +2371,7 @@ msgstr "" "จึงต้องเรียกคำสั่งตั้งค่าอีกครั้งเพื่อใช้เวอร์ชันใหม่ หากต้องการใช้ CLI " "ครั้งเดียว ให้ต่อคำสั่งที่ต้องการหลัง {ph0}" -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "คือการติดตั้งทักษะจาก skills.sh พอแล้ว?" @@ -2371,7 +2379,7 @@ msgstr "คือการติดตั้งทักษะจาก skills.s # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2383,17 +2391,17 @@ msgstr "" "REA{ph1}เพื่อเชื่อมต่อเซิร์ฟเวอร์ MCP และติดตั้ง skill ที่ตรงกัน " "จากนั้นเริ่มผู้ช่วยใหม่เพื่อใช้งานเครื่องมือ" -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "การวิเคราะห์" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "สิ่งที่ฉันสามารถวิเคราะห์ด้วย REA?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "เริ่มต้นด้วยชนิดของซอฟต์แวร์ที่คุณมี:" @@ -2401,7 +2409,7 @@ msgstr "เริ่มต้นด้วยชนิดของซอฟต์ # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2413,7 +2421,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2424,7 +2432,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2433,7 +2441,7 @@ msgstr "{ph0}หน้าเว็บเบราว์เซอร์{ph1}:ส # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2444,13 +2452,13 @@ msgstr "" "REA ยังวิเคราะห์ managed assembly เช่น .NET, Android APK, เฟิร์มแวร์ " "และทรัพยากรในแพ็กเกจได้ ดูขั้นตอนจริงได้ใน{ph0}กรณีศึกษา{ph1}" -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "ฉันต้อง Hopper, Ghidra หรือ IDA?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2463,7 +2471,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2476,13 +2484,13 @@ msgstr "" "เครื่องมือที่ใช้ได้ขึ้นอยู่กับระบบปฏิบัติการและเป้าหมาย " "{ph0}ตั้งค่าการวิเคราะห์เนทีฟ{ph1}" -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "ฉันสามารถใช้ REA โดยไม่มีตัวแทนการเขียนโค้ด?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2491,7 +2499,7 @@ msgstr "" "ได้ CLI ใช้ขั้นตอนวิเคราะห์เดียวกัน สำหรับแอป JavaScript หรือ Electron " "ในเครื่อง:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "เทอร์มินัล*การวิเคราะห์การใช้งานแบบคงที่" @@ -2499,7 +2507,7 @@ msgstr "เทอร์มินัล*การวิเคราะห์ก # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2510,13 +2518,13 @@ msgstr "" "ดูตัวเลือกติดตั้งใน{ph0}คู่มือ CLI{ph1}" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA ส่งคืนโค้ดอะไรบ้าง?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2532,7 +2540,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2544,13 +2552,13 @@ msgstr "" "ดูกระบวนการได้จาก{ph0}การคำนวณของ DX-Ball{ph1}และ{ph2}ตัวตรวจ flag ของ " "CTF{ph3}" -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "ควรถามอะไรกับผู้ช่วย?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2567,7 +2575,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2576,7 +2584,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเ # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2586,19 +2594,19 @@ msgstr "" "เปลี่ยนพาธเป็นเป้าหมายของคุณ " "{ph0}คู่มือ{ph1}มีพรอมป์ต์ตัวอย่างสำหรับโปรแกรมเนทีฟ Electron และเบราว์เซอร์" -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "การแก้ไขปัญหา" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "ทำไมตัวแทนของฉันไม่สามารถเห็น REA เครื่องมือ?" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2608,7 +2616,7 @@ msgstr "" "หลังตั้งค่า ให้เริ่มผู้ช่วยใหม่หรือเชื่อมต่ออีกครั้ง ตรวจสอบการลงทะเบียน REA" " ด้วย {ph0} ตัวอย่างสำหรับ Codex:" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "เทอร์มินัล*ตรวจสอบลูกค้าหนึ่ง" @@ -2617,7 +2625,7 @@ msgstr "เทอร์มินัล*ตรวจสอบลูกค้า #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2627,7 +2635,7 @@ msgstr "" "เปลี่ยน {ph0} เป็น ID ของไคลเอนต์ เช่น {ph1} หรือ {ph2} " "หากรายงานว่าการลงทะเบียนหายไปหรือเก่า ให้ตั้งค่าไคลเอนต์นั้นอีกครั้ง:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "เทอร์มินัล*ซ่อมแซมการตั้งค่าของไคลเอนต์หนึ่ง" @@ -2635,7 +2643,7 @@ msgstr "เทอร์มินัล*ซ่อมแซมการตั้ # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2647,7 +2655,7 @@ msgstr "" "ให้ดูข้อผิดพลาดการเชื่อมต่อ MCP ของไคลเอนต์ " "{ph0}ดูวิธีวินิจฉัยเพิ่มเติม{ph1}" -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "ฉันจำเป็นต้องเริ่มต้น Hopper ก่อน?" @@ -2655,7 +2663,7 @@ msgstr "ฉันจำเป็นต้องเริ่มต้น Hopper # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2667,7 +2675,7 @@ msgstr "" "ให้เลือกโหมดทดลองหรือเปิดใช้งานใบอนุญาตในหน้าจอเปิดครั้งแรก " "ก่อนเริ่มการวิเคราะห์อัตโนมัติ {ph0}ดูการตั้งค่าเครื่องมือเนทีฟ{ph1}" -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "ควรทำอย่างไรเมื่อพบข้อผิดพลาด?" @@ -2675,7 +2683,7 @@ msgstr "ควรทำอย่างไรเมื่อพบข้อผิ # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2688,7 +2696,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2700,18 +2708,18 @@ msgstr "" "ชนิดเป้าหมาย ขั้นตอนทำซ้ำ และข้อความผิดพลาด " "หากเป็นการวิเคราะห์เนทีฟให้ระบุชื่อเครื่องมือด้วย" -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "ข้อมูลและการแบ่งปัน" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "ไม่ REA อัปโหลดแอปของฉัน?" # Reviewed for readable instructions and accurate software terminology. -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2720,7 +2728,7 @@ msgstr "" "REA วิเคราะห์เป้าหมายบนเครื่องของคุณ ผู้ช่วยจะได้รับผลลัพธ์ " "และผลลัพธ์นั้นอยู่ภายใต้นโยบายข้อมูลของผู้ให้บริการโมเดลที่ผู้ช่วยใช้" -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "ฉันจะแบ่งปันตัวอย่างหรือมีส่วนร่วมได้อย่างไร" @@ -2730,7 +2738,7 @@ msgstr "ฉันจะแบ่งปันตัวอย่างหรือ #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2746,7 +2754,7 @@ msgstr "" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2771,77 +2779,77 @@ msgstr "" "คำตอบสำหรับคำถาม REA ที่พบบ่อย: การติดตั้ง อัปเดต เครื่องมือวิเคราะห์ " "ผู้ช่วยเขียนโค้ด การแก้ปัญหา และการแชร์ตัวอย่าง" -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "คำถามที่พบบ่อยเกี่ยวกับ REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "คัดลอกREAคำสั่งการตั้งค่า" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "คัดลอก REA อัพเดตคำสั่ง" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "คัดลอกคำสั่งรีเฟรชการตั้งค่าตัวแทน" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "คัดลอก REA CLI คำสั่งการวิเคราะห์" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "คัดลอกตัวอย่างพร้อมท์การวิเคราะห์" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "คัดลอกคำสั่งการวินิจฉัยไคลเอ็นต์" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "สำเนาคำสั่งการตั้งค่าขอบเขต" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}บ้าน{ph1} /การสืบสวนครั้งแรกของคุณ" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "หาที่{ph0}บันทึกการส่งออกไป" -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2850,14 +2858,14 @@ msgstr "" "ใช้ REA " "นาดเล็กทำตามปุ่มบันทึกการส่งออกและตรวจสอบรายละเอียดหนึ่งด้วยตัวคุณเอง" -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "ในการออกกำลังกายนี้" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2865,7 +2873,7 @@ msgstr "{ph0}1. ตั้งค่า{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2873,7 +2881,7 @@ msgstr "{ph0}2. สอบถามเกี่ยวกับการส่ง #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2881,7 +2889,7 @@ msgstr "{ph0}3. ทำตามคำตอบ{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2889,13 +2897,13 @@ msgstr "{ph0}4. พรีเมียร์ลีก{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. ถามคำถามอื่น{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. เชื่อมต่อตัวแทนของคุณกับ REA" @@ -2908,29 +2916,29 @@ msgstr "1. เชื่อมต่อตัวแทนของคุณกั #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "คัดลอก" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "หรือเรียกใช้คำสั่งนี้ในเทอร์มินัลของคุณ:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2939,14 +2947,14 @@ msgstr "" "ตรวจสอบแผนอนุมัติการตั้งค่าจากนั้นรีสตาร์ทตัวแทนของคุณ เชื่อมต่อแล้ว? " "ดำเนินการต่อด้านล่าง" -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. ถามที่ CSV ถูกเขียน" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2958,7 +2966,7 @@ msgstr "" "{ph0}บันทึกการส่งออก{ph1} ปุ่ม " "ตัวแทนของคุณสามารถตรวจสอบรหัสได้โดยไม่ต้องติดตั้งหรือเปิดตัว Electron." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2968,14 +2976,14 @@ msgstr "ตัวแทนของคุณดาวน์โหลดไฟล #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}ดาวน์โหลดตัวอย่างไปรษณีย์{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2985,12 +2993,12 @@ msgstr "" "หากตัวแทนของคุณไม่สามารถดาวน์โหลดไฟล์ได้ให้เปิดเครื่องรูดที่เก็บถาวรนี้ด้วยตัวเอง" " ให้มันเส้นทางไป {ph0} โฟลเดอร์และคำถามการส่งออกเดียวกัน" -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. ทำตามคำตอบกลับไปที่รหัส" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "ค้นหาคำอธิบายสั้นๆด้วยการอ้างอิงไฟล์และบรรทัด:" @@ -2999,7 +3007,7 @@ msgstr "ค้นหาคำอธิบายสั้นๆด้วยกา #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3010,12 +3018,12 @@ msgstr "" "ปุ่มส่ง {ph0} ข้อความ รูปแบบกระบวนการหลักบันทึกเป็น CSV และเขียน {ph1} " "ในโฟลเดอร์ดาวน์โหลดของผู้ใช้ คอลัมน์คือ {ph2} และ {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "จากปุ่มไปยังนักเขียนไฟล์" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3023,7 +3031,7 @@ msgid "" msgstr "" "REAการวิเคราะห์แบบคงที่ของคู่ข้อความที่มีการจัดการ ปลายทางถูกอ่านจากรหัส" -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3034,18 +3042,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}ดูการติดตามรหัสเต็มรูปแบบและบันทึก REA ผลลัพธ์{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. พรีเมียร์ลีก" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3054,19 +3062,19 @@ msgstr "" "เครื่องหมายจุลภาคแยก CSV คอลัมน์ " "จะเกิดอะไรขึ้นเมื่อชื่อโน้ตมีเครื่องหมายจุลภาคหรือใบเสนอราคา" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "เรียกใช้การตรวจสอบตัวเอง" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "เปิดเทอร์มินัลในห่อ {ph0} โฟลเดอร์:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3075,24 +3083,24 @@ msgstr "" "คำสั่งนี้ใช้เชลล์ที่มีการสนับสนุนเอกสารที่นี่เช่นการทุบตีหรือ " "ตัวแทนของคุณสามารถทำงานได้เหมือนกัน JavaScript ในเปลือกของแพลตฟอร์มของคุณ" -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. ถามคำถามอื่น" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "ลองติดตามผลในการสนทนาเดียวกัน:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "จะเกิดอะไรขึ้นหากไม่สามารถเขียนไฟล์ได้ ทำตามข้อผิดพลาดกลับไปยังหน้า" -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3104,7 +3112,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3119,7 +3127,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3133,7 +3141,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3157,65 +3165,65 @@ msgstr "" "ลองดู REA ในแอพพลิเคโน้ตขนาดเล็ก " "ตั้งค่าตัวแทนของคุณขอที่บันทึกส่งออกไปและตรวจสอบ CSV รูปแบบที่มีชื่อตัวอย่าง" -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "ครั้งแรกของคุณ REA การสืบสวน" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "คัดลอก REA พร้อมท์การติดตั้ง" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "คัดลอกคำสั่งการตั้งค่า" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "คัดลอกบันทึกการตรวจสอบพรอมต์" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "คัดลอก CSV ตรวจสอบพรอมต์" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "คัดลอกคำสั่งตรวจสอบรูปแบบ" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}บ้าน{ph1} /เริ่มต้นใช้งาน" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "ตั้งค่า REA." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3223,49 +3231,49 @@ msgstr "" "เชื่อมต่อ REA " "ให้กับตัวแทนการเข้ารหัสของคุณหรือตรวจสอบแอปท้องถิ่นจากสถานีของคุณ" -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "เปิดเทอร์มินัลและตรวจสอบ:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "เทอร์มินัล" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "คัดลอก" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0}Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3278,7 +3286,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3289,17 +3297,17 @@ msgstr "" "{ph0}\"การเรียกใช้สคริปต์ถูกปิดใช้งานในระบบนี้\"{ph1} เมื่อคุณวิ่ง {ph2} " "เรียกใช้ครั้งนี้และลองอีกครั้ง:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "ถ้าคุณใช้ Homebrew:" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "มิฉะนั้น:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "ปิดเทอร์มินัลเปิดอีกครั้งแล้ว:" @@ -3307,7 +3315,7 @@ msgstr "ปิดเทอร์มินัลเปิดอีกครั้ #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3319,7 +3327,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3331,7 +3339,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3340,14 +3348,14 @@ msgid "" msgstr "" "ต้องการติดตั้งปกติหรือไม่ ดาวน์โหลดรุ่นแอลทีเอสจาก {ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "ตัวเลือกการตั้งค่า" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3355,7 +3363,7 @@ msgstr "{ph0}เชื่อมต่อตัวแทนการเข้า #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3363,7 +3371,7 @@ msgstr "{ph0}ใช้ CLI{ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3371,18 +3379,18 @@ msgstr "{ph0}ตั้งค่าการวิเคราะห์โปร #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}การรับความช่วยเหลือ{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "เชื่อมต่อตัวแทนการเข้ารหัสของคุณ" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3394,12 +3402,12 @@ msgstr "" "Grok Build และสนับสนุนอื่นๆ MCP ลูกค้า เชื่อมต่อGrok " "Botจะถูกเพิ่มจากการแชทของ" -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "ใหม่สำหรับตัวแทนการเขียนโค้ด?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3410,7 +3418,7 @@ msgstr "" " มันสามารถอ่านไฟล์และเรียกใช้คำสั่งและจะถามก่อนที่จะทำการเปลี่ยนแปลง REA " "ให้เครื่องมือวิศวกรรมย้อนกลับ" -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3420,7 +3428,7 @@ msgstr "หากคุณยังไม่ได้หนึ่งเลือ #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3433,7 +3441,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3444,7 +3452,7 @@ msgstr "{ph0}{ph1}Codex{ph2}{ph3} โดย OpenAI. ลงชื่อเข้ #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3454,7 +3462,7 @@ msgstr "" "{ph0}{ph1}OpenCode{ph2}{ph3},โอเพนซอร์ส " "เชื่อมต่อผู้ให้บริการรูปแบบที่คุณเลือก" -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3471,18 +3479,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "หรือเรียกใช้การตั้งค่าด้วยตัวคุณเอง" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "ฉันจะเปิดเทอร์มินัลได้อย่างไร?" @@ -3491,7 +3499,7 @@ msgstr "ฉันจะเปิดเทอร์มินัลได้อย #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3505,7 +3513,7 @@ msgstr "{ph0}Windows:{ph1} เปิดเมนูเริ่ม,ชนิด #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3518,7 +3526,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3531,7 +3539,7 @@ msgstr "{ph0}Linux:{ph1} สื่อมวลชน {ph2} {ph3} {ph4} บนเ #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3541,7 +3549,7 @@ msgstr "" "วางคำสั่งด้วย {ph0} {ph1} (macOS: {ph2} {ph3}; Linux เทอร์มินัล: {ph4} {ph5}" " {ph6})จากนั้นกดป้อน" -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3552,12 +3560,12 @@ msgstr "" "การเชื่อมต่อและทักษะการตรวจสอบการจับคู่การรักษาสำรองของการกำหนดค่าที่มีอยู่ " "มันถามก่อนที่จะใช้การเปลี่ยนแปลง" -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "รีสตาร์ทไคลเอนต์ของคุณเมื่อเสร็จสิ้นการติดตั้ง" -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "ฉันจะรีสตาร์ทลูกค้าของฉันได้อย่างไร?" @@ -3566,7 +3574,7 @@ msgstr "ฉันจะรีสตาร์ทลูกค้าของฉั #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3581,7 +3589,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3591,7 +3599,7 @@ msgstr "" "{ph0}ตัวแทนเทอร์มินัล{ph1} (Claude Code, Codex, Gemini " "CLI):ออกจากเซสชั่นและเริ่มต้นอีกครั้ง" -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3601,7 +3609,7 @@ msgstr "" " Electron แอพคุณอาจเริ่มต้นด้วย:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3611,12 +3619,12 @@ msgstr "" "ดูสิ {ph0} และหาวิธีที่จะส่งออกข้อมูล " "แสดงจุดเข้าโทรและการอ้างอิงที่เกี่ยวข้องกับสถานที่แหล่งที่มาสำหรับการค้นพบของคุณ" -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "แทนที่เส้นทางด้วยเป้าหมายท้องถิ่นของคุณ" -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "ฉันจะได้รับเส้นทางเต็มของโฟลเดอร์ได้อย่างไร" @@ -3625,7 +3633,7 @@ msgstr "ฉันจะได้รับเส้นทางเต็มขอ #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3639,7 +3647,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3651,7 +3659,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3661,17 +3669,17 @@ msgstr "" "{ph0}ระบบใดๆ:{ph1} " "ลากโฟลเดอร์ลงในหน้าต่างเทอร์มินัลและเส้นทางของมันปรากฏขึ้น" -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "ในเทอร์มินัลใส่ใบเสนอราคารอบเส้นทางที่มีช่องว่าง" -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "ใช้ CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3679,14 +3687,14 @@ msgid "" msgstr "" "วิเคราะห์เป็นJavaScriptหรือElectronองโปรแกรมหรือโฟลเดอร์ASARแฟ้มจัดเก็บโดยไม่มีกำลังแอพฯ:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "การวิเคราะห์แอปพลิเคชันแบบคงที่" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3696,13 +3704,13 @@ msgstr "" "แทนที่พาธด้วยไดเรกทอรีแอปที่คุณแยกออกหรือ {ph0} แฟ้ม บน Windows เส้นทางเช่น " "{ph1} ทำงานที่นี่" -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "ฉันจะหาแอปได้ที่ไหนแฟ้มอะซาร์?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3713,7 +3721,7 @@ msgstr "Electron ปพลิเคชันมักจะเก็บไว้ #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3725,7 +3733,7 @@ msgstr "{ph0}Windows:{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3738,20 +3746,20 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0}Linux:{ph1} มักจะ {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "บางแอปติดตั้งที่อื่น ค้นหาโฟลเดอร์ของแอป {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3762,31 +3770,31 @@ msgstr "" " การเชื่อมต่อ REA ไม่สามารถแก้ไขได้ถูกทำเครื่องหมายในผลลัพธ์" #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "ถ้าคุณต้องการถาวร {ph0} คำสั่งในเปลือกของคุณ:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "ติดตั้ง CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}ดำเนินการต่อด้วย JavaScript คู่มือการสมัคร{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "ตั้งค่าการวิเคราะห์โปรแกรมเครื่องรหัส" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3795,12 +3803,12 @@ msgstr "" "ไบนารีพื้นเมืองต้องการเครื่องมือวิเคราะห์ท้องถิ่น " "เลือกและกำหนดค่าหนึ่งด้านล่างแล้วให้ REA ปฏิบัติการหรือห้องสมุดของคุณ" -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "เลือกเครื่องมือ: Ghidra, Hopper หรือ IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3812,17 +3820,17 @@ msgstr "" "การติดตั้งต้องใช้ตัวถอดคอมไพเลอร์พื้นเมืองสำหรับสถาปัตยกรรมโฮสต์ของคุณ " "ตั้งค่าพาธก่อนรันการตั้งค่า:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "เชื่อมต่อของคุณ Ghidra การติดตั้ง" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidraการเชื่อมต่อ·macOS/Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3833,12 +3841,12 @@ msgstr "" "การตั้งค่าการตรวจสอบพวกเขาและบันทึกการตั้งค่าที่ถูกต้องสำหรับลูกค้าที่คุณเลือก" " บน Linux แขน64 คุณอาจจำเป็นต้องสร้าง Ghidraพื้นเมืองแยกต่างหาก" -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "เชื่อมต่อ Ghidra บน Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3849,18 +3857,18 @@ msgstr "" " 86 เท่าและ 64 ใช้ที่มีอยู่ Ghidra 12.1.การติดตั้งเอ็กซ์และเจดีเค 64 บิต 21 " "หรือใหม่กว่า:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra การเชื่อมต่อ · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "แทนที่เส้นทางสองเส้นทางด้วยการติดตั้งจากนั้นตรวจสอบแผนการติดตั้ง" -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3869,7 +3877,7 @@ msgstr "" "เชื่อมต่อHopperบmacOSหรือLinux. " "รันคำสั่งการติดตั้งข้างต้นจะตรวจพบการติดตั้งที่มีอยู่หรือเสนอแผนการติดตั้งเพื่อขออนุมัติ" -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3878,7 +3886,7 @@ msgstr "" "บน macOS,สมบูรณ์ " "Hopperทางเลือกที่ทำงานครั้งแรกของโหมดการสาธิตหรือการเปิดใช้งานใบอนุญาตก่อนที่จะวิเคร" -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3889,7 +3897,7 @@ msgstr "" "การประมวลผลข้อมูล,คีย์ข้อมูล,การพิมพ์ดีดคัดลอก Linux และ macOS " "การวิเคราะห์แบบไร้หัวขาดยังคงไม่ได้รับการยืนยัน" -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "เชื่อมต่อที่มีอยู่ IDA MCP ลงทะเบียน" @@ -3899,7 +3907,7 @@ msgstr "เชื่อมต่อที่มีอยู่ IDA MCP ลงท #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3911,13 +3919,13 @@ msgstr "" "ที่มีอยู่ {ph3} วัตถุที่มี {ph4} สามารถเข้าชมได้ จุด REA " "ที่ไฟล์ก่อนที่จะติดตั้ง:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA การเชื่อมต่อ · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3935,7 +3943,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3946,29 +3954,29 @@ msgstr "" "ให้ REA เส้นทางปฏิบัติการเดิมด้วย {ph0} ใน CLI งคุณ สำหรับตัวแทนรวมถึง {ph1}" " ใน REA สภาพแวดล้อมการลงทะเบียนและเลือก IDA เมื่อเปิดไบนารี" -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "สำหรับที่มีอยู่ Ghidra การติดตั้งตรวจสอบฟังก์ชั่นที่มี:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "การวิเคราะห์ฟังก์ชัน" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "แทนที่ {ph0} ด้วยชื่อฟังก์ชั่นหรือที่อยู่ที่คุณต้องการตรวจสอบ" -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "วิธีการวิเคราะห์โปรแกรมโค้ดเครื่องทำงานของเซสชัน" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3980,7 +3988,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3990,18 +3998,18 @@ msgstr "" "{ph0}ติดตามการวิเคราะห์ของโปรแกรมเครื่องรหัสตัวอย่าง{ph1} " "เพื่อดูว่าผลฟังก์ชั่นที่นำไปสู่การคำนวณกู้คืน" -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "การรับความช่วยเหลือ" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "ถ้าตัวแทนของคุณไม่เห็น REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4011,27 +4019,27 @@ msgstr "" "รีสตาร์ทหรือเชื่อมต่อไคลเอ็นต์หลังจากการตั้งค่า ตรวจสอบ REA การเชื่อมต่อกับ " "{ph0};สำหรับ Codex:" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "ตรวจสอบลูกค้าหนึ่งราย" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "หากผู้ให้บริการต้องการความสนใจ" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "ตรวจสอบผู้ให้บริการที่คุณใช้ สำหรับ Ghidra:" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "ตรวจสอบผู้ให้บริการหนึ่งราย" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "รายงานให้ตรวจสอบล้มเหลวและแนะนำขั้นตอนถัดไป." @@ -4040,7 +4048,7 @@ msgstr "รายงานให้ตรวจสอบล้มเหลวแ #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4053,7 +4061,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4067,7 +4075,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4080,7 +4088,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4102,112 +4110,112 @@ msgstr "" "เชื่อมต่อREAต้องของคุณเขียนโปรแกรหรือเจ้าหน้าที่ตรวจท้องถิ่JavaScriptหรือElectronแอพจากเทอร์มินัล." " การตั้งค่าคำถามแรกและคำแนะนำผู้ให้บริการพื้นเมือง" -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "คัดลอก Node.js ตรวจสอบรุ่น" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "คัดลอก Node.js คำสั่งการติดตั้งสำหรับ Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "คัดลอกคำสั่งตั้งค่านโยบายการเรียกใช้สคริปต์ของ PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "คัดลอก Homebrew Node.js คำสั่งการติดตั้ง" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "สำเนาคำสั่งการติดตั้งสำหรับ macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "คัดลอก Node.js 24 คำสั่งสำหรับ macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "สำเนาคำสั่งการติดตั้งสำหรับ Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "คัดลอก Node.js 24 คำสั่งสำหรับ Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REAคู่มือการเริ่มต้นใช้งาน" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "คัดลอก REA พร้อมท์การติดตั้ง" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "คัดลอกคำสั่งการตั้งค่าตัวแทน" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "คัดลอกJavaScriptคำสั่งการวิเคราะห์" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "คัดลอกCLIคำสั่งการติดตั้ง" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "คัดลอกคำสั่งเชื่อมต่อ Ghidra สำหรับ macOS และ Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "คัดลอก Ghidra การเชื่อมต่อสำหรับ Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "คัดลอก IDA การเชื่อมต่อสำหรับ Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "คัดลอกคำสั่งการวิเคราะห์ฟังก์ชันพื้นเมือง" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "คัดลอกคำสั่งการวินิจฉัยไคลเอ็นต์" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "คัดลอกคำสั่งการวินิจฉัยผู้ให้บริการ" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -4216,20 +4224,20 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}บ้าน{ph1} / {ph2}กเขา{ph3} /การสังเกตเบราว์เซอร์" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "ดูว่าเกิดอะไรขึ้น{ph0}เมื่อคุณคลิก" -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4238,14 +4246,14 @@ msgstr "" "การเขียนข้อความโฆษณา,การเขียนในนามคนอื่น,บทความ,การเขียนเนื้อหา JavaScript " "ที่สร้างการดาวน์โหลด" -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "ในคู่มือนี้" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4253,7 +4261,7 @@ msgstr "{ph0}ตัวอย่าง{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4261,7 +4269,7 @@ msgstr "{ph0}เปิดเบราว์เซอร์{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4269,7 +4277,7 @@ msgstr "{ph0}สอบถามตัวแทนของคุณ{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4277,13 +4285,13 @@ msgstr "{ph0}จับภาพจาก CLI{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}อ่านคำขอและสคริปต์{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "เกิดอะไรขึ้นเมื่อคุณคลิกส่งออก?" @@ -4293,7 +4301,7 @@ msgstr "เกิดอะไรขึ้นเมื่อคุณคลิก #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4304,7 +4312,7 @@ msgstr "" "ร {ph0}ตัวอย่างเบราว์เซอร์หมายเหตุ{ph1} มี {ph2}บันทึกการส่งออก{ph3} ปุ่ม " "คลิกโหลด {ph4} รูปแบบสองบันทึกเป็น CSV และเริ่มต้นการดาวน์โหลด" -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "จากการคลิกที่ CSV ดาวน์โหลด" @@ -4315,7 +4323,7 @@ msgstr "จากการคลิกที่ CSV ดาวน์โหลด" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4330,7 +4338,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4348,7 +4356,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4358,17 +4366,17 @@ msgstr "" "{ph0}03·ตัวแทนของคุณ{ph1}{ph2}อ่านรหัสส่งออก{ph3}{ph4}เชื่อมต่อคำขอสังเกตไปที่" " {ph5} ใน {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "เริ่มการจับภาพก่อนที่จะคลิกส่งออกหมายเหตุ" -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "เปิด Chrome ด้วยการดีบักระยะไกล" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4377,21 +4385,21 @@ msgstr "" "เปิดตัวอย่างบันทึกย่อที่โฮสต์กับโปรไฟล์เบราว์เซอร์ที่แยกต่างหากและพอร์ตการดีบักโลคั" " บนLinux:" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "เริ่มต้นเบราว์เซอร์ตัวอย่าง" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "คัดลอก" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4400,7 +4408,7 @@ msgstr "" "ใช้เส้นทางปฏิบัติการของเบราว์เซอร์ที่ติดตั้งบน macOS หรือ Windows. " "คุณสามารถแทนที่ลิงค์เพจด้วยเพจอื่นที่คุณต้องการตรวจสอบได้" -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4409,7 +4417,7 @@ msgstr "" "REA เชื่อมต่อกับเบราว์เซอร์ที่มีอยู่นี้ " "คุณสามารถควบคุมเพจดำเนินการและปิดเบราว์เซอร์เมื่อเสร็จสิ้น" -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "เว็บแคม,ถ้ำมอง,ซ่อน,จับได้,นอกใจ," @@ -4422,7 +4430,7 @@ msgstr "เว็บแคม,ถ้ำมอง,ซ่อน,จับได้ #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4434,7 +4442,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเ #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4445,7 +4453,7 @@ msgstr "" "สิ่งที่ร้องขอไม่ได้ทำให้และวิธีการที่เป็น CSV สร้าง?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4455,7 +4463,7 @@ msgstr "" "รือไม่ ให้ตัวแทนของคุณดีบักปลายทาง, {ph0} และลิงค์หน้า " "ให้มันเริ่มการจับภาพก่อนที่จะคลิก" -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4465,23 +4473,23 @@ msgstr "" "ตัวแทนของคุณค้นพบเป้าหมายหน้าเริ่มต้นหน้าต่างสังเกตการณ์และอ่านหลักฐานที่เกิดขึ้น" " จากนั้นก็สามารถตรวจสอบสคริปต์ที่อยู่เบื้องหลังการส่งออก" -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "หรือจับภาพจากเทอร์มินัล" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "ค้นหารหัสเป้าหมายของหน้าเว็บ:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "ค้นหาหน้าเว็บ" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4491,14 +4499,14 @@ msgstr "" "เลือกเป้าหมายด้วยลิงค์ตัวอย่างหมายเหตุ แทนที่ {ph0} " "ด้านล่างมีรหัสของตนแล้วเรียกใช้:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "จับสิบวินาทีถัดไป" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4508,7 +4516,7 @@ msgstr "" "ให้คำสั่งเชื่อมต่อไม่กี่วินาที,แล้วคลิก {ph0}บันทึกการส่งออก{ph1} " "ในเบราว์เซอร์ที่ ผลลัพธ์จะมาถึงหลังจากที่หน้าต่างการสังเกตสิ้นสุดลง" -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4518,49 +4526,49 @@ msgstr "" "ผลลัพธ์ที่จับมีเพจที่เลือกกิจกรรมของเครือข่ายระหว่างหน้าต่างนั้นและรูปร่างของการตอ" " คำขอก่อนหน้านี้อยู่นอกการจับภาพนี้" -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "อ่านคำขอและส่งออกสคริปต์" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "บันทึกด้วย REA 4.1.0 ในตัวอย่างบันทึกท้องถิ่น" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "จับความจริง" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "ค่า" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "คำขอ" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "การตอบสนอง" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "ผู้ริเริ่มการร้องขอ" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} *สคริปต์" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "โครงสร้างการตอบสนอง" @@ -4568,19 +4576,19 @@ msgstr "โครงสร้างการตอบสนอง" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} ด้วย {ph1} และ {ph2} สนาม" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "อ่านสคริปต์ที่โหลด" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4591,7 +4599,7 @@ msgstr "" "อ่านแหล่งที่มาของสคริปต์ที่จับเพื่อดูว่ามีการใช้ข้อมูล:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4603,7 +4611,7 @@ msgstr "" "ขั้นตอนการจัดรูปแบบมาจากสคริปต์;จับเครือข่ายกำหนดว่าการคลิกนี้ร้องขอ {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4615,7 +4623,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4639,65 +4647,65 @@ msgstr "" "สังเกตบันทึกการส่งออกด้วย " "REA:เลือกหน้าเบราว์เซอร์จับคลิกตรวจสอบการร้องขอและทำตามสคริปต์การส่งออก" -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "การสังเกตเบราว์เซอร์" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "คัดลอกเริ่มต้นตัวอย่างเบราว์เซอร์" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "คัดลอกตัวอย่างพรอมต์" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "คัดลอกค้นหาหน้า" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "คัดลอกจับภาพสิบวินาทีถัดไป" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "คัดลอกอ่านสคริปต์ที่โหลด" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}บ้าน{ph1} /คู่มือ" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA กเขา" -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4706,37 +4714,37 @@ msgstr "" "วิเคราะห์ฟังก์ชั่นพื้นเมืองและ Electron ส่งออกหรือคำขอเบราว์เซอร์ " "คู่มือแต่ละคนรวมถึงให้รหัสและผล" -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "การสืบสวนครั้งแรก" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "ตั้งค่า REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "เชื่อมต่อตัวแทนการเข้ารหัสของคุณหรือใช้ REA จากอาคารผู้โดยสาร" -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "เริ่มต้นใช้งาน REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "โปรแกรมเครื่องรหัส" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "กู้คืนการคำนวณของตำแหน่งเสียงซ้าย/ขวา" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4745,22 +4753,22 @@ msgstr "" "เริ่มต้นด้วย Windows ปฏิบัติการเกม " "ตรวจสอบคำแนะนำ,ทำตามโทร,อ่านค่าคงที่ตัวเลขและตรวจสอบการกู้คืนซี." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "คู่มือการวิเคราะห์โปรแกรมเครื่องรหัส" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "ทำตาม CSV ส่งออก" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4769,30 +4777,30 @@ msgstr "" "แอพพลิเคบันทึกย่อขนาดเล็กกระจายคุณลักษณะหนึ่งในการแสดงผล,โหลดล่วงหน้าและกระบ" " ใช้ REA การเขียนข้อความโฆษณา,การเขียนในนามคนอื่น,บทความ" -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript & Electron คู่มือ" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "สำหรับแอปที่บรรจุขนาดใหญ่ให้ทำตาม {ph0}Notionสะพานคลิปบอร์ด{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "พฤติกรรมของเบราว์เซอร์" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "สังเกตการคลิก" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4800,7 +4808,7 @@ msgid "" msgstr "" "เปิดตัวอย่างบันทึกการทำงานจับการร้องขอการส่งออกและหารหัสที่จะเปลี่ยนการตอบสน" -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "คู่มือการสังเกตเบราว์เซอร์" @@ -4819,12 +4827,12 @@ msgstr "" "เรียนรู้ REA ผ่านตัวอย่างการทำงานสั้น:การคำนวณพื้นเมืองและ Electron CSV " "การส่งออกและคำขอเบราว์เซอร์" -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -4833,20 +4841,20 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}บ้าน{ph1} / {ph2}กเขา{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "ตามรอย Electron{ph0}CSV งกัน" -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4855,14 +4863,14 @@ msgstr "" "การตลาดทางอินเทอร์เน็ต,การขาย,การตลาด,การโฆษณา Electron การเงินและการลงทุน " "CSV นักเขียนไฟล์" -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "ในคู่มือนี้" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4870,7 +4878,7 @@ msgstr "{ph0}ตัวอย่าง{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4878,7 +4886,7 @@ msgstr "{ph0}สอบถามตัวแทนของคุณ{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4886,7 +4894,7 @@ msgstr "{ph0}ติดตามรหัสส่งออก{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4894,20 +4902,20 @@ msgstr "{ph0}ลองตัวอย่าง{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}ตรวจสอบ CSV นักเขียน{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "ที่ไม่\"บันทึกการส่งออก\"ไป?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4919,7 +4927,7 @@ msgstr "" "การเขียนข้อความโฆษณา,บล็อก,การเขียนในนามคนอื่น,บทความ,การเขียนเนื้อหา CSV. " "ลักษณะการทำงานจะถูกกระจายไปทั่วหลายแฟ้ม" -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "ร CSV ส่งออกข้าม Electron กระบวนการ" @@ -4933,7 +4941,7 @@ msgstr "ร CSV ส่งออกข้าม Electron กระบวนกา #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4950,7 +4958,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4966,7 +4974,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4979,13 +4987,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} รูปแบบบันทึกย่อ→ {ph1} เขียน {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -4995,14 +5003,14 @@ msgstr "" "REA การเรียกตัวจัดการและระบุเอพีไอที่เปิดเผย " "พาธจะอนุมานจากรหัสจับรันไทม์สามารถตรวจสอบสิ่งที่ดำเนินการ" -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "ถามเกี่ยวกับ CSV ส่งออก" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5020,14 +5028,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "คัดลอก" @@ -5038,7 +5046,7 @@ msgstr "คัดลอก" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5049,7 +5057,7 @@ msgstr "" "สร้าง?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5057,7 +5065,7 @@ msgid "" "{ph0}." msgstr "รือไม่ รวมเส้นทางที่แน่นอนไปยังโฟลเดอร์โปรแกรมประยุกต์หรือ {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5067,17 +5075,17 @@ msgstr "" "REA อ่านไฟล์โปรแกรมและสร้างแผนที่จุดเข้าโมดูลและขอบเขตของกระบวนการ " "ตัวแทนของคุณใช้แผนที่เพื่อจำกัดการสืบสวนให้แคบลงให้เป็นคุณลักษณะการส่งออก" -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "ติดตามรหัสส่งออก" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "การแปลภาษา,การพิสูจน์อักษร,การตรวจแก้" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5087,7 +5095,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5099,7 +5107,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5109,7 +5117,7 @@ msgstr "" "การอ่านผู้ดูแลตอบคำถามเดิม: {ph0} รูปแบบบันทึกและกระบวนการหลักเขียน {ph1} " "ลงในโฟลเดอร์ดาวน์โหลดของผู้ใช้" -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5118,7 +5126,7 @@ msgstr "" "บันทึกโดย REA 4.1.0 ในตัวอย่างที่สามารถดาวน์โหลดได้ด้านล่าง " "การวิจัยทางการเงิน,การเงิน,ตลาดการเงิน,การวิเคราะห์ทางการเงิน" -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "วิเคราะห์ตัวอย่างด้วยตัวคุณเอง" @@ -5126,25 +5134,25 @@ msgstr "วิเคราะห์ตัวอย่างด้วยตัว #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}ดาวน์โหลดตัวอย่างไปรษณีย์{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "เรียกดูไฟล์ที่มาหก" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "การวิเคราะห์แอปพลิเคชันแบบคงที่" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5155,7 +5163,7 @@ msgstr "" "คุณควรหาช่องทางไอพีซีหนึ่งช่องและตัวจัดการการจับคู่หนึ่งใน {ph0}. " "สถานที่ที่มาอยู่ใน {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5166,13 +5174,13 @@ msgstr "" "ตัวแทนสามารถทำตามสตริงที่แท้จริงชื่อเอพีไอหรือช่องทางไอพีซีด้วย " "REAคุณลักษณะของเครื่องมือติดตาม" -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "ตรวจสอบ CSV นักเขียน" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5182,7 +5190,7 @@ msgstr "" "ทำตาม {ph0} ไปยังผู้จัดการของตน ซึ่งปัจจัยการผลิตถึง CSV " "นักเขียนและสิ่งที่เกิดขึ้นถ้าการเขียนไฟล์ล้มเหลว?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5196,7 +5204,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5210,7 +5218,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5223,7 +5231,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5248,32 +5256,32 @@ msgstr "" "ออกแบบเว็บไซต์,ออกแบบกราฟิก,ออกแบบโลโก้,การสร้างตราสินค้า REA. " "รวมไฟล์ตัวอย่างที่สามารถดาวน์โหลดได้และผลการวิเคราะห์ที่ได้รับการยืนยัน" -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "คัดลอกตัวอย่างพรอมต์" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "คัดลอกการวิเคราะห์แอ็พพลิเคชันแบบคงที่" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -5282,34 +5290,34 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}บ้าน{ph1} / {ph2}กเขา{ph3} /การวิเคราะห์โปรแกรมเครื่องรหัส" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "กู้คืน DX-Ballของ{ph0}การคำนวณเสียงแพน" -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " "check the recovered C." msgstr "ตรวจสอบคำแนะนำเดิมระบุการป้อนข้อมูลและค่าคงที่แล้วตรวจสอบการกู้คืนซี" -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "ในคู่มือนี้" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5317,7 +5325,7 @@ msgstr "{ph0}ตัวอย่าง{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5325,7 +5333,7 @@ msgstr "{ph0}สอบถามตัวแทนของคุณ{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5333,7 +5341,7 @@ msgstr "{ph0}อ่าน REA ผลลัพธ์{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5341,18 +5349,18 @@ msgstr "{ph0}กู้คืนและตรวจสอบ{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}ใช้ไบนารีของคุณเอง{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "คำนวณตำแหน่งเสียงสเตอริโอซ้าย/ขวา" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5363,7 +5371,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5374,7 +5382,7 @@ msgstr "" "ฟังก์ชั่นเริ่มต้น, {ph0} มีผลแยกคอมไพเลอร์สั้น:เรียกฟังก์ชันไป {ph1}. REA " "งกลับคำแนะนำและเรียกฟังก์ชันซึ่งให้ตัวแทนวิธีการตรวจสอบเลขคณิตที่ขาดหายไป" -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "ใหม่กับเงื่อนไขเหล่านี้?" @@ -5383,7 +5391,7 @@ msgstr "ใหม่กับเงื่อนไขเหล่านี้?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5395,7 +5403,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5408,7 +5416,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5420,7 +5428,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5430,7 +5438,7 @@ msgstr "{ph0}ที่อยู่:{ph1} ตำแหน่งในโปรแ #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5439,7 +5447,7 @@ msgid "" msgstr "" "{ph0}ค่าคงที่:{ph1} ตัวเลขคงที่เก็บไว้ในโปรแกรมอ่านเป็นไบต์ดิบและถอดรหัส" -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "สามชิ้นของหลักฐานหนึ่งการคำนวณ" @@ -5450,7 +5458,7 @@ msgstr "สามชิ้นของหลักฐานหนึ่งกา #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5466,7 +5474,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5484,7 +5492,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5494,7 +5502,7 @@ msgstr "" "{ph0}03·ไบต์ข้อมูล{ph1}{ph2}ค่าคงที่เป็นตัวเลข{ph3}{ph4}ไบต์อ้างอิงถอดรหัสไป" " {ph5}, {ph6} และค่าสเกล{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5503,7 +5511,7 @@ msgstr "" "REA ให้คำแนะนำ,ความสัมพันธ์การเรียกฟังก์ชันและไบต์. " "เจ้าหน้าที่ตีความพวกเขาด้วยกัน" -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "ถามเกี่ยวกับพฤติกรรม" @@ -5512,7 +5520,7 @@ msgstr "ถามเกี่ยวกับพฤติกรรม" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5523,19 +5531,19 @@ msgstr "" "{ph2}การตั้งค่าเครื่องมือวิเคราะห์พื้นเมือง{ph3} " "ให้ปฏิบัติการในท้องถิ่นและคำถาม:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "ฉันควรใช้เครื่องมือวิเคราะห์ใด" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA การศึกษาและการติว,อังกฤษ(สหราชอาณาจักร),อังกฤษ(สหรัฐอเมริกา):" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5549,7 +5557,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5561,7 +5569,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5571,7 +5579,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5586,14 +5594,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "คัดลอก" @@ -5604,7 +5612,7 @@ msgstr "คัดลอก" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5614,7 +5622,7 @@ msgstr "" "{ph0}›{ph1}{ph2}ใช้ REA เพื่อหาวิธีการ DX-Ball คำนวณเสียงแพน " "อธิบายการคำนวณและแสดงรหัส{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5626,7 +5634,7 @@ msgstr "" "เพื่อใช้สำเนาของคุณเองหรือถามชนิดเดียวกันของคำถามเกี่ยวกับขนาดเล็กอื่น " "Windows โปรแกรมที่คุณมี" -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "ฉันจะได้รับเส้นทางเต็มของแฟ้มได้อย่างไร" @@ -5635,7 +5643,7 @@ msgstr "ฉันจะได้รับเส้นทางเต็มขอ #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5649,7 +5657,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5661,7 +5669,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5670,17 +5678,17 @@ msgid "" msgstr "" "{ph0}ระบบใดๆ:{ph1} ลากไฟล์ลงในหน้าต่างเทอร์มินัลและเส้นทางของมันจะปรากฏขึ้น" -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "อ่าน REA ผลลัพธ์" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "อ่านข้อมูล" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5689,13 +5697,13 @@ msgstr "" "คำแนะนำโหลดอาร์กิวเมนต์จำนวนเต็มและแปลงสำหรับเลขคณิตจุดลอยตัว " "นี่คือการป้อนข้อมูลที่ขาดจากมุมมองหลอกแรก" -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "ติดตามฟังก์ชันที่เรียก" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5705,12 +5713,12 @@ msgstr "" "REA ระบุตัวฟังก์ชันที่เรียกหาอิฐ คำแนะนำก่อนหน้านี้คูณกระเบื้องประสานงานด้วย" " 30;เพิ่ม {ph0} (20)ให้ตำแหน่งหน้าจอของอิฐ" -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "อ่านค่าคงที่อ้างอิง" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5719,12 +5727,12 @@ msgstr "" "คณิตศาสตร์อ้างอิงที่อยู่เหล่านี้ " "การอ่านไบต์เป็นค่าจริงลำดับคำสั่งจะบอกเอเจนต์ว่ามีการใช้งานอย่างไร" -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "เขียนและตรวจสอบฟังก์ชั่นการกู้คืน" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5735,7 +5743,7 @@ msgstr "" "ก่อนที่จะแปลงจำนวนเต็ม " "การคำนวณทำให้ศูนย์กลางของหน้าจอที่ศูนย์กลางของสนามสเตอริโอ" -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5747,21 +5755,21 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "" "{ph0}เครื่องชั่งสำหรับธุรกิจค้าปลีกอาหารเครื่องชั่งคิดราคาเครื่องชั่งติดป้ายราคา{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "ลองใช้ไบนารีของคุณเอง" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5774,7 +5782,7 @@ msgstr "" "แล้วให้ตัวแทนของคุณปฏิบัติการในท้องถิ่นหรือห้องสมุดและคุณลักษณะในการตรวจสอบ " "คำถามเริ่มต้นที่มีประโยชน์รวมถึง\"วิธีการคือไฟล์นี้แยก?\"หรือ\"ฟังก์ชั่นใดที่จัดการกับการกระทำของเมนูนี้”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5783,13 +5791,13 @@ msgstr "" "ถ้าคุณรู้อยู่แล้วว่าชื่อฟังก์ชั่นหรือที่อยู่คุณสามารถสอบถามได้จากขั้ว " "สำหรับการกำหนดค่า Ghidra การติดตั้ง:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "การวิเคราะห์ฟังก์ชัน" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5802,7 +5810,7 @@ msgstr "" "CLI การอิมพอร์ตการเรียกใช้และการวิเคราะห์ไบนารีแล้วปิดเซสชัน ตัวแทนของคุณ " "MCP การสืบค้นข้อมูลใช้ไบนารีที่นำเข้าอีกครั้งในขณะที่เซสชันนั้นเปิดอยู่" -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5825,50 +5833,50 @@ msgstr "" "กู้คืนการคำนวณพื้นเมืองด้วย " "REA:ตรวจสอบคำแนะนำตามโทรอ่านค่าคงที่และตรวจสอบการสร้างขึ้นใหม่ซี" -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "การวิเคราะห์โปรแกรมเครื่องรหัส" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "คัดลอกตัวอย่างพรอมต์" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "คัดลอกการวิเคราะห์ฟังก์ชัน" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "ตั้งค่า REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5876,7 +5884,7 @@ msgstr "{ph0}ตั้งค่า REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5884,7 +5892,7 @@ msgstr "{ph0}เรื่องคืออะไร?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5892,7 +5900,7 @@ msgstr "{ph0}REA ช่วยอย่างไร{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5900,7 +5908,7 @@ msgstr "{ph0}เกมไดโนเสาร์{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5908,7 +5916,7 @@ msgstr "{ph0}เครื่องคิดเลข{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5916,7 +5924,7 @@ msgstr "{ph0}ลองดู REA{ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5924,7 +5932,7 @@ msgstr "{ph0}ศึกษาเพิ่มเติม{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5932,25 +5940,25 @@ msgstr "{ph0}ความช่วยเหลือและข้อเสน #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}ชุมชน{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "วิศวกรรมย้อนกลับกับตัวแทนการเข้ารหัสของคุณ" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "เรียนรู้ว่า{ph0}ซอฟต์แวร์ทำงานอย่างไร" -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5961,7 +5969,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5969,13 +5977,13 @@ msgstr "รู้อยู่แล้วว่าอีกครั้ง? {ph0 #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "ต้องการที่จะไปลึก? {ph0}อ่านบล็อก→{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "วางพรอมป์ต์นี้ในผู้ช่วยเขียนโค้ด AI ของคุณ:" @@ -5988,38 +5996,38 @@ msgstr "วางพรอมป์ต์นี้ในผู้ช่วยเ #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "คัดลอก" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "หรือรันคำสั่งนี้ในเทอร์มินัล:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "ตรวจสอบและอนุมัติแผนการตั้งค่า แล้วเริ่มผู้ช่วยใหม่" -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "วิศวกรรมย้อนกลับคืออะไร?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6032,7 +6040,7 @@ msgstr "การทำความเข้าใจซอฟต์แวร์ #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6044,7 +6052,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6052,7 +6060,7 @@ msgstr "ก่อนใช้ REA · คุณต้องตรวจสอบ #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6060,7 +6068,7 @@ msgstr "{ph0}01{ph1} ถอดรหัสสาขา" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6068,7 +6076,7 @@ msgstr "{ph0}02{ph1} ติดตามการโทร" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6078,20 +6086,20 @@ msgstr "{ph0}03{ph1} กู้คืนกฎ" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}ต้นฉบับ 64·เลือกคำแนะนำ{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01·สาขาใด?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6101,29 +6109,29 @@ msgstr "" "“{ph0}0*5 บาท? 0*5 องศาเซลเซียส?{ph1} สองกระโดดไปยังสถานที่เดียวกัน " "ผู้ประกอบการคนไหน”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "ค้นหารหัสคำสั่งแล้วติดป้ายชื่อสาขา" -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "แบ่ง÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "คูณ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · ฟังก์ชันที่เรียกทำอะไร?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6133,24 +6141,24 @@ msgstr "" "\"100 เป็นที่ชัดเจน การโทรเป็นแค่ที่อยู่ {ph0}อันไหนแบ่งกัน? " "ซึ่งค่าไปใน?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "ตรวจสอบฟังก์ชั่นผู้ช่วยและติดตามค่าที่เก็บไว้" -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "แบ่ง" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03·กฎคืออะไร?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6160,19 +6168,19 @@ msgstr "" "\"เส้นทางนี้คูณด้วยอินพุตอื่นๆ แล้ว {ph0}10%หมายถึง 10%ของ 200{ph1} " "หลังจาก+.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "ตั้งชื่อตัวดำเนินการและตรวจสอบเส้นทางตัวดำเนินการทั้งสอง" -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "เหตุผลผู้เชี่ยวชาญที่เป็นตัวอย่าง" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6182,20 +6190,20 @@ msgstr "{ph0}คุณถอดรหัสคำแนะนำตามสา #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "เมื่อใช้ REA · คุณถาม {ph0}ผู้ช่วย AI{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "ใช้พรอมป์ต์เดียวก็พอ" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6209,49 +6217,49 @@ msgstr "ถามผู้ช่วย {ph0}ด้วยภาษาทั่ว #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวอย่างพรอมต์*เครื่องคิดเลข" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "คำตอบตัวอย่าง·ขึ้นอยู่กับการค้นพบ" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "หลังจาก+ปุ่ม%ใช้เวลา {ph0}เปอร์เซ็นต์ของจำนวนแรก{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "ข้อมูลที่ REA ให้" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "คำแนะนำของผู้จัดการถอดรหัสและการโทร" -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "สิ่งที่ผู้ช่วยอธิบาย" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "ซึ่งสาขาที่ใช้สิ่งที่มันคำนวณและวิธีการที่จะสร้างมัน" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6263,7 +6271,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6273,37 +6281,37 @@ msgstr "" "{ph0}ลองสองตัวอย่าง{ph1} " "เปลี่ยนความเร็วของเกมแล้วกลับไปที่เครื่องคิดเลขและสร้างปุ่ม%ของมัน" -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "ตัวอย่าง 01*Chromeเกมไดโนเสาร์" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "ทำไมไดโนเสาร์จึงวิ่งเร็วขึ้น?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "งเขา" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "สร้างเกมด้วย {ph0}ปรับความเร็ว{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "ทำไมวิศวกรรมย้อนกลับมันได้หรือไม่" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6313,48 +6321,48 @@ msgstr "" "ในการเร่งความเร็วของมันเราต้องการ " "{ph0}กฎในเกมที่ทำงาน{ph1}:วิธีที่รวดเร็วจะเริ่มต้นวิธีการที่มันจะเพิ่มขึ้นและเมื่อมันหยุด" -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "เล่นเกมที่สร้างขึ้นใหม่" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "เล่น" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "กระโดด ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "เริ่มใหม่" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "ความเร็ว" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "ใช้กฎการเร่งการกู้คืน" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "กฎเดิม:เริ่มต้นที่ 6 จากนั้นเพิ่มขึ้นถึง 13" -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "เลื่อนแถบเลื่อนเพื่อตั้งค่าความเร็วของคุณเอง พื้นที่หรือกระโดดล้างแคคตัส" -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6362,14 +6370,14 @@ msgid "" msgstr "" "เปิดใช้งาน JavaScript เพื่อเล่นการฟื้นฟู รหัสและคำอธิบายข้างต้นยังคงอ่านได้" -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "ผลลัพธ์ที่ REA ส่งกลับ" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6387,7 +6395,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6399,7 +6407,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวอย่างพร #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6412,7 +6420,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6424,7 +6432,7 @@ msgstr "ตรวจสอบเป้าหมาย: {ph0}วายู Chromiu #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6434,12 +6442,12 @@ msgstr "" "{ph0}เริ่มที่ 6{ph1} เพิ่ม {ph2}0.001{ph3} " "แต่ละการปรับปรุงโดยไม่ต้องปะทะกันในขณะที่ความเร็วอยู่ด้านล่าง {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "เปิดห้องปฏิบัติการความเร็ว→" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "สิ่งที่แต่ละส่วนทำ" @@ -6450,7 +6458,7 @@ msgstr "สิ่งที่แต่ละส่วนทำ" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6466,7 +6474,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6481,7 +6489,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6490,13 +6498,13 @@ msgid "" msgstr "" "{ph0}03·คุณ{ph1}{ph2}เปลี่ยนความเร็วและเล่น{ph3}{ph4}ลองเร่งเดิมแล้วเลือกก้าวของคุณเอง{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "ดูสคริปต์การตรวจสอบและวิธีการลองวิเคราะห์" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6506,7 +6514,7 @@ msgstr "" "REA ตรวจสอบรุ่นเบราว์เซอร์ผ่านการเชื่อมต่อดีบักท้องถิ่นและส่งกลับโหลด {ph0} " "รวมทั้งแหล่งที่มาและย่อย" -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6519,7 +6527,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6535,7 +6543,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6552,7 +6560,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6560,19 +6568,19 @@ msgid "" msgstr "" "{ph0}ตรวจสอบรหัสความเร็ว{ph1} · {ph2}Chromium ผู้เขียน·ใบอนุญาตบีเอส{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "ตัวอย่าง 02*Windowsเครื่องคิดเลข" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "สร้างปุ่ม % ของเครื่องคิดเลขขึ้นใหม่" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6581,7 +6589,7 @@ msgstr "สร้างเครื่องคิดเลขขนาดเล #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6591,29 +6599,29 @@ msgstr "" "ปุ่มเดียวกันใช้ {ph0}กฎที่แตกต่างกันหลังจาก+และ×{ph1} " "เราตรวจสอบการตรวจสอบที่ติดตั้งเพื่อหาจำนวนเปอร์เซ็นต์ถูกนำไปใช้" -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "ลองคำนวณ" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "รีเซ็ต" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10%ของ 200=20. จากนั้น 200+20=220" -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "ภาพประกอบโต้ตอบของกฎร้อยละตรวจสอบ" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6625,7 +6633,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6639,7 +6647,7 @@ msgstr "สำหรับตัวอย่างนี้, {ph0} และ {ph #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6654,7 +6662,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6665,7 +6673,7 @@ msgstr "" "{ph0}›{ph1}{ph2}ใช้ REA เพื่อตรวจสอบ Windows ปุ่ม%ของเครื่องคิดเลข " "กู้คืนกฎหลังจาก+และ×แล้วสร้างเครื่องคิดเลขขนาดเล็กที่ใช้ทั้งสอง{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "ด้วย+" @@ -6673,13 +6681,13 @@ msgstr "ด้วย+" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}เอา 10%ของเลขแรก{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "กับ×" @@ -6687,13 +6695,13 @@ msgstr "กับ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}เปลี่ยน 10%เป็น 0.1{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "จากแอปที่ติดตั้งไปยังปุ่ม%การทำงาน" @@ -6705,7 +6713,7 @@ msgstr "จากแอปที่ติดตั้งไปยังปุ่ #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6723,7 +6731,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6733,12 +6741,12 @@ msgid "" msgstr "" "{ph0}03·ตัวแทนของคุณตีความมัน{ph1}{ph2}อธิบายและทำซ้ำกฎ{ph3}{ph4}ตรวจสอบสาขาที่มีแหล่งที่มาของไมโครซอฟท์,แล้วลอง+และ×ข้างต้น.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "ดูรหัสจริงและวิธีการตรวจสอบคำตอบ" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6758,7 +6766,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6768,17 +6776,17 @@ msgstr "" "{ph0}การดำเนินงานร้อยละ{ph1} · {ph2}กรณีทดสอบของไมโครซอฟท์{ph3} · " "{ph4}คู่มือการติดตั้งพื้นเมือง{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "การสืบสวนครั้งแรกของคุณ" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "ลองดู REA บนแอปขนาดเล็ก" -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6787,12 +6795,12 @@ msgstr "" "ดาวน์โหลดตัวอย่างบันทึกของเรา,ติดตามของ CSV " "ส่งออกและตรวจสอบการป้อนข้อมูลที่มีการเปลี่ยนแปลงอย่างใดอย่างหนึ่ง" -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "ลองตัวอย่างที่แนะนำ" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "อยากศึกษาให้ลึกขึ้นไหม?" @@ -6801,7 +6809,7 @@ msgstr "อยากศึกษาให้ลึกขึ้นไหม?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6821,13 +6829,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวอย่างพรอมต์*เว็บไซต์" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "ใช่อันนี้" @@ -6840,7 +6848,7 @@ msgstr "ใช่อันนี้" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6853,7 +6861,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวอย่างพร #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6866,23 +6874,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}ดู DX-Ball กรณีศึกษา→{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "สำหรับขั้นตอนการตั้งค่าและการวิเคราะห์เลือกเป้าหมายของคุณ:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "โปรแกรมเครื่องรหัส" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -6890,34 +6898,34 @@ msgid "" msgstr "" "ตรวจสอบฟังก์ชัน,สตริง,การอ้างอิงและเรียกฟังก์ชันความสัมพันธ์ในปฏิบัติการและไลบรารี." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "คู่มือการวิเคราะห์โปรแกรมเครื่องรหัส" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " "or ASAR archive." msgstr "การประมวลผลข้อมูล,คีย์ข้อมูล,การพิมพ์ดีดคัดลอก ASAR ยวข้อง" -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "เวิร์กโฟลว์แอ็พพลิเคชัน" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "เบราว์เซอร์และรันไทม์กิจกรรม" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -6925,12 +6933,12 @@ msgid "" msgstr "" "จับภาพกิจกรรมของเบราว์เซอร์หรือกระบวนการที่เลือกแล้วเปรียบเทียบผลลัพธ์ข้ามรัน" -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "คู่มือการสังเกตเบราว์เซอร์" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "มีคำถามไหม?" @@ -6941,7 +6949,7 @@ msgstr "มีคำถามไหม?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6951,12 +6959,12 @@ msgstr "" "{ph0}อ่านคำถามที่พบบ่อย{ph1}, {ph2}แชทกับเราใน Discord{ph3} หรือ {ph4}เปิด " "GitHub ปัญหา{ph5} สำหรับข้อบกพร่องและการร้องขอคุณสมบัติ" -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "เข้าร่วมชุมชน" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -6979,64 +6987,64 @@ msgstr "" "แอพพลิเควิศวกรย้อนกลับ,ไบนารีและพฤติกรรมเบราว์เซอร์กับตัวแทนการเข้ารหัสของคุณ" " ทำตามคำแนะนำที่ชัดเจนและลองตัวอย่างแบบโต้ตอบกับ REA." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "คัดลอก REA พร้อมท์การติดตั้ง" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "คัดลอกคำสั่งการตั้งค่า" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "ปฏิบัติตามคู่มือการวิเคราะห์เครื่องคิดเลข" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "คัดลอกคำถามร้อยละเครื่องคิดเลข" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "ไดโนเสาร์มินิเกม ใช้ปุ่มกระโดดหรือกดพื้นที่ในขณะที่เกมจะมุ่งเน้น" -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "คัดลอกไดโนเสาร์พร้อมท์วิเคราะห์" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "เลือกการคำนวณ" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "คัดลอกการวิเคราะห์เครื่องคิดเลขพร้อมท์" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "คัดลอกเว็บไซต์พร้อมท์โครงการ" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "สำเนาพร้อมท์การฟื้นฟูเกม" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -7045,25 +7053,25 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}บ้าน{ph1} / {ph2}โชว์เคส{ph3} /แอนดรอยด์" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "กรณีศึกษา·Aegisตรวจสอบความถูกต้อง" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "เครื่องพิสูจน์ตัวตนอย่างไร{ph0}สร้างรหัสล็อกอิน?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7072,17 +7080,17 @@ msgstr "" "รหัสหกหลักเปลี่ยนทุก 30 วินาที ใช้ REA เพื่อหาการคำนวณในAndroid APK " "แล้วสร้างมันด้วยนาฬิกาที่คุณสามารถควบคุม" -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3*แอนดรอยด์*การเปิดตัวอย่างเป็นทางการ APK ·6.9 ล้านบาท" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "ดู Aegis บน GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "จาก APK รหัสที่คุณสามารถทำซ้ำ" @@ -7093,7 +7101,7 @@ msgstr "จาก APK รหัสที่คุณสามารถทำซ #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7111,7 +7119,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7128,7 +7136,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7139,14 +7147,14 @@ msgstr "" "{ph0}03·สร้างและตรวจสอบ{ph1}{ph2}เปลี่ยนนาฬิกา " "ดูรหัส{ph3}{ph4}การสาธิตเบราว์เซอร์ใหม่ทำซ้ำกฎและตรวจสอบกับกรณีการอ้างอิงสาธารณะ{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "กรณีศึกษา" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7154,7 +7162,7 @@ msgstr "{ph0}สอบถามตัวแทนของคุณ{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7162,7 +7170,7 @@ msgstr "{ph0}ลองสร้างรหัส{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7170,7 +7178,7 @@ msgstr "{ph0}ค้นหารหัสด้วย REA{ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7178,7 +7186,7 @@ msgstr "{ph0}อ่านการคำนวณ{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7186,20 +7194,20 @@ msgstr "{ph0}ตรวจสอบการฟื้นฟู{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}ตรวจสอบ APK ตัวคุณเอง{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "สอบถามตัวแทนของคุณ" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7217,14 +7225,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "คัดลอก" @@ -7232,7 +7240,7 @@ msgstr "คัดลอก" # Reviewed for concrete meaning, software terminology and readable sentences. #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7242,7 +7250,7 @@ msgstr "" "พรอมป์ต์ตัวอย่างสำหรับ APK ที่ดาวน์โหลดมา ให้ตั้งค่าการวิเคราะห์ Android ของ" " REA ก่อน {ph0}ดาวน์โหลด APK และการตั้งค่าการวิเคราะห์ ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "ลองสร้างรหัส" @@ -7250,7 +7258,7 @@ msgstr "ลองสร้างรหัส" # Reviewed for concrete meaning, software terminology and readable sentences. #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7262,33 +7270,33 @@ msgstr "" "แล้วนำหมายเลขช่วงเวลากับคีย์บัญชีมาสร้างรหัส " "คีย์เดียวกันและช่วงเวลาเดียวกันจะให้รหัสเดียวกัน" -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "ย้ายนาฬิกาข้าม 60 วินาที" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "เวลา" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "วินาที" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "นาฬิกาตัวอย่างที่สามารถปรับได้ของเรา" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "บล็อก 30 วินาที" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "บล็อก" @@ -7297,35 +7305,35 @@ msgstr "บล็อก" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 วินาที{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "รหัสที่สร้างขึ้น" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "คีย์บัญชี+บล็อก six หกหลัก" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "ตัวอย่างเวลาในไม่กี่วินาที" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 วินาที" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 วินาที" @@ -7334,7 +7342,7 @@ msgstr "60 วินาที" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7346,7 +7354,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7356,25 +7364,25 @@ msgstr "" "คีย์ได้รับการแก้ไขสาธารณะ {ph0}6238 ข้อมูลการทดสอบ{ph1}. " "การสาธิตดำเนินการคำนวณกู้คืนจาก APK." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " "clock." msgstr "แผนภาพแสดงผลที่ 59 วินาที เปิดใช้งาน JavaScript เพื่อเปลี่ยนนาฬิกา" -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "ค้นหารหัสด้วย REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "แคบ APK ถึงสามชั้นเรียน" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7384,14 +7392,14 @@ msgstr "" "{ph0} เป็นผู้สมัครคำนวณ;อีกสองกังวลแถบความคืบหน้าและบัญชีที่นำเข้า TOTP " "หมายถึงรหัสผ่านแบบครั้งเดียวตามเวลา" -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "เชื่อมต่อเครื่องกำเนิดไฟฟ้าเข้ากับจอแสดงผลของแอป" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7402,7 +7410,7 @@ msgstr "" "{ph0} จากนั้นแสดงการโทรจอแสดงผล {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7411,14 +7419,14 @@ msgid "" msgstr "" "คำขอแสดงเส้นทางอินพุตที่สั้นลง ชื่อชั้นผลลัพธ์ละเว้นทั่วไป {ph0} คำนำหน้า" -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "อ่านการคำนวณ" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7432,7 +7440,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7440,7 +7448,7 @@ msgstr "{ph0}01{ph1} บล็อกเวลา" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7448,7 +7456,7 @@ msgstr "{ph0}02{ph1} กุญแจ+บล็อก" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7456,7 +7464,7 @@ msgstr "{ph0}03{ph1} หกหลัก" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7468,7 +7476,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7481,7 +7489,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7495,7 +7503,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7505,7 +7513,7 @@ msgstr "" "ตัดตอนมาจากหลายวิธีการตรวจสอบที่มีการตัดสายสำหรับการแสดงผล " "แผงด้านขวาเป็นบทสรุปอธิบาย {ph0}Aegis รหัสคือจีพีแอล-3.0{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Insideในเครื่องกำเนิดไฟฟ้า" @@ -7514,7 +7522,7 @@ msgstr "Insideในเครื่องกำเนิดไฟฟ้า" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7524,7 +7532,7 @@ msgstr "" "เปิดตัว APK ทำให้ {ph0} ใน {ph1}. REA ตามสายจาก {ph2} " "และส่งกลับร่างกายนี้แหล่งที่มาเดิมเรียกผู้ช่วย {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7540,20 +7548,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}เปรียบเทียบกับแหล่งที่มาของรีลีสที่ตรงกัน{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "ตรวจสอบการฟื้นฟู" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7565,29 +7573,29 @@ msgstr "" "ผลผลิตของพวกเขาตรงกับการฟื้นฟูอิสระ {ph0}133 กรณีทดสอบ{ph1} " "รวมถึงขอบเขตเวลาบล็อกและรหัสที่เริ่มต้นด้วยศูนย์" -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "ตัวอย่างเวลา" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "รหัสหกหลัก" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 วินาที" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 วินาที" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7597,24 +7605,24 @@ msgstr "" "เครื่องกำเนิดไฟฟ้ายังตรงกับหกตีพิมพ์ SHA-1 กรณีอ้างอิงใน {ph0}6238{ph1}. " "ตรวจสอบการใช้เบราว์เซอร์กับพวกเขา:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "เรียกใช้การตรวจสอบอ้างอิง" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "อ่านการคำนวณการสาธิต" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" "digit results." msgstr "กรณีอ้างอิงใช้แปดหลัก ตรวจสอบยังตรวจสอบผลลัพธ์หกหลักของพวกเขา" -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7623,14 +7631,14 @@ msgstr "" "การตรวจสอบการทำงานแยกวิธีการจาวาและการสาธิตใหม่ Android APK " "ได้รับการตรวจสอบแบบคงที่" -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "ตรวจสอบ APK ตัวคุณเอง" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7643,7 +7651,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7651,18 +7659,18 @@ msgid "" "{ph1}. This case used JDK 21." msgstr "17 หรือสูงกว่า เลือกด้วย {ph0} หรือ {ph1}. คดีนี้ใช้เจดีเค 21" -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "จุด REA ที่ไฟล์ผู้ให้บริการและตรวจสอบ APK:" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7674,7 +7682,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7684,7 +7692,7 @@ msgstr "" "คำถามต่อไป: " "{ph0}จะเกิดอะไรขึ้นเมื่อบัญชีใช้ตัวเลขแปดหลักหรือช่วงเวลาที่แตกต่างกัน{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "แหล่งที่มา" @@ -7700,7 +7708,7 @@ msgstr "แหล่งที่มา" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7714,13 +7722,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}กรณีอ้างอิง 6238{ph1} · {ph2}ข้อมูลการทดสอบการสาธิต{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7745,37 +7753,37 @@ msgstr "" "ตรวจสอบที่AegisAndroidAPKกับREA,ฟื้นคืนของมันหก-ตัวเลขล็อกอิน-รหัสการคำนวณและลองชิ้นกับ" " comment." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK กรณีศึกษา" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "คัดลอก Aegis ตัวอย่างพรอมต์" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "ติดตามการคำนวณการเข้าสู่ระบบรหัส" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "คัดลอก APK คำสั่งการตรวจสอบ" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -7784,26 +7792,26 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}บ้าน{ph1} / {ph2}โชว์เคส{ph3} /ซีทีเอฟ" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "กรณีศึกษา·ดาวน์ดันเดอร์ซีเอฟ 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "หาธงใน{ph0}ไบนารีซีทีเอฟ" #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7814,17 +7822,17 @@ msgstr "" "ในการตรวจสอบตัวตรวจสอบธงขนาดเล็ก,เปิดกฎของมันเป็นสมการและหาอินพุตที่ทำให้ก " "{ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "สี่เหลี่ยมสวมหน้ากากตรวจสอบธง*ง่าย · Linux 86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "ดูความท้าทายเดิม" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "จากไบนารีถึงคำตอบที่ถูกตรวจสอบ" @@ -7835,7 +7843,7 @@ msgstr "จากไบนารีถึงคำตอบที่ถูกต #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7852,7 +7860,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7870,7 +7878,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7881,21 +7889,21 @@ msgstr "" "{ph0}03*แก้ปัญหาและเรียกใช้{ph1}{ph2}กู้คืนธงยุคที่ถูกต้อง!{ph3}{ph4}สคริปต์หลามแก้สมการ" " REA จับโปรแกรมต้นฉบับที่ยอมรับผลลัพธ์{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" "ความท้าทายคือโจเซฟเผยแพร่ในพื้นที่เก็บข้อมูลอย่างเป็นทางการของดาวันเดอร์ซีฟ" -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "กรณีศึกษา" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7903,7 +7911,7 @@ msgstr "{ph0}ค้นหารหัสตรวจสอบ{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7911,7 +7919,7 @@ msgstr "{ph0}อ่านหนึ่งหน้ากาก{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7919,7 +7927,7 @@ msgstr "{ph0}ประกอบรหัสที่อ่านได้{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7927,7 +7935,7 @@ msgstr "{ph0}แก้สมการ{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7935,20 +7943,20 @@ msgstr "{ph0}ตรวจสอบคำตอบ{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}ลองด้วยตัวคุณเอง{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "ค้นหารหัสตรวจสอบ" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7966,17 +7974,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "คัดลอก" @@ -7987,7 +7995,7 @@ msgstr "คัดลอก" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7999,7 +8007,7 @@ msgstr "" "วิจัย,การเขียนทางเทคนิค,การเขียนรายงาน,การเขียนเชิงวิชาการ " "อธิบายวิธีการตรวจสอบการทำงานแล้วตรวจสอบคำตอบด้วยโปรแกรมต้นฉบับ{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8007,12 +8015,12 @@ msgid "" msgstr "" "พร้อมท์ตัวอย่างกับความท้าทายดาวน์โหลดพร้อมใช้งานภายในและการวิเคราะห์ผู้ให้บริก" -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "ทำตามพร้อมท์อินพุตไปยังฟังก์ชัน" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8020,14 +8028,14 @@ msgid "" msgstr "" "การอ้างอิงให้ตัวแทนสถานที่ในการตรวจสอบแม้ว่าชื่อฟังก์ชันเดิมของปฏิบัติการได้ถูกลบออก" -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "อ่านตรวจสอบและสองผู้ช่วย" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8039,7 +8047,7 @@ msgstr "" "ห่วงการตรวจสอบถอดรหัสหน้ากากรวมรหัสที่เลือกและเปรียบเทียบผลกับหมายเลขที่เก็บไว้" " มัน {ph0}-ขั้นตอนไบต์ข้าม {ph1} ไบต์ให้ 26 มาสก์" -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8049,12 +8057,12 @@ msgstr "" "เส้นทางเป้าหมายท้องถิ่นจะสั้นลงสำหรับการแสดงผล;ที่อยู่อ้างถึง " "REAของภาพที่นำเข้า" -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "หนึ่งตรวจสอบเผยตัวละครตัวหนึ่ง" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8066,13 +8074,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "ตรวจสอบที่เจ็ดเลือกเพียงหนึ่งตำแหน่ง {ph0}เปิดรูป{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "อ่านหน้ากากและเป้าหมายจากไบนารี" @@ -8081,7 +8089,7 @@ msgstr "อ่านหน้ากากและเป้าหมายจา #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8093,12 +8101,12 @@ msgstr "" "หมายถึง -21 เป้าหมายคือจำนวนเต็มเอนเดียนน้อย ร่วมกันไบต์เหล่านี้บอกตัวแทนที่" " {ph2} เพื่อให้ตัวละครที่เป็น {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "จากคำแนะนำในการตรวจสอบที่อ่านได้" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8108,7 +8116,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8116,7 +8124,7 @@ msgstr "{ph0}01{ph1} เริ่มต้น" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8124,7 +8132,7 @@ msgstr "{ph0}02{ph1} เลือก" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8132,7 +8140,7 @@ msgstr "{ph0}03{ph1} เพิ่ม" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8140,18 +8148,18 @@ msgstr "{ph0}04{ph1} ล่วงหน้า" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} เปรียบเทียบ" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA *เลือกคำแนะนำเดิม" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "อ่านค·สรุปหนึ่งตรวจสอบ" @@ -8159,7 +8167,7 @@ msgstr "อ่านค·สรุปหนึ่งตรวจสอบ" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8167,7 +8175,7 @@ msgstr "{ph0}01*เริ่มที่ศูนย์{ph1} {ph2} ถือผ #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8178,7 +8186,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8190,7 +8198,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8204,7 +8212,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8214,7 +8222,7 @@ msgstr "" "{ph0}05*เปรียบเทียบกับเป้าหมายที่เก็บไว้{ph1} ฟังก์ชั่นการโทรได้รับผลรวมใน " "{ph2}. ไม่ตรงกันกระโดดไป {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8223,12 +8231,12 @@ msgstr "" "คำแนะนำมาจากผู้ช่วยข้อสรุปและฟังก์ชั่นการเรียก " "คเป็นบทสรุปอธิบายที่มีชื่ออธิบายและแบนลูป 36 เซลล์" -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "แก้สมการ 26" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8239,13 +8247,13 @@ msgstr "" "รหัสอักขระและต้องมีทั้งหมด 1441 " "การเลือกที่ทับซ้อนกันให้สมการที่สคริปต์หลามขนาดเล็กสามารถแก้ร่วมกัน" -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "งูหลาม*ตัดตอนแก้" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8259,19 +8267,19 @@ msgstr "" "ธงที่มีตัวอักษรตัวเลขขีดและวงเล็บ ดาวน์โหลดที่สมบูรณ์รวมถึงทั้งหมด 26 " "หน้ากากและเป้าหมาย" -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "ดาวน์โหลดแก้ที่สมบูรณ์" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "ตรวจสอบคำตอบด้วยโปรแกรมต้นฉบับ" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8283,47 +8291,47 @@ msgstr "" "เปลี่ยนตัวอักษรที่เลือกจาก {ph0} ถึง {ph1} ทำให้ผลรวมแรก 1440 แทน 1441 " "และโปรแกรมปฏิเสธมัน" -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "อินพุต" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "ผลลัพธ์ที่สังเกต" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "รหัสออก" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "ธงของแก้" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "ตัวละครตัวหนึ่งเปลี่ยนไป" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "แสดงธงที่กู้คืนและเอาท์พุทที่จับ" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA*เอาท์พุทโปรแกรมต้นฉบับ" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "คัดลอกธง" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8331,12 +8339,12 @@ msgid "" msgstr "" "ค่าที่กู้คืนยังตรงกับธงในการเผยแพร่ข้อมูลเมตาความท้าทายของผู้จัดงาน,ตรวจสอบหลังจ" -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "แหล่งที่มาอัตลักษณ์เป้าหมายและรายละเอียดการวิเคราะห์" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8346,7 +8354,7 @@ msgstr "" "เพิ่งวิเคราะห์และสองระบวนการจับภาพใน 8 ตุลาคม 2026 ใช้REA4.1.0 " "กับGhidra12.1.4 บLinuxx64. 86-64 เอลฟ์ 15,248 ไบต์" -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8368,7 +8376,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8378,12 +8386,12 @@ msgstr "" "{ph0}เปรียบเทียบกับแหล่งที่มาของผู้จัดงาน{ph1} · " "{ph2}ท้าทายข้อมูลเมตาและธง{ph3} · {ph4}REA บันทึกหลักฐาน{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "ลองด้วยตัวคุณเอง" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8392,13 +8400,13 @@ msgstr "" "ดาวน์โหลดความท้าทายเดิมและแก้ลงในโฟลเดอร์หนึ่ง " "ใช้พร้อมท์ข้างต้นเพื่อตรวจสอบกับตัวแทนของคุณหรือเรียกใช้สคริปต์ที่รวมอยู่" -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "เทอร์มินัล*แก้ปัญหาและเรียกใช้" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8409,7 +8417,7 @@ msgstr "" "สคริปต์พิมพ์ธงผู้สมัครวางไว้ที่พรอมต์ของโปรแกรม การแก้ความต้องการงูหลามและ " "{ph0}. การเรียกใช้ความต้องการที่ปฏิบัติการเดิม Linux จำนวน 86-64" -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "ตั้งค่า REA กับตัวแทนการเขียนโค้ดของคุณ" @@ -8429,27 +8437,27 @@ msgstr "" "ใช้ REA ธง " "หาฟังก์ชั่นการตรวจสอบสารสกัดจากหน้ากากและเปรียบเทียบธงกู้คืนกับโปรแกรมเดิม" -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "กรณีศึกษา" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "พร้อมท์ตัวอย่างการคัดลอก" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "สมการหน้ากากซีทีเอฟ;เลื่อนในแนวนอนบนหน้าจอขนาดเล็ก" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8460,42 +8468,42 @@ msgstr "" "เฉพาะเซลล์ที่ก่อให้เกิดผลรวม รหัสอักขระที่จำเป็นคือ 55 " "ซึ่งหมายความว่าอักขระคือ 7" -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "ทำตามการตรวจสอบซีทีเอฟ" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "คัดลอก" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "คัดลอกตรวจสอบซีทีเอฟที่อ่านได้" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "คัดลอก" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "คัดลอกกู้คืนธง" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "คัดลอกคำสั่งแก้" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -8504,26 +8512,26 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}บ้าน{ph1} / {ph2}โชว์เคส{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "กรณีศึกษา · DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "การฟื้นฟู DX-Ball{ph0}จากปฏิบัติการของ" # Reviewed for concrete meaning, software terminology and readable sentences. -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8532,14 +8540,14 @@ msgstr "" "เป้าหมายคือสร้างเกม Windows ปี 1996 ขึ้นใหม่ด้วยโค้ด C ที่ดูแลต่อได้ REA " "ช่วยให้เอเจนต์วิเคราะห์ฟังก์ชันในโปรแกรมต้นฉบับทีละฟังก์ชัน" -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows ไอ386·ซี · REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8551,14 +8559,14 @@ msgstr "" "งานธุรการงานทรัพยากรบุคคล>งานธุรการงานการจัดการทั่วไปงานธุรการงานทรัพยากร " "{ph0}เปิดรูป{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "กรณีศึกษา" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8566,7 +8574,7 @@ msgstr "{ph0}โครงการ{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8574,7 +8582,7 @@ msgstr "{ph0}แพนเสียง{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8582,23 +8590,23 @@ msgstr "{ph0}การตรวจสอบผลลัพธ์{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}ทำงานต่อ{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "รักษาฟังก์ชัน C" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "เปรียบเทียบกับรหัสเดิม" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "ฟังก์ชั่นที่มีการจับคู่ไบต์ที่รวบรวมไว้" @@ -8609,7 +8617,7 @@ msgstr "ฟังก์ชั่นที่มีการจับคู่ไ #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8619,12 +8627,12 @@ msgstr "" "ด่านโครงการ:7 ตุลาคม 2026 {ph0}บัญชีแยกประเภท{ph1} · " "{ph2}ความคุ้มครองการทดสอบ{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "โครงการเพื่อให้ห่างไกล" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8638,12 +8646,12 @@ msgstr "" "ทำงานในเกมที่สามารถเล่นได้อย่างต่อเนื่องกับลูกและพายฟิสิกส์,การจัดการพลังงานขึ้นแ" " Windows บูรณาการ" -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "การหาการคำนวณตำแหน่งเสียงซ้าย/ขวา" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8661,17 +8669,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "คัดลอก" @@ -8682,7 +8690,7 @@ msgstr "คัดลอก" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8692,7 +8700,7 @@ msgstr "" "{ph0}›{ph1}{ph2}ใช้ REA เพื่อหาวิธีการ DX-Ball คำนวณเสียงแพน " "อธิบายการคำนวณและแสดงรหัส{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8704,7 +8712,7 @@ msgstr "" "แบบสอบถามและหลักฐานที่อยู่เบื้องหลังคำตอบ" # Reviewed for concrete meaning, software terminology and readable sentences. -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8718,7 +8726,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8732,12 +8740,12 @@ msgstr "" "มุมมองการเรียนการสอนแสดงให้เห็นการป้อนข้อมูลสแต็คและการดำเนินงานจุดลอยตัว " "ความขัดแย้งนั้นทำให้ตัวแทนมีเหตุผลที่ชัดเจนที่จะสืบสวนต่อไป" -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "มุมมองแยกคอมไพเลอร์แรก" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8746,18 +8754,18 @@ msgstr "" "ผลลัพธ์แสดงการเรียกร้องการแปลง " "อ่านคำแนะนำด้านล่างแสดงให้เห็นการป้อนข้อมูลและการให้อาหารการคำนวณที่เรียก" -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "สามคำถามตอบผ่าน REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "กู้คืนข้อมูลที่ขาดหายไป" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8767,14 +8775,14 @@ msgstr "" "นะนำควบคู่ไปกับรหัสปลอมและฟังก์ชั่นการเรียก ที่นี่, {ph0} " "แสดงการป้อนข้อมูลจำนวนเต็มที่ขาดหายไปจากมุมมองแยกคอมไพเลอร์" -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "ติดตามฟังก์ชันที่เรียกที่จะเข้าใจการป้อนข้อมูล" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8784,12 +8792,12 @@ msgstr "" "REA ระบุสายนี้ในผลแรก คำแนะนำก่อนหน้านี้ขนาด {ph0} โดย 30;การเพิ่ม 20 " "จะช่วยให้การประสานงานหน้าจออิฐ, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "อ่านค่าที่อยู่เบื้องหลังที่อยู่หน่วยความจำ" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -8798,12 +8806,12 @@ msgstr "" "ไบต์ที่ส่งคืนจะสร้างค่าคงที่ทางคณิตศาสตร์ทั้งสองและขนาดแพนเริ่มต้น " "ตัวแทนตอนนี้มีค่าที่จำเป็นสำหรับนิพจน์ค" -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "จาก REAการค้นพบของค" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8813,7 +8821,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8821,7 +8829,7 @@ msgstr "{ph0}01{ph1} อินพุต" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8829,7 +8837,7 @@ msgstr "{ph0}02{ph1} คูณ" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8837,7 +8845,7 @@ msgstr "{ph0}03{ph1} ลบ" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8845,18 +8853,18 @@ msgstr "{ph0}04{ph1} เครื่องชั่ง" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} การคืนสินค้า" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "ต้นฉบับ 86·ข้อความที่ตัดตอนมา" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "สร้างขึ้นใหม่ค" @@ -8866,7 +8874,7 @@ msgstr "สร้างขึ้นใหม่ค" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8885,7 +8893,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8901,7 +8909,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8918,7 +8926,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8935,7 +8943,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8947,7 +8955,7 @@ msgstr "" "REAผลของแคลลี าการปวดหลังและอาการบวม {ph4};เปรียบเทียบต้นฉบับ-86 " "เทียบตรวจสอบค่าที่ส่งคืน" -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -8957,23 +8965,23 @@ msgstr "" "ข้อความที่ตัดตอนมาประกอบเลือกป้อนข้อมูล,คณิตศาสตร์และคำแนะนำกลับมา " "รายการเต็มรูปแบบด้านล่างนอกจากนี้ยังมีร้านค้าแทรกแซงและการตั้งค่าฟังก์ชั่นและการ" -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "ประกอบเต็มรูปแบบและหลักฐานสนับสนุน" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA ผล·0*406400-0*40643" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "สิ่งที่อุปกรณ์โทร" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8983,54 +8991,54 @@ msgstr "" "ฟังก์ชั่นอิฐตีที่ {ph0} เครื่องชั่งน้ำหนักของกระเบื้องประสานงานโดย 30 เพิ่ม " "20 แล้วผลักดันมันก่อนที่จะเรียก:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "สิ่งที่ข้อมูลอ่านสร้าง" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REAไบต์อ่าน,ถอดรหัสเป็นคู่เล็กๆน้อยๆเอนเดียน" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "ที่อยู่" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "ค่า" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "ใช้สำหรับ" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "คูณครั้งแรก" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "การลบ" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} ในตอนแรก" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "ขนาดกระทะที่เก็บไว้" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9046,7 +9054,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9055,12 +9063,12 @@ msgid "" msgstr "" "{ph0}แหล่งบำรุงรักษา{ph1} · {ph2}บันทึกการตรวจสอบและการอ้างอิงหลักฐาน{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "การตรวจสอบฟังก์ชั่นการกู้คืน" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9068,12 +9076,12 @@ msgid "" msgstr "" "ฟังก์ชั่นการกู้คืนผ่านการตรวจสอบสอง:ค่าส่งคืนตรงกับต้นฉบับและไบต์ที่คอมไพล์ตรงกับปฏิ" -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3,205 กรณีพฤติกรรม" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9084,12 +9092,12 @@ msgstr "" "และเปรียบเทียบค่าตอบแทนของมันกับซีที่เก็บรักษาไว้มันครอบคลุมทุกตำแหน่งจำนวนเต็มตั้งแต่" " 0 ถึง 640 ที่ห้าเครื่องชั่งแพน:0,0.5,1,20 และ -1" -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 ไบต์ที่ตรงกัน" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9099,7 +9107,7 @@ msgstr "" "4.0 " "รีเพลย์คอมไพเลอร์ตรงกับฟังก์ชันที่สมบูรณ์หลังจากใช้การย้ายที่ตรวจสอบและตรวจสอบค่า" -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9113,18 +9121,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}อ่านรายละเอียดรีเพลย์คอมไพเลอร์{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "ต่อการสืบสวน" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9133,7 +9141,7 @@ msgid "" msgstr "" "วิธีการเดียวกันจะถูกใช้สำหรับการปรับปรุงอนุภาคคิวการระเบิดและการสร้างโบนัส:ตรวจ" -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9142,7 +9150,7 @@ msgstr "" "เพื่อตรวจสอบฟังก์ชั่นเสียงแพนด้วยตัวคุณเองให้ทำตาม DX-Ball " "คำแนะนำในการติดตั้งของโครงการและจัดหาเป้าหมายเดิมที่ตรงกัน แล้วเรียกใช้:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "ใน DX-Ball ชำระเงิน" @@ -9151,7 +9159,7 @@ msgstr "ใน DX-Ball ชำระเงิน" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9165,7 +9173,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9181,7 +9189,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9204,13 +9212,13 @@ msgstr "" "ทำตาม DX-Ball ฟื้นฟูจากการวิเคราะห์ไบนารีผ่าน REA การทดสอบ 86 " "และการจับคู่ไบต์ฟังก์ชันที่รวบรวมไว้" -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ball การตรวจสอบเสียงแพน;เลื่อนในแนวนอนบนหน้าจอขนาดเล็ก" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9223,87 +9231,87 @@ msgstr "" "ครั้งไทล์_เอ็กซ์คำแนะนำในการโหลด,คูณด้วย 1.5625,ลบ 500.0,ใช้แพนสเกลและกลับ " "86 ใน 3,205 กรณีและโดยคอมไพเลอร์รีเพลย์ 4.0 ที่ตรงกับ 63 ไบต์" -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball กรณีศึกษาการฟื้นฟู" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "คัดลอกตัวอย่างพรอมต์" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "ติดตามการคำนวณตำแหน่งเสียงซ้าย/ขวา" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "คัดลอกประกอบต้นฉบับ" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "คัดลอกฟังก์ชั่นเสียงแพน" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "คัดลอกประกอบเสียงแพนที่สมบูรณ์" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "คัดลอกDX-Ballคำสั่งการวิเคราะห์" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}บ้าน{ph1} /ตู้โชว์" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA กรณีศึกษา" -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" " results." msgstr "Android,เกมส์, Electron รหัส,ตัวเลขและผลการตรวจสอบ" -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "แอนดรอยด์ · APK การวิเคราะห์" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "วิธีที่ผู้รับรองความถูกต้องสร้างรหัสล็อกอิน" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9313,22 +9321,22 @@ msgstr "" "ค้นหา Aegisการคำนวณรหัสหกหลักในการเปิดตัวของ APK. ติดตามวิธีการสร้างด้วย REA" " แล้วย้ายนาฬิกาสาธิตเพื่อดูว่าทำไมรหัสการเปลี่ยนแปลงทุก 30 วินาที" -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "อ่านกรณีศึกษาAndroid" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "การวิเคราะห์ของโปรแกรมเครื่องรหัส" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "คีย์ข้อมูล,การพิมพ์ดีดคัดลอก" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9338,22 +9346,22 @@ msgstr "" "ตรวจสอบความท้าทายที่ลดลงง่ายด้วย REA. " "ค้นหาฟังก์ชั่นการตรวจสอบของเปิดหน้ากากและผลรวมเป็นสมการแล้วตรวจสอบธงแก้ไข" -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "อ่านกรณีศึกษาซีทีเอฟ" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "พื้นเมือง*ฟื้นฟู" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ballการคำนวณเสียงแพน" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9363,22 +9371,22 @@ msgstr "" "กู้คืนการคำนวณเสียงกระทะจาก 1996 Windows เกม " "REAล็กการตรวจสอบกับพฤติกรรมเดิมและทั้งหมด 63 ไบต์ที่รวบรวม" -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "อ่าน DX-Ball กรณีศึกษา" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron*การติดตามคุณลักษณะ" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "ยังไง Notion คัดลอกข้อความและเอชทีเอ็ม" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9388,22 +9396,22 @@ msgstr "" "ออกแบบกราฟิก,ออกแบบโลโก้ Notionบรรจุ JavaScript. " "การป้องกันไวรัสมัลแวร์และอุปกรณ์ที่หายไปสำหรับมาร์ทโฟนและแท็บเล็" -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "อ่าน Notion กรณีศึกษา" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98ดอส*ฟื้นฟู" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "ยังไง TH04 มีจุดมุ่งหมายแหวนกระสุน" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9413,17 +9421,17 @@ msgstr "" "ตรวจสอบผู้ช่วยมุม 16 บิตเดิมด้วย REA. " "นการประสานงานกับแถวคอ่านแล้วดูว่าพวกเขาผลิตแหวนที่มุ่งเป้าไปที่ผู้เล่น" -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "อ่าน TH04 กรณีศึกษา" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "คำแนะนำทีละขั้นตอน" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9432,7 +9440,7 @@ msgstr "" "คำแนะนำเดินผ่านการคำนวณพื้นเมืองและ Electron การส่งออกและคำขอเบราว์เซอร์ " "แต่ละคนเริ่มต้นด้วยพรอมต์และเป้าหมายที่เป็นรูปธรรม" -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "อ่านคำแนะนำ" @@ -9451,12 +9459,12 @@ msgstr "" "ทำตาม REA การตรวจสอบผ่านรหัส,ตัวเลขและการสาธิต:การตรวจสอบAndroid, DX-Ball, " "Notion, TH04 และนักตรวจสอบธงขาลง" -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -9465,25 +9473,25 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}บ้าน{ph1} / {ph2}โชว์เคส{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "กรณีศึกษา · Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "ยังไง Notion สำเนา{ph0}ข้อความและเอชทีเอ็ม" -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9493,12 +9501,12 @@ msgstr "" "Notionการเขียนข้อความโฆษณา,การเขียนในนามคนอื่น,บทความ,การเขียนเนื้อหา " "Electronนักเขียนคลิปบอร์ด" -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notionพื้นที่ทำงาน 7.6.1·JavaScript·REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "สะพานภายใน Notionแพ็คเกจเดสก์ท็อป" @@ -9510,7 +9518,7 @@ msgstr "สะพานภายใน Notionแพ็คเกจเดสก #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9527,7 +9535,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9544,7 +9552,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9561,7 +9569,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9572,13 +9580,13 @@ msgstr "" "การเขียนข้อความโฆษณา,การเขียนในนามคนอื่น{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "ช่องทางหนึ่งร่วมทั้งสองฝ่าย: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9587,14 +9595,14 @@ msgstr "" "รหัสที่บรรจุใช้ช่องเดียวกันในการโหลดและกระบวนการหลัก การแก้ไขห่อเผยให้เห็น " "Electron เรียกฟังก์ชันตามชื่อพวกนั้น" -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "กรณีศึกษา" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9602,7 +9610,7 @@ msgstr "{ph0}ตามสะพานคลิปบอร์ด{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9610,19 +9618,19 @@ msgstr "{ph0}รักษาโครงสร้างของบล็อก{ #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}ตัวอย่างและแหล่งที่มาเพิ่มเติม{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "การดำเนินการคัดลอกไปที่ไหน?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9641,17 +9649,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "คัดลอก" @@ -9662,7 +9670,7 @@ msgstr "คัดลอก" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9672,7 +9680,7 @@ msgstr "" "{ph0}›{ph1}{ph2}ใช้ REA เพื่อติดตามวิธีการ Notion อร์ดระบบ " "แสดงรหัสในแต่ละขั้นตอน{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9681,12 +9689,12 @@ msgstr "" "ตัวอย่างพร้อมท์ด้วย " "Notionแพคเกจโปรแกรมท้องถิ่นที่มีให้ตัวแทนการเข้ารหัสของคุณ" -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA ค้นหาตำแหน่งที่จะเริ่มต้นการอ่าน" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9696,13 +9704,13 @@ msgstr "" "การวิเคราะห์โหลดพรีโหลดแท็บด้วย REA การเรียกที่ส่งคำขอไอพีซี " "การค้นพบทั้งสองมาพร้อมกับช่วงแหล่งที่มาในกลุ่มย่อ:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA ผลการวิจัย→สองสถานที่ที่จะเปิด" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9715,7 +9723,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9729,12 +9737,12 @@ msgstr "" "ชื่อนั้นทำให้ตัวแทนบางสิ่งบางอย่างที่แม่นยำในการค้นหาในกลุ่มหลัก. " "สี่ข้อความที่ตัดตอนมาด้านล่างแสดงเส้นทางที่เชื่อมต่อ." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "สี่ชิ้นสั้นของรหัส" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9743,13 +9751,13 @@ msgstr "" "ง่ายจากบรรจุ JavaScript มีชื่อตัวแปรที่อ่านได้ " "สมาชิกที่ไม่เกี่ยวข้องจะถูกละเว้น" -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "การเขียนข้อความโฆษณา,การเขียนในนามคนอื่น" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9759,13 +9767,13 @@ msgstr "" "สมาชิกนี้ระบุชื่อช่อง การดำเนินงานของ {ph0} " "บอกเราว่าคำขอออกจากกระบวนการของหน้าเว็บอย่างไร" -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "แก้ไขกระดาษห่อของโหลด" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9775,14 +9783,14 @@ msgstr "" "ฟังก์ชั่นกลับส่งต่ออาร์กิวเมนต์ผ่าน Electronคำขอและการตอบสนองของไอพีซี " "ตอนนี้เราสามารถมองหา {ph0} ในด้านกระบวนการหลัก" -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "ตรวจสอบวิธีการลงทะเบียนผู้รับ" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9792,12 +9800,12 @@ msgstr "" "กระบวนการหลักใช้กระดาษห่ออื่น มัน {ph0} วิธีการลงทะเบียน {ph1} " "รับสัญญาณสำหรับช่องทางที่" -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "ค้นหาการเขียนและการตรวจสอบผู้ส่ง" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9808,13 +9816,13 @@ msgstr "" "Electronคลิปบอร์ดเอพีไอ " "ช่องและตัวห่อที่แก้ไขแล้วสองตัวเชื่อมต่อวิธีการเปิดเผยกับสายนี้" -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "บล็อกที่ถูกคัดลอกเก็บโครงสร้างไว้ได้อย่างไร" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9824,27 +9832,27 @@ msgstr "" "Notionแก้ไขข้อความ {ph0}. " "การป้องกันไวรัสในเชิงรุกและการรักษาความปลอดภัยที่จะไปมือถือด้วยความมั่นใจ" -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "เชื่อมโยงไปยังบล็อกข้อมูลที่บันทึกไว้" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "อ่านรหัสเอชทีเอ็มแอล" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "ค้นหารหัสท้องถิ่นเดียวกัน" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "คืนค่า Notion บล็อกข้อมูล" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -9853,7 +9861,7 @@ msgstr "" "ข้อความและรหัสตัวอย่าง " "การทดสอบโมดูลที่บันทึกไว้คืนค่าข้อมูลบล็อกเมื่อตรงกับรหัส;รายการเก่าส่งกลับเฉพาะข้อค" -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -9862,22 +9870,22 @@ msgstr "" "เมื่อวาง, Notion ตรวจสอบกับสำเนาที่บันทึกไว้ " "รหัสที่ตรงกันจะคืนค่าข้อมูลที่ถูกบล็อก" -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "รูปแบบคลิปบอร์ดที่บันทึกจากเนื้อหาเว็บแคชเมื่อวันที่ 13 กรกฎาคม 2026" -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "ตัวอย่างและแหล่งที่มาเพิ่มเติม" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "อีกตัวอย่างหนึ่ง:ตารางยอด" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -9886,25 +9894,25 @@ msgstr "" "Notion วิเคราะห์ยอดรวมลงในข้อมูลบล็อก " "ตัวอย่างนี้แสดงให้เห็นว่าตารางกลายเป็นแถวส่วนหัวและข้อมูล" -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "ตารางผ่าน Notionวิเคราะห์ยอดรวมของ" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " "and cells." msgstr "ผลลัพธ์ที่บันทึกจากตัวแยกยอดรวม ตารางจะกลายเป็นแถวและเซลล์" -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "เส้นทางอื่น:การเชื่อมต่อแบบออฟไลน์" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9917,7 +9925,7 @@ msgstr "" "กระบวนการหลักสร้างแชแนลข้อความและให้พอร์ตหนึ่งไปยังตัวแสดงผลและอื่นๆไปยังกระบ" " ชุดคำสั่งที่ตามมาและผลการเดินทางผ่านพอร์ตที่" -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -9925,7 +9933,7 @@ msgid "" msgstr "" "ต่อไปนี้แฮนด์ออฟนี้อธิบายที่ทำงานฐานข้อมูล,และทำไมการติดตามเพียงการร้องขอไอพีซีเ" -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "แหล่งที่มาและวิธีการอ่านข้อความที่ตัดตอนมา" @@ -9933,7 +9941,7 @@ msgstr "แหล่งที่มาและวิธีการอ่าน #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9951,7 +9959,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9966,7 +9974,7 @@ msgstr "" "สินทรัพย์เหล่านั้นมีเวอร์ชั่นของตัวเอง " "โพรบที่บันทึกไว้ดำเนินการแยกโมดูลและสายรัดขนาดเล็ก;ผลของพวกเขาอธิบายหัววัดเหล่" -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -9981,7 +9989,7 @@ msgstr "" "สมาชิกคลิปบอร์ดและรับจับคู่มีการเชื่อมต่อโดยการอ่านการใช้งานห่อของพวกเขาในแพค" #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9998,7 +10006,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10012,7 +10020,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10037,52 +10045,52 @@ msgstr "" "ทำตาม Notionของคลิปบอร์ดเอพีไอผ่าน " "Electronโหลดของห่อไอพีซีและกระบวนการหลักที่มีข้อความที่ตัดตอนมารหัสสั้นและดูที่รูปแบบคลิปบอ" -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron กรณีศึกษา" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "คัดลอก Notion พรอมต์การวิเคราะห์" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "คัดลอก Notion โหลดข้อความที่ตัดตอนมา" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "คัดลอก Notion เรียกตัดตอนเสื้อคลุมห่อ" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "คัดลอก Notion ตัวจัดการตัดตอน" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "คัดลอก Notion ข้อความที่ตัดตอนมาจากคลิปบอร์ด" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "การกู้คืนข้อมูลคลิปบอร์ดที่อุดมไปด้วยในการวาง" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "ข้ามไปที่เนื้อหา" @@ -10091,25 +10099,25 @@ msgstr "ข้ามไปที่เนื้อหา" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}บ้าน{ph1} / {ph2}โชว์เคส{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "กรณีศึกษา*ทูโฮ 4:เรื่องโลตัสแลนด์" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "การฟื้นฟู TH04ของ{ph0}รูปแบบกระสุน" -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10118,17 +10126,17 @@ msgstr "" "แหวนของกระสุนเริ่มต้นด้วยการคำนวณมุมสั้น ใช้ REA " "รวจสอบฟงกชันดอสดั้งเดิมจากนั้นปฏิบัติตามคำแนะนำของฟงกชันดอสที่สามารถอ่านได" -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 ·ดอส 16 บิต·ซีดีและแอสเซมบลี" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "ดู TH04 การฟื้นฟู" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "จากคำแนะนำเดิมไปยังแหล่งที่มาที่ตรวจสอบ" @@ -10139,7 +10147,7 @@ msgstr "จากคำแนะนำเดิมไปยังแหล่ง #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10155,7 +10163,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10172,7 +10180,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10188,7 +10196,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10199,7 +10207,7 @@ msgstr "" "{ph0}04·ตรวจสอบแหล่งที่มา{ph1}{ph2}2,139 " "ไบต์ที่ตรงกัน{ph3}{ph4}ตรวจสอบคอมไพเลอร์ที่บันทึกไว้ครอบคลุมรหัสรุ่นกระสุนที่ประกอบด้วยตัวช่วยนี้{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10208,14 +10216,14 @@ msgstr "" "REA ส่งกลับรหัสต้นฉบับและหลักฐานการวิเคราะห์ ร TH04 " "โครงการอุปกรณ์การบำรุงรักษาแหล่งที่มาและคอมไพเลอร์ตรวจสอบ" -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "กรณีศึกษา" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10223,7 +10231,7 @@ msgstr "{ph0}แหวนกระสุน{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10231,7 +10239,7 @@ msgstr "{ph0}อะไรนะ REA การคืนสินค้า{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10239,7 +10247,7 @@ msgstr "{ph0}การชุมนุมที่จะค++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10247,18 +10255,18 @@ msgstr "{ph0}การตรวจสอบแหล่งที่มา{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}โครงการเต็ม{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "วิธีแหวนเล็งไปที่ผู้เล่น" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10277,16 +10285,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}ตัวแทนการเข้ารหัสของคุณ" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "คัดลอก" @@ -10297,7 +10305,7 @@ msgstr "คัดลอก" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10308,7 +10316,7 @@ msgstr "" "สร้างแหวนของกระสุนและมีจุดมุ่งหมายที่ผู้เล่น " "อธิบายการคำนวณและแสดงรหัส{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10317,7 +10325,7 @@ msgstr "" "พร้อมท์ตัวอย่างด้วยการเช็คเอาท์ที่ปฏิบัติการและการฟื้นฟูเดิมที่มีอยู่ภายใน" #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10331,7 +10339,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10341,12 +10349,12 @@ msgstr "" "ภาพประกอบของคณิตศาสตร์มุมกู้คืนสำหรับการนับ 16 ทิศทางผู้เล่น 40 " "และการหมุนแม่แบบ 0 {ph0}เปิดรูป{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "แม่แบบการยิงในแหล่งที่มาที่กู้คืน" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "การโจมตีแหวนของเอลลี่*ที่มาตัดตอนมา" @@ -10355,7 +10363,7 @@ msgstr "การโจมตีแหวนของเอลลี่*ที #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10365,13 +10373,13 @@ msgstr "" "เส้นเหล่านี้เลือกรูปแบบก่อนที่จะปรับความยากลำบากและประสิทธิภาพการทำงาน " "{ph0}อ่านแหล่งที่มาของการโจมตี{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "อะไรนะ REA การคืนสินค้า" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10382,12 +10390,12 @@ msgstr "" "เราตรวจสอบ {ph0} ฟังก์ชั่นที่กำหนดความเร็วและมุมของกระสุน REA " "ส่งคืนคำแนะนำของรหัสปลอมและการอ้างอิง สามส่วนของผลลัพธ์นั้นอธิบายรูปแบบ" -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "ตรวจสอบภาพก่อนอ่านรหัส" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10396,7 +10404,7 @@ msgstr "" "ตรวจสอบผูกโค้ดที่โหลดและระเบียนการย้ายไปยังปฏิบัติการที่ให้มา " "เส้นทางด้านบนจะสั้นลงสำหรับการแสดงผล" -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "อ่านแหวนคูณและหาร" @@ -10404,7 +10412,7 @@ msgstr "อ่านแหวนคูณและหาร" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10415,12 +10423,12 @@ msgstr "" "{ph0} ถือดัชนีกระสุน กะคูณด้วย 256 แล้วส่วนที่ใช้นับอ่านจาก {ph1}. " "ชื่อแหล่งที่มาที่เก็บรักษาไว้ {ph2}. ลำดับที่สมบูรณ์ปรากฏด้านล่าง" -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "หาที่รูปแบบหันไปทางผู้เล่น" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10433,12 +10441,12 @@ msgstr "" "ชื่อแหล่งที่มาทำให้ที่อยู่เหล่านั้นสามารถอ่านได้; REA " "ช่วยให้ตัวแทนตรวจสอบการดำเนินงานเดิมที่อยู่เบื้องหลังพวกเขา" -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "จากการชุมนุมที่จะอ่านค++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10450,7 +10458,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10458,7 +10466,7 @@ msgstr "{ph0}01{ph1} ดัชนี" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10466,7 +10474,7 @@ msgstr "{ph0}02{ph1} อวกาศ" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10474,7 +10482,7 @@ msgstr "{ph0}03{ph1} เล็ง" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10482,18 +10490,18 @@ msgstr "{ph0}04{ph1} หมุน" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} ร้านค้า" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA *คำแนะนำเดิม 16 บิต" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Reอ่านได้ค*สรุปเล็งแหวน" @@ -10501,7 +10509,7 @@ msgstr "Reอ่านได้ค*สรุปเล็งแหวน" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10515,7 +10523,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10530,7 +10538,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10544,7 +10552,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10558,7 +10566,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10571,7 +10579,7 @@ msgstr "" " ค่าห่อหลังจาก 255 เช่นเดียวกับการหล่อไบต์ที่ไม่ได้ลงนามไม่ " "แหล่งที่มาโดยรอบยังแปลงมุมนี้และความเร็วเป็นความเร็ว" -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10583,7 +10591,7 @@ msgstr "" " " "ตรวจสอบคอมไพเลอร์ด้านล่างนำไปใช้กับแหล่งที่มาของการบำรุงรักษาในโครงการที่เชื่" -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "อ่านแหวนที่เก็บรักษาไว้และจุดมุ่งหมาย" @@ -10600,7 +10608,7 @@ msgstr "อ่านแหวนที่เก็บรักษาไว้แ #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10610,12 +10618,12 @@ msgstr "" "{ph0}แมโครแหวน{ph1} · {ph2}จุดมุ่งหมายและแหล่งที่มาของความเร็ว{ph3} · " "{ph4}การแสดงมุม{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "การตรวจสอบแหล่งที่มาที่บำรุงรักษา" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10625,24 +10633,24 @@ msgstr "" "การตรวจสอบการบันทึกของโครงการรวบรวมรหัสรุ่นกระสุน,รวมทั้งผู้ช่วยนี้,กับเทอร์โบตรึงค" " 44.0" -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 ไบต์ที่ตรงกัน" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " "original executable." msgstr "รหัสรุ่นกระสุนที่คอมไพล์ตรงกับส่วน 2,139 ไบต์ของปฏิบัติการเดิม" -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "สองสร้างสะอาด" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10655,65 +10663,65 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "บันทึกใน 3 ตุลาคม 2026. {ph0}อ่านการตรวจสอบคอมไพเลอร์{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "อัตลักษณ์เป้าหมายและขอบเขตการวิเคราะห์" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "เป้าหมายเดิม" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0},156,258 ไบต์,เมกะไบต์" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "รายการผู้ช่วย" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} ใน REAภาพโหลดของ" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "ชดเชยแฟ้มต้นฉบับ" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0},ส่งคืนโดย {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "การตรวจสอบรหัสที่บันทึกไว้" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA4.1.0·7 ตุลาคม 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10723,7 +10731,7 @@ msgstr "" "พวกเขายังเปรียบเทียบการมีส่วนร่วมของแผนที่และการย้ายที่ทับซ้อนกัน" #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10737,7 +10745,7 @@ msgstr "" "ไบต์ร่างกายในสองช่วงข้ามช่วง 517 ไบต์;คำแนะนำที่เลือกข้างต้นอยู่ในช่วง" #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10752,7 +10760,7 @@ msgstr "" " REA การตรวจสอบของเป้าหมายเดิมเดียวกัน " "ตัวตนของเกมที่ให้มาถูกตรึงโดยที่ประจักษ์พื้นที่เก็บข้อมูลที่มีแหล่งที่มาที่เก่าแก่การถ่ายโอน" -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10762,12 +10770,12 @@ msgstr "" "รูปที่แสดงให้เห็นถึงการคำนวณมุม การควบคุมเต็มรูปแบบเกมระยะเวลาและ PC-98 " "รวจสอบรันไทม์แยกต่างหากในโครงการฟื้นฟู" -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "เต็ม TH04 การฟื้นฟู" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10779,7 +10787,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10791,7 +10799,7 @@ msgstr "{ph0}สำรวจ TH04 ที่เก็บข้อมูล{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10806,7 +10814,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10822,7 +10830,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10845,28 +10853,28 @@ msgstr "" "ตรวจสอบ TH04ของเดิม 16 บิตรหัสดอสด้วย REA. " "นของกระสุนมีระยะห่างและมุ่งเป้าไปที่ผู้เล่น" -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "ในหน้านี้" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 กรณีศึกษารูปแบบกระสุน" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "คัดลอก TH04 ตัวอย่างพรอมต์" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "TH04 คงที่และมุ่งแหวนกระสุน;เลื่อนในแนวนอนบนหน้าจอขนาดเล็ก" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10879,27 +10887,27 @@ msgstr "" "หมุนทุกทิศทางโดยจำนวนเดียวกัน;ไฮไลต์จุดกระสุนแรกที่มีต่อผู้เ " "ทั้งคู่มีระยะห่าง 16 หน่วยหรือ 22.5 องศา" -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "คัดลอก TH04 เทมเพลตการยิง" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "ตาม TH04 การคำนวณวงแหวน" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "คัดลอก TH04 ตัดตอนมาประกอบ" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "สำเนาที่อ่านได้มุ่งเป้าแหวน-การคำนวณ" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "กลับขึ้นด้านบน" @@ -11007,7 +11015,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "ความเร็วคงที่: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11016,7 +11024,7 @@ msgstr "" "ย้อนกฎการกู้คืน " "ทั้งหมดสี่ค่าตรงกับการตรวจสอบเดิมควบคุมเกมเมื่อปัดเศษถึงสามทศนิยม" -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11375,591 +11383,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "ระยะห่างเดียวกัน:256÷16=16 หน่วยมุม=22.5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "ตัวอย่าง" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "บล็อก" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "เริ่มต้น" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "คู่มือ" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "ซอร์สโค้ด" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "สัญญาอนุญาต MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "เข้าร่วมชุมชน" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "ติดตามบน X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA *เลือกแหล่งสคริปต์" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "ซอร์สโค้ด" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "เอาต์พุตรูปแบบที่คาดหวัง" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "การแนะนำ" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "ฟังก์ชันที่เรียก" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "ค่าคงที่" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "ฟังก์ชัน C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "ปุ่ม" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "พรีโหลดเอพีไอ" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "ไอพีซี" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV แฟ้ม" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "คลิกของคุณ" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "คำขอจับ" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "ส่งออกสคริปต์" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REAผล·สรุปข้อความที่ตัดตอนมาจากไอพีซี" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA คำแนะนำ*0*406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA ข้อความที่ตัดตอนมา*0*411เอฟ5 บาท" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA ผลลัพธ์ไบต์*ตีความว่าเป็นคู่เล็กๆน้อยๆเอนเดียน" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "กู้คืนค*ตัดตอนมา" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "ดูว่า REA ทำงานอย่างไร ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "โชว์เคส→" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "การตั้งค่าที่เลือกจากสคริปต์ที่ตรวจสอบแล้ว" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "สรุปที่สามารถอ่านได้ของตัวจัดการ%" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA *เลือกคำแนะนำเดิม" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "รหัสผู้ประกอบการ·แหล่งที่มาของไมโครซอฟท์" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "ดูบทสนทนาซ่อนบทสนทนา" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "เจ้าหน้าที่→ REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA agent ตัวแทน·ผลลัพธ์ที่เลือกไว้" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA →ตัวแทน*วิธีการและฟังก์ชันที่เรียก" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA *เลือกแยกจาวา" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "สรุปสามารถอ่านได้*การตีความของตัวแทน" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA *เครื่องกำเนิดไฟฟ้า,ร่างกายที่สมบูรณ์" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "ดาวน์โหลด Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "ดาวน์โหลดผู้ให้บริการวิเคราะห์Android" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "เจ้าหน้าที่→ REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA agent ตัวแทน·ผลลัพธ์ที่เลือกไว้" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA →ตัวแทน·คำแนะนำที่เลือกไว้" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "เจ้าหน้าที่→ REA ·อ่าน_ไบต์" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA →ตัวแทน*รายการที่เจ็ด" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "ปฏิบัติการเดิม · SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "ดาวน์โหลดความท้าทายเดิม" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "ดาวน์โหลดแก้" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REAผล·รหัสปลอมที่ตัดตอนมา" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "เจ้าหน้าที่→ REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA →ตัวแทน*ตัดตอนการเรียนการสอน" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA →ตัวแทน*ข้อความที่ตัดตอนมาโทร" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "เจ้าหน้าที่→ REA *สอง {ph0} คำขอ" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REAผลไบต์*ถอดรหัสเป็นคู่" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "เริ่มจากเป้าหมายของคุณเอง" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "การสร้างรหัส" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "กู้คืนกฎ" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "นาฬิกาปรับได้" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "ไบนารี" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "ตรวจสอบรหัส" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "สมการ" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "ถูกต้อง!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "ปฏิบัติการ" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA ผลลัพธ์" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "กู้คืนค" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "การตรวจสอบความถูกต้อง" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "แอพแพคเกจ" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "งคุณเอง" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "ห่อไอพีซี" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "คลิปบอร์ด" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "รหัสดอสต้นฉบับ" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA การแนะนำ" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "การคำนวณมุม" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "แหวนกระสุน" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "หน้าเว็บ" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "ทำให้เรียกฟังก์ชันไอพีซี" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "ส่งไปยังคลิปบอร์ดระบบ" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "บันทึกไว้ในประเทศโดย Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "อินพุตมาร์กดาวน์" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "การวิเคราะห์โครงสร้างผลลัพธ์*ข้อความที่ตัดตอนมา" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "วิเคราะห์แอปของคุณเอง" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "เจ้าหน้าที่→ REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA agent ตัวแทน·ช่องที่เลือกไว้" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "เจ้าหน้าที่→ REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA →ตัวแทน*ตัดตอนการเรียนการสอน" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "ผลฟังก์ชั่นเดียวกัน*ตัดตอนมาจุดมุ่งหมาย" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "การบำรุงรักษาที่สอดคล้องกันค++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "แมโครแหวน · TH04 สาขาที่ตัดตอนมา" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "มุมและความเร็ว*ข้อความที่ตัดตอนมา" @@ -11992,7 +12008,7 @@ msgstr "แปลมีการปรับปรุง อ่านหน้ #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12009,7 +12025,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12030,7 +12046,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12050,7 +12066,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12069,7 +12085,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12088,7 +12104,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12099,7 +12115,7 @@ msgstr "" "โคลนเว็บไซต์นี้สำหรับฉัน.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" @@ -12107,7 +12123,7 @@ msgstr "การฟื้นฟู · {ph0}" # Reviewed for readable instructions and accurate software terminology. #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12118,7 +12134,7 @@ msgstr "" "และตรวจสอบการเปลี่ยนแปลงที่เสนอ" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12127,7 +12143,7 @@ msgstr "ตัวอย่างที่ให้มา · {ph0} และ npm #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12145,7 +12161,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12161,7 +12177,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12180,7 +12196,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12191,7 +12207,7 @@ msgstr "" "{ph7} และเขียนไฟล์{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12206,7 +12222,7 @@ msgstr "{ph0} *สาย 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12219,7 +12235,7 @@ msgstr "" "แสดงการคาดการณ์และผลลัพธ์ที่เกิดขึ้นจริง{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12230,7 +12246,7 @@ msgstr "" "นี้จะตรวจสอบรูปแบบโดยตรงกับ {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12238,7 +12254,7 @@ msgstr "{ph0} · CSV ฟอร์แมตเตอร์" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12247,7 +12263,7 @@ msgstr "" "คุณจะต้อง {ph0} 22 (22.19+), 24 (24.11+) หรือ 26+ npm มาพร้อมกับ {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12255,7 +12271,7 @@ msgstr "ไม่มี {ph0} หรือไม่แน่ใจ?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12267,7 +12283,7 @@ msgstr "" "ถ้าพิมพ์รุ่นเก่าหรือ\"ไม่รู้\"/\"ไม่พบคำสั่ง\",ติดตั้ง {ph1} 24 ลิตร:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12281,7 +12297,7 @@ msgstr "{ph0} ·ตัวอย่างแหล่งที่มาที่ #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12292,9 +12308,9 @@ msgstr "" "{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12302,7 +12318,7 @@ msgstr "{ph0} ·ตัวอย่างแหล่งที่มา" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12316,7 +12332,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12329,7 +12345,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12342,7 +12358,7 @@ msgstr "ตัวอย่าง: {ph0}ทำไมเครื่องคิ #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12353,7 +12369,7 @@ msgstr "" "220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12362,7 +12378,7 @@ msgstr "REA *โหลด {ph0} *สายที่เลือก" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12380,7 +12396,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12399,7 +12415,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12412,28 +12428,28 @@ msgstr "" "แล้วสร้างเดโมเล็ก ๆ ที่ฉันปรับเวลาได้{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "แท็บ_เบราเซอร์_มุมมอง/{ph0} ·สมาชิกเอพีไอ" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "แท็บ_เบราเซอร์_มุมมอง/{ph0} ·ผู้ช่วยไอพีซี" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "หลัก/{ph0} *ผู้ช่วยผู้จัดการ" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12443,12 +12459,1390 @@ msgstr "หลัก/{ph0} *รับคลิปบอร์ด" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "เริ่มต้น {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "เปลี่ยนเป็นโหมดสว่าง" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "เปลี่ยนเป็นโหมดมืด" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"หากต้องการตรวจสอบเนื้อหาคำขอและคำตอบ HTTP ให้ใช้ {ph0}Fiddler Everywhere: " +"ข้อมูลที่บันทึกในรูปแบบ SAZ, MCP และทักษะสาธารณะ{ph1} ส่งออกเป็น SAZ ???? " +"HAR 1.2 เพื่อรับ Evidence จากข้อมูลที่บันทึกใน REA แบบออฟไลน์ " +"หรือเชื่อมต่อเซิร์ฟเวอร์ MCP ของ Everywhere " +"เพื่อตรวจสอบทราฟฟิกที่บันทึกไว้ร่วมกับเอเจนต์ของคุณ" + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "โมเดลเฉพาะทาง{ph0}บทความ" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "การวิศวกรรมย้อนกลับจำเป็นต้องใช้โมเดลที่ใหญ่ขึ้นไหม?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"ข้อคิดจากการสร้าง Touhou ขึ้นใหม่ เกี่ยวกับโมเดลทั่วไป โมเดลเฉพาะทาง " +"และการเรียนรู้จากผลตอบกลับของคอมไพเลอร์" + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "โดย N0zoM1z0 · 13 ตุลาคม 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "ข้ามไปที่เนื้อหา" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Home{ph1} / {ph2}Blog{ph3} / โมเดลและวิศวกรรมย้อนกลับ" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "เรียงความ" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "วิศวกรรมย้อนกลับจำเป็นต้องมีโมเดลที่ใหญ่กว่านี้หรือไม่?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "โดย N0zoM1z0 · 13 ตุลาคม 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "ประเด็นสำคัญ" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}ความสามารถของโมเดลส่งผลต่อสมมติฐานที่เอเจนต์ AI สามารถเสนอได้{ph1} " +"เซสชันต่อมาได้แก้ไขปัญหาที่งานก่อนหน้านี้ยังไม่ได้รับการแก้ไข" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}คอมไพเลอร์ที่คุ้นเคยนำเสนอรูปแบบที่เป็นรูปธรรมสำหรับโมเดลเฉพาะทางในการเรียนรู้{ph1}" +" " +"การจับคู่โค้ดเครื่องที่แน่นอนบางรายการขึ้นอยู่กับรูปแบบซอร์สโค้ดเฉพาะที่สามารถนำมาใช้ซ้ำได้" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}รวมความรู้ของพื้นที่เก็บข้อมูลไว้ในการเปรียบเทียบที่ยุติธรรม{ph1} " +"โมเดลขนาดเล็กที่มีการดึงความรู้ที่ดีอาจมีข้อมูลเพียงพอที่จะดำเนินการต่อไป" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}ฝึกแบบจำลองเพื่อเลือกการทดลองที่มีประโยชน์ถัดไป " +"และทดสอบเครื่องมือตรวจสอบการยืนยัน{ph1} " +"ความคิดเห็นจะมีประโยชน์เฉพาะในขอบเขตที่ผู้ตรวจสอบตรวจสอบสิ่งที่ถูกต้องเท่านั้น" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}ประเมินผลการฟื้นฟูที่ได้รับการยืนยันควบคู่ไปกับเวลาและต้นทุน{ph1} " +"นั่นคือสิ่งที่ฉันต้องการวัดสำหรับเวิร์กโฟลว์เอเจนต์ AI ที่สมบูรณ์" + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "ในบทความนี้" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}โมเดลที่เก่งขึ้นเปลี่ยนอะไรบ้าง?{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}ทำไมจึงมีความเชี่ยวชาญ?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}ประสบการณ์นี้ควรเก็บไว้ที่ไหน?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}เรียนรู้การทดลองที่มีประโยชน์ครั้งต่อไป{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}วิศวกรรมย้อนกลับและการเสริมกำลัง{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}เมื่อตัวตรวจสอบความถูกต้องผิดพลาด{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}การเปรียบเทียบที่คุ้มค่า{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}สิ่งนี้แนะนำเอเจนต์ AI ประเภทใด{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "โมเดลที่เก่งขึ้นเปลี่ยนอะไรบ้าง?" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"ตั้งแต่เดือนสิงหาคม 2026 " +"ฉันได้สำรวจว่าตัวแทนสามารถดำเนินการวิศวกรรมย้อนกลับได้มากเพียงใดโดยมีสิทธิ์เข้าถึงโปรแกรมและวิธีการตรวจสอบงาน" +" ประสบการณ์ส่วนใหญ่ของฉันมาจากการสร้างเกมขึ้นใหม่ โดยเฉพาะ Touhou " +"ขณะที่ฉันเปลี่ยนโมเดล " +"พื้นที่เก็บข้อมูลได้เก็บบันทึกว่าแต่ละเซสชันจัดการเพื่อกู้คืนอะไรบ้าง" + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"งานส่วนใหญ่มีเป้าหมายให้ซอร์สโค้ดที่สร้างขึ้นคอมไพล์แล้วตรงกับต้นฉบับ " +"เราใช้ชุดเครื่องมือจากยุคนั้นโดยกำหนดเวอร์ชันไว้แน่นอน " +"แล้วตรวจว่าผลลัพธ์ตรงกับฟังก์ชันเป้าหมายหรือไม่ " +"เมื่อโมเดลรุ่นใหม่แก้จุดที่งานก่อนหน้าติดอยู่ได้ " +"การเปลี่ยนแปลงซอร์สโค้ดช่วยให้เห็นว่าอะไรทำให้ก้าวหน้าได้" + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "ตัวแปรชั่วคราวจำเป็นต้องมีอายุการใช้งานที่ทับซ้อนกัน" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"ลอจิกของฟังก์ชันการโจมตี TH09 ส่วนใหญ่ได้ถูกสร้างขึ้นใหม่แล้ว " +"แต่คอมไพเลอร์ยังคงเก็บผลลัพธ์ชั่วคราวแตกต่างไปจากต้นฉบับ " +"ปัญหาที่เหลืออยู่คือผลลัพธ์เหล่านั้นต้องใช้เวลานานเท่าใดจึงจะคงอยู่ได้ " +"และเมื่อใดจึงจะสามารถนำพื้นที่จัดเก็บกลับมาใช้ใหม่ได้" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"บันทึกเซสชัน {ph0}GPT-6-Sol{ph1} " +"รายงานความไม่ตรงกันนี้หลังจากทดสอบการจัดเตรียมซอร์สโค้ดทั่วไปหลายรายการ " +"เมื่อ {ph2}GPT-6.1-Sol ตรวจสอบปัญหาอีกครั้ง{ph3} " +"ก็เสนอสมมติฐานที่เป็นประโยชน์เกี่ยวกับช่วงอายุของตัวแปรชั่วคราวเหล่านี้" + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"ฟังก์ชันนี้สร้างผลลัพธ์ชั่วคราวและคัดลอกไปยังตำแหน่งแอนิเมชัน ในภาษา C++ " +"ผลลัพธ์ชั่วคราวจะคงอยู่จนกว่านิพจน์ที่ใช้จะเสร็จสิ้น " +"การจัดกลุ่มการดำเนินการจริงให้เป็นนิพจน์เดียวทำให้ผลลัพธ์เหล่านั้นคงอยู่ร่วมกัน" +" " +"ดังนั้นคอมไพลเลอร์จึงไม่สามารถใช้พื้นที่เก็บข้อมูลเดียวกันซ้ำได้อีกต่อไปสำหรับการดำเนินการทั้งหมด" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"ผลลัพธ์หนึ่งรายการยังคงแชร์พื้นที่เก็บข้อมูลด้วยค่าที่ใช้ในภายหลังสำหรับการตรวจสอบการชนกัน" +" การให้คุณค่านั้นตลอดอายุการใช้งานจะช่วยแก้ไขการทับซ้อนที่เหลือ " +"หลังจากการทดลองที่กำหนดเป้าหมายหลายครั้ง " +"{ph0}การคอมไพล์ใหม่ทั้งหมดจากแหล่งที่มายืนยันว่าฟังก์ชันทั้งหมดตรงกัน{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"ฉันสนใจว่าการค้นพบและการทดสอบสนับสนุนซึ่งกันและกันอย่างไร " +"สมมติฐานเกี่ยวกับอายุการใช้งานของวัตถุชั่วคราวทำให้เอเจนต์ AI มีทิศทางใหม่ " +"คำติชมของคอมไพเลอร์ช่วยปรับแต่งสมมติฐานนั้นให้กลายเป็นการจัดเรียงซอร์สโค้ดที่ตรงกัน" + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "กราฟโฟลว์ควบคุมที่แตกต่างกัน" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"ฟังก์ชัน TH09 ตัวที่สองแสดงให้เห็นว่าเหตุใดทิศทางใหม่จึงมีความสำคัญ " +"อุปสรรคอยู่ที่ว่าหลายสาขาจะแบ่งปันผลงานชิ้นสุดท้ายของพวกเขาอย่างไร " +"งานก่อนหน้าของ {ph0}GPT-6.1-Sol{ph1} มีฟังก์ชันบางส่วนที่เข้ากัน " +"แต่กิ่งก้านยังคงเชื่อมกันแตกต่างไปจากต้นฉบับ" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra เปลี่ยนกราฟโฟลว์ควบคุมโดยรอบ{ph1} " +"เส้นทางหลักตอนนี้นำไปสู่การอัปเดตและการกลับมาครั้งสุดท้ายที่ใช้ร่วมกัน " +"ในโครงสร้างต้นทางนั้น คอมไพลเลอร์จะรวมสาขาต่างๆ ในลักษณะเดียวกับต้นฉบับ " +"ฟังก์ชันที่สมบูรณ์ตรงกัน และ " +"{ph2}การตรวจสอบการสร้างใหม่แยกกันยืนยันแล้ว{ph3}" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}การเปลี่ยนการแสดงทำให้พื้นที่การค้นหามีประสิทธิผลมากขึ้น{ph1} " +"ทั้งสองกรณีให้เหตุผลแก่ฉันในการให้ความสำคัญกับความสามารถของโมเดลทั่วไปอย่างจริงจัง:" +" " +"ตัวแทนสามารถลองใช้รูปแบบท้องถิ่นต่อไปเป็นเวลานานก่อนที่จะพบวิธีที่ดีกว่าในการแสดงงานโดยรอบ" + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"ในเวลาเดียวกัน " +"เซสชันต่อมาเริ่มต้นด้วยแหล่งที่มาก่อนหน้าและความล้มเหลวที่บันทึกไว้ " +"งานที่สะสมไว้นั้นเป็นส่วนหนึ่งของความได้เปรียบของพวกเขา " +"ประวัติศาสตร์ช่วยให้เราตรวจสอบการค้นพบและการตรวจสอบของพวกเขา " +"การเปรียบเทียบแบบควบคุมจะช่วยแยกผลกระทบของแบบจำลองออกจากประสบการณ์ที่สืบทอดมา" + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"นี่คือสิ่งที่ทำให้คำถามน่าสนใจสำหรับฉัน " +"ความคืบหน้าบางอย่างมาจากการค้นหาตัวแทนใหม่ " +"งานที่เหลือส่วนใหญ่เกี่ยวข้องกับการทดสอบการจัดเตรียมซอร์สโค้ดที่แตกต่างกันกับคอมไพเลอร์ที่คุ้นเคย" +" สิ่งนี้ต้องใช้ความสามารถในการให้เหตุผลแบบกว้างๆ มากน้อยเพียงใด? " +"โมเดลสามารถเรียนรู้ได้มากเพียงใดจากการทำงานซ้ำๆ กับคอมไพเลอร์และโค้ดนั้น" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "เหตุใดโมเดล AI เฉพาะทางจึงทำได้ดี" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou ให้เหตุผลที่ชัดเจนแก่เราในการคาดหวังว่าประสบการณ์นั้นจะช่วยได้ " +"รหัสเกมส่วนใหญ่มาจากผู้เขียนคนเดียวกัน ZUN ดังนั้นนิสัยที่เกิดขึ้นซ้ำๆ " +"จึงเป็นสมมติฐานเริ่มต้นที่สมเหตุสมผล " +"แหล่งเก็บข้อมูลสนับสนุนด้วยตัวอย่างที่เป็นประโยชน์: " +"ลูปที่เกี่ยวข้องและการจัดเตรียมตัวช่วยได้ให้สมมติฐานแก่เกมต่างๆ" + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"รูปแบบแหล่งที่มาเหล่านั้นมีความเฉพาะเจาะจงมากขึ้นเมื่อเรารวมคอมไพเลอร์ " +"ภายใต้เวอร์ชันและชุดตัวเลือกเฉพาะ การเปลี่ยนแปลงเล็กๆ น้อยๆ " +"ในแหล่งที่มาอาจทำให้เกิดความแตกต่างที่ทำซ้ำได้ในรหัสเครื่อง " +"ความแตกต่างบางประการนั้นคลุมเครืออย่างน่าประหลาดใจ" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"ตัวอย่างเช่น ใน TH095 {ph0}แม้แต่ชื่อของตัวแปรโลคัลก็อาจส่งผลต่อตำแหน่งที่ " +"VC7.1 เก็บไว้{ph1} การย้ายการประกาศไม่ได้ช่วยแก้ปัญหารูปแบบการจัดเก็บข้อมูล " +"อย่างไรก็ตาม " +"ฟังก์ชันพื้นหลังก่อนหน้านี้ได้เปิดเผยรูปแบบการตั้งชื่อที่ส่งผลต่อการเลือกของคอมไพเลอร์" +" นั่นเสนอสมมติฐานที่มีแนวโน้มมากขึ้นสำหรับ {ph2}การสร้าง {ph3}{ph4} ใหม่" + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"การใช้รูปแบบนั้นซ้ำสำหรับตัวแปรขนาดไฟล์ทำให้เกิดเค้าโครงที่ต้องการโดยไม่ต้องเพิ่มพื้นที่เก็บข้อมูล" +" ฟังก์ชั่นครบถ้วนจึงเข้าคู่กัน" + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"นี่เป็นรายละเอียดเฉพาะเจาะจงมากที่โมเดล AI " +"เอนกประสงค์อาจไม่ทราบเมื่อพบปัญหาครั้งแรก " +"โมเดลเฉพาะสำหรับคอมไพลเลอร์นี้สามารถเห็นกรณีดังกล่าวได้มากมาย " +"และเรียนรู้ว่าซอร์สโค้ดรูปแบบใดที่ควรค่าแก่การทดสอบก่อน" + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"โอกาสมีความชัดเจนโดยเฉพาะอย่างยิ่งในปัญหาการจับคู่ขั้นสุดท้ายที่เราเข้าใจพฤติกรรมอยู่แล้ว" +" " +"จากนั้นเราจะถามว่าการจัดเรียงซอร์สโค้ดธรรมดาใดที่คอมไพเลอร์นี้เปลี่ยนเป็นคำสั่งที่สังเกตได้" +" " +"ความเชี่ยวชาญพิเศษสามารถช่วยแบบจำลองเสนอรูปแบบเหล่านั้นได้อย่างมีประสิทธิภาพมากขึ้น" +" ในขณะที่เป้าหมายยังคงกำหนดว่าสมมติฐานใดที่จะอยู่รอดได้" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"รูปแบบที่ใช้ได้ต้องมีบริบทกำกับ TH08 ใช้ Visual C++ รุ่นเก่ากว่า TH095 และ " +"TH09 ส่วน TH04 ใช้คอมไพเลอร์อีกตัวหนึ่งจากยุค DOS " +"{ph0}การสร้างโค้ดผู้เล่นขึ้นใหม่{ph1} จึงต้องใช้สมมติฐานต่างออกไป " +"ทั้งเรื่องรูปแบบซอร์สโค้ดและการลิงก์เป็นไฟล์ปฏิบัติการ " +"ผู้เขียนคนเดียวกันให้ข้อสันนิษฐานเริ่มต้น " +"แต่ต้องตรวจในแต่ละเป้าหมายว่าใช้ได้หรือไม่ " +"โมเดลเฉพาะทางต้องเรียนรู้ความแตกต่างเหล่านี้" + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "ประสบการณ์นี้ควรเก็บไว้ที่ไหน?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"ก่อนที่จะตัดสินใจสอนรูปแบบเหล่านั้นผ่านการฝึกโมเดล " +"ฉันจะดูความรู้ที่เราเก็บไว้ในที่เก็บอยู่แล้ว ใน {ph0}เรียงความก่อนหน้า{ph1} " +"ฉันเขียนเกี่ยวกับการที่กลายเป็นความทรงจำในการทำงานของโครงการ " +"หน่วยความจำดังกล่าวประกอบด้วยบทเรียนเกี่ยวกับคอมไพเลอร์ " +"พร้อมด้วยแหล่งที่มาและการทดลองที่ล้มเหลวซึ่งทำให้มีประโยชน์" + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"ด้วยการเรียกบันทึกนั้น " +"ตัวแทนสามารถเริ่มต้นด้วยผลลัพธ์ที่ทราบและตรวจสอบว่าเราเข้าถึงได้อย่างไร " +"นอกจากนี้ยังสามารถหลีกเลี่ยงทางเลือกอื่นที่ล้มเหลวในบริบทเดียวกันได้ " +"จุดเริ่มต้นจะดีขึ้นโดยไม่ต้องเปลี่ยนพารามิเตอร์ที่ได้รับการฝึกของโมเดล" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"ในขณะที่สร้างฟังก์ชันของ TH09 ขึ้นมาใหม่เพื่อสร้างศัตรู เซสชัน " +"{ph0}GPT-6-Luna-max{ph1} ได้ตั้งสมมุติฐานจากซอร์สโค้ด TH08 ที่เกี่ยวข้อง " +"โค้ดก่อนหน้านี้แนะนำวิธีจัดระเบียบลูปและจัดการกับความล้มเหลวภายใน หลักฐานของ" +" TH09 ให้รายละเอียดเฉพาะเกม " +"การสร้างใหม่จากแหล่งที่มายืนยันว่าฟังก์ชันทั้งหมดตรงกัน" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"โมเดลไม่ทราบว่านิสัยแปลกๆ ของคอมไพเลอร์\" และ " +"\"โมเดลไม่สามารถใช้งานได้\" เป็นปัญหาที่แตกต่างกัน {ph1} " +"การดึงข้อมูลอาจแก้ปัญหาได้ในวิธีแรก " +"แต่การเปลี่ยนข้อเท็จจริงดังกล่าวให้กลายเป็นตัวเลือกที่มีประโยชน์ยังคงต้องใช้เวลา" +" และหากซอร์สโค้ดของผู้สมัครล้มเหลว " +"โมเดลจะต้องตัดสินใจว่าผลลัพธ์มีความหมายอย่างไรสำหรับความพยายามครั้งถัดไป " +"การรู้รูปแบบที่เกี่ยวข้องเป็นเพียงจุดเริ่มต้นของกระบวนการนั้นเท่านั้น" + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"ด้วยเหตุผลดังกล่าว ฉันจึงรวมโมเดล AI " +"อเนกประสงค์ที่มีขนาดเล็กกว่าพร้อมการดึงข้อมูลที่ดีไว้ด้วยในการเปรียบเทียบ " +"การให้คลังประสบการณ์แบบเดียวกันจะช่วยให้เราระบุได้ว่าการฝึกอบรมใดที่เพิ่มเข้ามา" +" เช่น การสร้างผู้สมัครที่ดีขึ้น การตัดสินใจที่ดีขึ้นหลังจากได้รับคำติชม " +"หรือทั้งสองอย่าง" + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "เรียนรู้การทดลองที่มีประโยชน์ครั้งต่อไป" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"การตัดสินใจเหล่านั้นหลังจากได้รับคำติชมคือสิ่งที่ฉันอยากศึกษามากที่สุด " +"ในการฟื้นฟูแบบเอเจนต์ แบบจำลองจะเสนอคำอธิบายและทดสอบกับโปรแกรม " +"แม้ว่าซอร์สโค้ดของผู้สมัครจะล้มเหลว " +"ผลลัพธ์ก็สามารถจำกัดความเป็นไปได้ที่เหลืออยู่ให้แคบลง " +"และแนะนำการทดลองถัดไปที่มีประโยชน์มากขึ้น" + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"ลองพิจารณาตัวอย่างผลลัพธ์ชั่วคราวอีกครั้ง " +"แหล่งที่มาสุดท้ายแสดงการจัดเตรียมที่ได้ผล " +"แต่เส้นทางไปยังแหล่งข้อมูลนั้นมีข้อมูลเพิ่มเติม " +"การทดลองแต่ละรายการต่อไปนี้ช่วยระบุสิ่งที่ยังจำเป็นต้องเปลี่ยนแปลง" + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "การทดลอง" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "ผลลัพธ์ของมันสอนอะไรเรา" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "ลองวิธีอื่นในการคัดลอกผลลัพธ์" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "รหัสการคัดลอกเปลี่ยนไป แต่ฟังก์ชันยังคงแตกต่างออกไป" + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "ใช้ค่าที่ส่งคืนโดยตรง" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"การคัดลอกเป็นไปตามรูปแบบดั้งเดิม แต่การจัดเก็บชั่วคราวยังคงแตกต่างออกไป" + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "เก็บตัวแปรชั่วคราวทั้งหมดให้ถูกต้องในเวลาเดียวกัน" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"พวกเขาได้รับพื้นที่เก็บข้อมูลแยกต่างหาก " +"แต่ยังมีอีกหนึ่งค่าที่ทับซ้อนกันกับค่าที่ใช้ในภายหลังสำหรับการตรวจสอบการชนกัน" + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "แยกค่าการตรวจสอบการชนกันออกจากกัน" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "การคอมไพล์ใหม่ทั้งหมดจากแหล่งที่มายืนยันการจับคู่ที่สมบูรณ์" + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"การทดลองที่เลือกจากการสร้างฟังก์ชันการโจมตีขึ้นใหม่ด้านบน " +"โดยจัดกลุ่มตามสิ่งที่พวกเขาสอนเรา" + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"บันทึกการฝึกอบรมที่เก็บลำดับนี้สามารถสอนได้มากกว่าแหล่งข้อมูลสุดท้ายเพียงอย่างเดียว" +" " +"โดยเชื่อมโยงการเปลี่ยนแปลงที่เสนอแต่ละรายการกับผลลัพธ์ที่สังเกตได้และการตัดสินใจครั้งต่อไป" +" การรักษารูปแบบที่ไม่มีประสิทธิภาพก็มีความสำคัญเช่นกัน " +"โดยจะแจ้งตัวแทนในภายหลังว่าสมมติฐานใดได้รับการทดสอบแล้วในบริบทนั้น" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}ฉันอยากให้โมเดลเรียนรู้วิธีใช้คำติชม{ph1} " +"ผลลัพธ์ที่เป็นกลางคือเหตุผลที่ต้องพิจารณารูปแบบใหม่อีกครั้ง " +"ความไม่ตรงกันที่เปลี่ยนแปลงอาจชี้ไปที่สาเหตุอื่น " +"เมื่อการแก้ไขเฉพาะที่หยุดให้ข้อมูล " +"ตัวแทนควรสามารถทบทวนการนำเสนอแหล่งที่มาหรือตรวจสอบหลักฐานอีกครั้ง" + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"การเรียนรู้ที่จะเลือกขั้นตอนเหล่านี้ต้องมีอิสระในการทำงาน " +"บางครั้งขั้นตอนที่มีประโยชน์คือการตรวจฟังก์ชันอื่นที่เรียกฟังก์ชันนี้ " +"แทนที่จะแก้โค้ดแล้วคอมไพล์อีกครั้ง " +"ลำดับการเขียนโค้ดใหม่ที่บังคับตายตัวจะตัดทางเลือกนี้ออก " +"รวมถึงพฤติกรรมบางส่วนที่เราอยากให้โมเดลเรียนรู้" + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "เหตุใดวิศวกรรมย้อนกลับจึงน่าสนใจสำหรับการเรียนรู้แบบเสริมกำลัง" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"การสร้างโค้ดขึ้นใหม่ในขอบเขตที่ชัดเจนเป็นสภาพแวดล้อมที่ใช้ศึกษาการเลือกเหล่านี้ได้จริง" +" เมื่อกำหนดเป้าหมายและเวอร์ชันคอมไพเลอร์ไว้แน่นอน " +"การทดลองซอร์สโค้ดหลายแบบจะให้ผลตอบกลับรวดเร็วและทำซ้ำได้ " +"เอเจนต์สามารถคอมไพล์โค้ดที่เสนอ ตรวจส่วนที่ยังต่าง แล้วเลือกขั้นตอนถัดไป" + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"การเรียนรู้แบบเสริมกำลังสามารถฝึกกระบวนการตัดสินใจผ่านคำติชมที่ได้รับ " +"ผู้สมัครที่ยอมรับโดยเช็คที่กำหนดจะให้ผลลัพธ์ที่เป็นรูปธรรมแก่เรา " +"ในขณะที่ลำดับของความพยายามช่วยให้เราสังเกตได้ว่าต้องใช้ความพยายามมากเพียงใดจึงจะบรรลุผลนั้น" + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"มีงานวิจัยสนับสนุนแนวทางนี้แล้ว {ph0}LLM4Decompile{ph1} " +"ศึกษาโมเดลที่เชี่ยวชาญการดีคอมไพล์ ส่วน {ph2}AutoDecompiler{ph3} " +"ฝึกการปรับปรุงหลายรอบโดยใช้ผลจากคอมไพเลอร์และการรันโปรแกรม " +"งานเหล่านี้เน้นการกู้คืนพฤติกรรมของโปรแกรม " +"ผมจะใช้เป็นจุดเริ่มต้นสำหรับงานที่เกี่ยวข้อง " +"คือการหาซอร์สโค้ดที่ให้ผลลัพธ์ตรงกับคอมไพเลอร์จากยุคเดิม" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"เพื่อให้บรรลุภารกิจที่กำหนดไว้อย่างชัดเจน " +"เราอาจจำเป็นต้องกำหนดทรัพยากรที่ฟังก์ชันเป็นเจ้าของก่อนหรือออกแบบวิธีใหม่เพื่อสังเกตพฤติกรรมของโปรแกรมขณะทำงาน" +" ตัวอย่างเช่น ใน TH08 ความแตกต่าง {ph0}การชนกัน " +"ทำให้ย้อนกลับไปถึงวิธีที่โปรแกรมดั้งเดิมจัดการการคำนวณจุดลอยตัว{ph1} " +"ก่อนที่ตัวแทนจะทดสอบการแก้ไขที่เป็นประโยชน์ได้ ก็ต้องพิจารณาว่าจะวัดอะไรก่อน" + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"สิ่งนี้ชี้ให้เห็นอีกบทบาทหนึ่งของแบบจำลองที่มีความสามารถในวงกว้าง: " +"ช่วยให้สามารถตรวจสอบปัญหาได้ตั้งแต่แรก เมื่อมีการตรวจสอบแล้ว " +"เราจะสามารถตรวจสอบได้ว่านโยบายการค้นหาที่เรียนรู้จะสามารถนำมาใช้ได้ไกลเพียงใด" + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "เมื่อตัวตรวจสอบความถูกต้องผิดพลาด" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"เมื่อใช้ผลตรวจสำหรับการฝึก " +"ขอบเขตของการตรวจก็กลายเป็นส่วนหนึ่งของสภาพแวดล้อมการเรียนรู้ " +"ผมเรียกข้อมูลอ้างอิงหรือเครื่องมือตรวจนี้ว่า oracle แม้คำตอบจะทำซ้ำได้ " +"เราก็ต้องเข้าใจว่ามันตรวจสอบอะไรจริง ๆ" + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 แสดงให้เห็นว่าปัญหาอาจซ่อนอยู่นอกขอบเขตการตรวจ " +"บางฟังก์ชันใช้ค่าคงที่แบบ floating-point ที่ผิด " +"แต่ยังผ่านการเปรียบเทียบแบบตรงกันทุกส่วน " +"ตัวเปรียบเทียบปรับแอดเดรสที่ถูกย้ายก่อนตรวจคำสั่ง " +"แต่ตรวจค่าที่แอดเดรสนั้นชี้ไปเฉพาะกรณีที่บันทึกไว้ให้ตรวจอย่างชัดเจน " +"การอ้างอิงค่าคงที่อื่นจึงอาจผ่านโดยไม่ได้ตรวจค่า" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"เพื่อแก้ไขช่องว่างนี้ {ph0}การตรวจสอบที่กว้างขึ้น{ph1} " +"พบค่าคงที่ที่ไม่ถูกต้องในฟังก์ชันที่ผ่านการตรวจสอบแล้ว ในการคำนวณครั้งหนึ่ง " +"ซอร์สโค้ดที่สร้างขึ้นใหม่ได้เพิ่ม {ph2} ในขณะที่ซอร์สโค้ดดั้งเดิมเพิ่ม {ph3}" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}โมเดลที่ได้รับรางวัลจากการตรวจสอบยืนยันแบบเก่าสามารถเรียนรู้ที่จะสร้างการสร้างใหม่ที่ไม่ถูกต้อง{ph1}" +" เราไม่ได้ฝึกโมเดล RL โดยใช้ตัวตรวจสอบนั้น " +"ความล้มเหลวที่เราสังเกตเห็นคือในการตรวจสอบนั่นเอง แต่ถ้าเราใช้เป็นรางวัล " +"จุดบอดเดียวกันก็จะกลายเป็นส่วนหนึ่งของสภาพแวดล้อมการเรียนรู้" + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"การทดสอบการทำงานอาจมีจุดบอดที่คล้ายกัน " +"{ph0}การวิจัยโดยใช้การแยกฟัซซีแบบดิฟเฟอเรนเชียลกับตัวถอดรหัส LLM{ph1} " +"พบความแตกต่างด้านพฤติกรรมนอกเหนือจากการทดสอบที่ให้มา " +"ดังนั้นเราจึงจำเป็นต้องเข้าใจการทดสอบที่ผ่านในแง่ของกรณีที่ผ่านการทดสอบ " +"ในทำนองเดียวกัน การจับคู่คำสั่งจะต้องเข้าใจในแง่ของไบต์และข้อมูลที่ตรวจสอบ" + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"ก่อนที่จะใช้การตรวจสอบยืนยันประเภทใดประเภทหนึ่งเป็นรางวัล " +"ฉันจะทดสอบด้วยผลลัพธ์ที่ไม่ถูกต้องโดยเจตนา " +"ฉันยังจะแยกการยอมรับขั้นสุดท้ายออกจากซอร์สโค้ดที่เอเจนต์ AI สามารถแก้ไขได้ " +"โมเดลจะต้องผ่านการตรวจสอบโดยการสร้างโปรแกรมใหม่อย่างถูกต้อง มิฉะนั้น " +"การคัดลอกอาร์เรย์ไบต์จากเป้าหมายอาจหลอกระบบการให้คะแนนที่ไร้เดียงสาโดยไม่ต้องกู้คืนซอร์สโค้ดที่มีประโยชน์" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}การปรับปรุงโมเดลและการปรับปรุงเครื่องมือตรวจเป็นส่วนของปัญหาวิจัยเดียวกัน{ph1}" +" ยิ่งโมเดลเก่งในการปรับตัวตามผลตอบกลับที่เราให้ " +"ก็ยิ่งสำคัญที่เราต้องเข้าใจผลตอบกลับนั้น" + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "การเปรียบเทียบที่คุ้มค่า" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"เมื่อตรวจสอบแล้ว ฉันจะเริ่มการเปรียบเทียบในกลุ่มงาน VC7.1 ที่คงที่ ก่อนอื่น " +"ฉันจะสร้างพื้นฐานสำหรับโมเดล AI อเนกประสงค์ที่แข็งแกร่งและโมเดลที่เล็กกว่า " +"การเพิ่มความรู้เกี่ยวกับพื้นที่เก็บข้อมูลให้กับโมเดลขนาดเล็กจะแสดงให้เห็นว่าการเปลี่ยนแปลงในการดึงข้อมูลมีอะไรบ้าง" +" จากนั้น ความเชี่ยวชาญพิเศษภายใต้การดูแลและเวอร์ชันที่ได้รับการฝึกอบรม RL " +"จะให้เราตรวจสอบได้ว่าการฝึกอบรมใดบ้างที่เพิ่มเข้ามา" + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"เพื่อให้การเปรียบเทียบเหล่านี้เป็นข้อมูล " +"แต่ละแบบจำลองจะได้รับหลักฐานและเครื่องมือเป้าหมายที่เหมือนกัน " +"สำหรับการเปรียบเทียบเฉพาะการฝึกอบรม " +"ฉันจะเก็บโมเดลพื้นฐานและความรู้ที่มีอยู่ไว้คงที่เช่นกัน การทดลองซ้ำๆ " +"จะช่วยแยกแยะกลยุทธ์การค้นหาที่เชื่อถือได้จากโซลูชันผู้สมัครที่ประสบความสำเร็จโดยบังเอิญ" + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"จากนั้นฉันจะแยกเงื่อนไขเริ่มต้นสองเงื่อนไข: สร้างฟังก์ชันใหม่จากคำแนะนำ " +"และปิดความแตกต่างสองสามข้อสุดท้ายในแหล่งที่มาที่ได้รับการบำรุงรักษา โมเดล AI" +" เฉพาะทางอาจทำงานได้ดีในงานที่สอง ในขณะที่โมเดล AI " +"เอนกประสงค์ทำงานส่วนใหญ่ที่จำเป็นในการเข้าถึงโมเดลนั้น " +"การวัดแยกกันจะเผยให้เห็นการแบ่งส่วนงานนั้น" + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"ทั้งสองงานต้องมีตัวอย่างทดสอบที่ไม่อยู่ในข้อมูลฝึกและแหล่งข้อมูลสำหรับค้นคืน" +" เกม Touhou ที่เกี่ยวข้องใช้โค้ดเอนจินร่วมกัน " +"การกันเกมหนึ่งออกจากข้อมูลฝึกจึงอาจยังเหลือฟังก์ชันที่เกือบเหมือนกันในชุดฝึก" +" ผมจะกันซอร์สโค้ดที่เกี่ยวข้องทั้งกลุ่มออก " +"และไม่ให้คำตอบที่ผ่านการตรวจแล้วอยู่ในข้อมูลฝึกหรือคลังสำหรับค้นคืน" + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"ผลที่วัดควรเป็นการตรงกันครบทั้งฟังก์ชันซึ่งผ่านการตรวจอย่างอิสระ " +"ให้แต่ละโมเดลมีงบจำนวนโค้ดที่เสนอหรือจำนวนครั้งที่คอมไพล์เท่ากันเพื่อเปรียบเทียบคุณภาพการค้นหา" +" แล้ววัดเวลารวมและต้นทุนรวมซึ่งรวมการคอมไพล์ด้วย " +"เพื่อดูว่าคุณภาพนั้นทำให้งานมีประสิทธิภาพจริงหรือไม่ " +"ต้นทุนการฝึกต้องนับแยกต่างหาก" + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"การวัดทั้งสองมีความสำคัญ ข้อเสนอราคาถูกอาจนำไปสู่ขั้นตอนการทำงานที่มีราคาแพง" +" หากทำให้เกิดการคอมไพล์มากขึ้นซึ่งไม่ได้ให้ข้อมูลที่เป็นประโยชน์ " +"ในทางกลับกัน " +"โมเดลที่ช้ากว่าอาจประหยัดกว่าหากพบว่าการทดสอบมีประโยชน์เร็วกว่านี้ " +"การเปรียบเทียบควรรวมต้นทุนเหล่านี้ด้วย" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"การนับผลลัพธ์ที่ยอมรับยังช่วยรักษาความก้าวหน้าระดับกลางในมุมมองด้วย TH09 " +"{ph0}บันทึกการเล่นซ้ำ-บันทึกผู้สมัคร{ph1} " +"หนึ่งตัวดูมีแนวโน้มดีเนื่องจากฟังก์ชันที่คอมไพล์มีขนาดตามที่คาดหวัง " +"แต่การเปรียบเทียบแบบเต็มยังคงพบความแตกต่างอย่างมาก " +"การเปลี่ยนแปลงวิธีที่คอมไพลเลอร์จัดเรียงคำสั่งยังสามารถทำให้ผู้สมัครมองเข้าไปใกล้มากขึ้นโดยไม่ต้องแก้ไขปัญหาที่ซ่อนอยู่" +" การวินิจฉัยดังกล่าวสามารถเป็นแนวทางในการทดสอบครั้งต่อไปได้ " +"แต่ฉันจะตรวจสอบรางวัลสำหรับการ \"เข้าใกล้\" " +"เทียบกับการตรวจสอบการยอมรับทั้งหมด" + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"ฉันจะสนใจรูปแบบของผลลัพธ์เหล่านี้ หากโมเดล AI " +"เฉพาะทางทำงานได้ดีในตระกูลคอมไพเลอร์ที่คุ้นเคย " +"ข้อได้เปรียบนั้นจะรอดพ้นจากการเปลี่ยนแปลง toolchain หรือไม่ และเมื่อ AI " +"ทั้งสองโมเดลดึงข้อมูลได้ดีแล้ว การฝึกยังเพิ่มอีกเท่าไหร่? " +"คำตอบจะช่วยให้เราตัดสินใจได้ว่าโมเดลแต่ละประเภทมีประโยชน์มากที่สุดที่ใด" + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "สิ่งนี้แนะนำเอเจนต์ AI ประเภทใด" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"หากโมเดลต่างๆ กลายเป็นความช่วยเหลือในขั้นตอนต่างๆ " +"การจัดการที่เป็นประโยชน์อาจเป็นตัวแทนในวงกว้างที่สามารถเข้าถึงโมเดล AI " +"เฉพาะทางได้ เมื่องานกลายมาเป็นการค้นหาคอมไพเลอร์ที่คุ้นเคย " +"งานนั้นก็สามารถถามโมเดล AI เฉพาะทางสำหรับผู้สมัครได้ หากผลลัพธ์ไม่สมเหตุสมผล" +" สารในวงกว้างสามารถกลับไปยังหลักฐานเป้าหมายหรือตรวจสอบการวัดเองได้" + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"ในการจัดการดังกล่าว " +"ความเชี่ยวชาญเฉพาะทางจะกลายเป็นเครื่องมือที่ตัวแทนสามารถเลือกได้ในขณะที่การสืบสวนพัฒนาขึ้น" +" ตัวแทนรักษาอิสระในการเปลี่ยนทิศทางที่ทำให้ความก้าวหน้าก่อนหน้านี้เป็นไปได้" + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"สิ่งนี้เป็นไปตามธรรมชาติจากการเปลี่ยนแปลงทางอุตสาหกรรมที่ฉันอธิบายไว้ในบทความก่อนหน้านี้" +" ความสามารถในการทำการทดสอบอื่นๆ " +"อีกมากมายได้เปลี่ยนแปลงวิธีที่เราจัดระเบียบงาน " +"นอกจากนี้ยังให้เหตุผลแก่เราในการถามว่าการตัดสินใจใดต้องใช้วิจารณญาณกว้างๆ " +"และการตัดสินใจครั้งใดจะปรับปรุงผ่านประสบการณ์ซ้ำแล้วซ้ำเล่ากับงานฝีมือเฉพาะอย่าง" + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"ตอนนี้โมเดลทั่วไปที่เก่งที่สุดมีที่ยืนในวิธีทำงานของผม " +"เพราะแก้ปัญหาที่ก่อนหน้านี้ผมยังแก้ไม่ได้ " +"ความสำเร็จเหล่านี้ทำให้ผมอยากศึกษางานให้ละเอียดขึ้น " +"ว่ามากน้อยแค่ไหนต้องอาศัยความสามารถที่กว้างของโมเดล " +"และมากน้อยแค่ไหนอาจให้โมเดลที่ฝึกเฉพาะงานสร้างโค้ดแบบนี้ทำได้" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}ที่เก็บข้อมูลช่วยให้เรามีวิธีทดสอบคำถาม{ph1} " +"ฉันต้องการใช้บันทึกนั้นเพื่อสร้างการเปรียบเทียบและดูสิ่งที่เราเรียนรู้" + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "หลักฐานและการระบุแหล่งที่มาของแบบจำลอง" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"ตัวอย่างจะอธิบายการเปรียบเทียบระดับฟังก์ชันในอดีตที่บันทึกไว้ในการคอมมิตที่เชื่อมโยง" +" การตรวจสอบรันไทม์ทั้งเกมถือเป็นเหตุการณ์สำคัญที่แยกจากกัน " +"แหล่งที่มาและบันทึกการจับคู่ได้รับการตรวจสอบเมื่อวันที่ 13 ตุลาคม พ.ศ. 2569" + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"ป้ายกำกับ TH09 {ph0} หมายถึง GPT-6-Astra โมเดลที่เกี่ยวข้องกับ {ph1} " +"มีการเปลี่ยนแปลงเมื่อเวลาผ่านไป " +"ดังนั้นป้ายกำกับเพียงอย่างเดียวจึงไม่สามารถระบุโมเดลที่ใช้ในการดำเนินการเฉพาะได้" +" ชื่อโมเดลที่ชัดเจนในคอมมิตที่อ้างถึงอื่นๆ ให้การระบุแหล่งที่มาที่บันทึกไว้ " +"ประวัติเหล่านี้ไม่ได้รวมการวัดต้นทุนหรือความพยายามอย่างสม่ำเสมอสำหรับการวิ่งทุกครั้ง" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 อายุการใช้งานของวัตถุชั่วคราว:{ph1} " +"{ph2}การตรวจสอบบริบทก่อนหน้า{ph3} และ " +"{ph4}การสร้างใหม่เสร็จสมบูรณ์ได้รับการตรวจสอบโดยการคอมไพล์ใหม่ทั้งหมดจากแหล่งที่มา{ph5}" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}คอลแบ็ก Front ของ TH09:{ph1} {ph2}บริเวณที่ตรวจพบว่ายังไม่ตรง{ph3}, " +"{ph4}กราฟการควบคุมใหม่ของ Astra{ph5} และ " +"{ph6}การตรวจคอมไพล์ซ้ำที่ผ่านการยอมรับ{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}ความรู้เกี่ยวกับคอมไพเลอร์:{ph1} {ph2}TH095 " +"นำพฤติกรรมตัวระบุ-บัคเก็ตกลับมาใช้ใหม่{ph3}, {ph4}TH04 " +"ซอร์สโค้ดของผู้เล่นและลำดับลิงก์เกอร์{ph5} และ {ph6}Luna " +"การสร้างศัตรูใหม่ของ TH09 ใหม่ทั้งหมด ฟังก์ชั่น{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}การตรวจสอบและการวินิจฉัย:{ph1} {ph2}TH08 " +"การตรวจสอบคงที่แบบจุดลอยตัว{ph3}, {ph4}TH08 การตรวจสอบเชิงตัวเลข{ph5} และ " +"{ph6}TH09 การสร้างใหม่เพื่อประหยัดการเล่นซ้ำ{ph7}" + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"การเปรียบเทียบที่เสนอของรุ่นพิเศษและการฝึกอบรม RL เป็นการทดลองในอนาคต " +"ประวัติโครงการเป็นแรงบันดาลใจให้พวกเขา " +"ไม่มีการประเมินแบบจำลองเฉพาะทางที่ได้รับการฝึกอบรมสำหรับบทความนี้" + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "วิศวกรรมย้อนกลับจำเป็นต้องมีโมเดลที่ใหญ่กว่านี้หรือไม่? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"สิ่งที่ Touhou การสร้างใหม่สอนฉันเกี่ยวกับโมเดลทั่วไป โมเดลผู้เชี่ยวชาญ " +"และการเรียนรู้ที่จะเสนอสมมติฐานที่ดีกว่าจากคำติชมของคอมไพเลอร์" + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "ในหน้านี้" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "แบบจำลองและเรียงความวิศวกรรมย้อนกลับ" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "การทดลองสร้างใหม่ที่เลือก" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "กลับขึ้นด้านบน" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}บันทึกหลักฐานโดยละเอียด{ph1} มีผลการเปรียบเทียบและบริบทของการทดลอง" + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "โดย N0zoM1z0 · 13 ตุลาคม 2026 · ฉบับร่างสำหรับตรวจทาน" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "คู่มือการติดตั้ง" diff --git a/website/locales/tr/messages.po b/website/locales/tr/messages.po index 4b4d2b5d2..9d71134ed 100644 --- a/website/locales/tr/messages.po +++ b/website/locales/tr/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "İçeriğe geç" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Anasayfa{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Tersine mühendislik üzerine düşünceler." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Oyun rekonstrüksiyonu{ph0}Deneme" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Tersine mühendislikte endüstri devrimi" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -53,34 +53,35 @@ msgstr "" "yapılandırılması bana projeler arasında birleşen aracılar, doğrulama ve " "bilgi hakkında bilgi verdi." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Makaleyi okuyun" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Başlangıç N0zoM1z0 * 10 Ekim 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -101,6 +102,8 @@ msgstr "" "deneyimlerden yararlanma." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -136,112 +139,117 @@ msgstr "" "REA - Yazılımın nasıl çalıştığını öğrenin. Kodlama aracınızla tersine " "mühendislik yapın." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "REA ana sayfası" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Ana menü" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "GitHub’da REA" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "REA Discord topluluğuna katıl" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "REA’yı X’te takip et" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -250,35 +258,35 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Anasayfa{ph1} / {ph2}Blog{ph3} / Touhou rekonstrüksiyonu" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Deneme * Touhou rekonstrüksiyonu" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Tersine mühendislikte sanayi devrimi." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Başlangıç N0zoM1z0 * 10 Ekim 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Önemli noktalar" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -291,7 +299,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -305,7 +313,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -318,7 +326,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -331,7 +339,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -341,65 +349,65 @@ msgstr "" "{ph0}RE'NİN sanayi devriminin ilk günlerindeyiz.{ph1} Yöntemler hala " "şekilleniyor. Keşfedilecek çok şey kaldı." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Bileşikler nasıl deneyimlenir" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}İnsan yönü{ph1} * Hedef ve kabul kriterleri" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Özerklik" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Ajan" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Bir deney seçin.{ph0}Bir hipotez öner." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Doğrulama" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Doğrulama ölçütü" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "A'ya karşı test{ph0}somut referans." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Depo" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Çalışma belleği" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -408,7 +416,7 @@ msgstr "Kod, kanıt,{ph0}çekler ve dersler." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -417,26 +425,26 @@ msgstr "Uyumsuzluk{ph0}{ph1}Hipotezi gözden geçirin{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Daha iyi bir{ph0}{ph1}başlangıç noktası{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Yeniden kullanım" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Geçmek{ph1} * Sonucu ve kanıtını saklayın" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -445,14 +453,14 @@ msgstr "" "Her proje bir sonrakini daha iyi bir başlangıç noktasıyla bırakır. Bu, bir " "boşluk keşfettiğimizde çekleri düzeltmeyi de içerir." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "Bu makalede" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -460,7 +468,7 @@ msgstr "{ph0}Ağustos 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -468,7 +476,7 @@ msgstr "{ph0} TH08 : devamı{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -476,7 +484,7 @@ msgstr "{ph0}İki yaklaşım{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -484,7 +492,7 @@ msgstr "{ph0} TH095 : bileşik{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -492,7 +500,7 @@ msgstr "{ph0} TH04: mimariler arası{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -500,7 +508,7 @@ msgstr "{ph0}Kesinden okunabilirliğe{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -508,18 +516,18 @@ msgstr "{ph0}Endüstriyel değişim{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Ne mümkün olur{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Ağustos 2026'da neler değişti" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -534,7 +542,7 @@ msgstr "" "harcamak anlamına geliyordu. Aynı zamanda kafamda giderek daha büyük bir " "resim tutmak anlamına geliyordu." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -548,7 +556,7 @@ msgstr "" "başka yerlerde yararlı olabilir, ancak her alanın güvenilir bir referansa " "karşı neyi kontrol edebileceğini belirlemesi gerekir." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -561,7 +569,7 @@ msgstr "" "gidebileceğini görmek istedim. Touhou'nun yeniden inşası bana öğrenmem " "gereken önemli bir proje verdi." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -578,7 +586,7 @@ msgstr "" "Projenin yönüne ve kontrollerinin güvenilir olup olmadığına daha fazla " "dikkat edebilirdim." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -589,7 +597,7 @@ msgstr "" "kalacağını merak etmeye başladım. Bir sonraki oyun yeni öğrendiğimiz her " "şeyden faydalanır mı?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: insan işi üzerine inşa etmek" @@ -598,7 +606,7 @@ msgstr "TH08: insan işi üzerine inşa etmek" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -612,7 +620,7 @@ msgstr "" " bir temel verdi. Devamında koruduğum yapı bilgisi ve katkıların tarihi ile " "geldi." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -623,7 +631,7 @@ msgstr "" "Bağımsız devamım 13 Ağustos'ta başladı. 19 Ağustos'a kadar defter, " "tanımlanan 1.107 oyun işlevinin tümü için kaynak kaydetti." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -634,7 +642,7 @@ msgstr "" "Linux yeniden yapılanma limanı işlendi. Bunu bir Web baskısı izledi. Yerel " "Linux 64 bit sürümü 30 Ağustos'ta geldi." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -649,7 +657,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -668,12 +676,12 @@ msgstr "" " önerir ve onu test eder; Bir uyumsuzluk ona araştırması gereken belirli bir" " şey verir." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Yanlış sabitle tam bir eşleşme" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -684,7 +692,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -697,7 +705,7 @@ msgstr "" "oyuncu gücünü {ph0}'a karşı kontrol etti. Orijinal, maksimum güç eşiği olan " "{ph1}'ı kullandı." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -712,13 +720,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}Yine de işlev tam karşılaştırmayı çoktan geçmişti.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -733,7 +741,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -749,7 +757,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -763,7 +771,7 @@ msgstr "" "denetim{ph3} daha sonra 1.548 kayan noktalı sabit referansı inceledi. Kabul " "edilen beş işlevde on iki yanlış referans daha buldu." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -777,7 +785,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -787,7 +795,7 @@ msgstr "" "{ph0}Doğrulama referansının (oracle) da yeniden yapılandırılması " "gerekiyordu.{ph1} Tamir etmek, oyunu tamir etmenin bir parçasıydı." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -805,7 +813,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -821,7 +829,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -831,7 +839,7 @@ msgstr "" "{ph0}Başarılı bir parti bize hem kurtarılan kodu hem de bir sonraki parti " "için daha iyi bir ortam sağladı.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "İki farklı yeniden yapılanma fikri" @@ -840,7 +848,7 @@ msgstr "İki farklı yeniden yapılanma fikri" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -852,7 +860,7 @@ msgstr "" "anlaşmazlığını açıkça ortaya koyuyor. Bildirim, tamamlanana kadar daha fazla" " gelişmenin özel olarak gerçekleşeceğini duyurdu. Bir pasaj okur:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -862,7 +870,7 @@ msgstr "" "çalışmalarımızdan aldığı yükseliş, gelecekteki ayrıştırma çabaları için kötü" " bir imaj çiziyor…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -879,7 +887,7 @@ msgstr "" "anlaşmazlık, yeniden yapılanmanın nasıl ilerlemesi gerektiği ve bir katkının" " nasıl değerlendirilmesi gerektiği ile ilgili." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -892,7 +900,7 @@ msgstr "" "ölçüde o kişinin uzmanlığına dayanıyordu. Katılımcıya olan güven önemliydi " "çünkü akıl yürütmenin çoğu onlar çalışırken gerçekleşti." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -903,7 +911,7 @@ msgstr "" "Benim için değişen şey, bir ajanın bu bilgiyi bir sonraki soruşturmayı kendi" " başına yürütmek için kullanabilmesiydi." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -918,7 +926,7 @@ msgstr "" "temsilci yapmış olsa bile, başka bir kişinin neden bir uygulamayı " "seçtiğimizi inceleyebilmesini istiyorum." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -931,7 +939,7 @@ msgstr "" "soruları gündeme getiriyor. Ayrıca, bir katkıyı kabul etmeden önce " "bakıcıların bilmesi gerekenleri de değiştirir." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -946,7 +954,7 @@ msgstr "" "ne zaman yanlış olduğunu anlamalıdır. Farklı topluluklar bu değişimin ne " "kadarını üstlenmek istediklerini seçebilir." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -971,7 +979,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -983,14 +991,14 @@ msgstr "" "bildirimi{ph1} ve {ph2}katkı politikası{ph3}. Alıntı kısaltılmış bir " "alıntıdır. TH08 {ph4}kredileri ve kaynağı{ph5} devam sınırını kaydeder." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: deneyim birleştirmeye başlar" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1005,7 +1013,7 @@ msgstr "" "nasıl başlanacağı ve nasıl devam ettirileceği hakkında çok daha fazlasını " "zaten biliyorduk." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1019,7 +1027,7 @@ msgstr "" "başlatmadan yaklaşık on iki gün sonra 10 Eylül'de oynanabilir olarak " "işaretlendi." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1030,7 +1038,7 @@ msgstr "" " bir oyun üzerinde yapılan işten yararlanabilir. Deneyim, araçlarda ve " "projenin organize edilme biçiminde zaten mevcuttu." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1045,7 +1053,7 @@ msgstr "" " TH095'NUN tüm program yapısına nasıl yaklaştığımızı şekillendirmeye " "yardımcı oldu." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1058,7 +1066,7 @@ msgstr "" "olmaya devam edebilir. Bir sonraki temsilci, sonuca yol açan soruşturmayı " "tekrar etmeden sonucu kullanabilir." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1073,7 +1081,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1085,7 +1093,7 @@ msgstr "" " gelir.{ph1} Bir sonraki projenin çabalarının çoğunu, hedefiyle ilgili " "gerçekte yeni olan şeylere harcayabiliriz." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1098,7 +1106,7 @@ msgstr "" "Kaynağın neden bu şekilde göründüğünü bulmak için tüm projenin geçmişini " "yeniden yapılandırmaları gerekmez." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: iş akışı farklı bir mimariden sağ çıkıyor" @@ -1107,7 +1115,7 @@ msgstr "TH04: iş akışı farklı bir mimariden sağ çıkıyor" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1123,7 +1131,7 @@ msgstr "" "gerektiriyordu. Mevcut {ph2}ReC98 çalışması{ph3} bize burada da değerli " "bilgiler ve kaynak materyaller verdi." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1136,7 +1144,7 @@ msgstr "" "yerel bir 64 bit bağlantı noktasıdır. Çalışan bir DOS sürümü oluşturmak, " "önce bu bağlantı noktasına bir başvuru verir." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1149,7 +1157,7 @@ msgstr "" "bir soruyu sonuca kadar takip edebilir ve bu sonucun bir sonraki deneye " "rehberlik etmesine izin verebilir." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1163,7 +1171,7 @@ msgstr "" "araştırabileceğimiz bir şey. Kanıt ve kontroller mevcut olduğunda, bir " "temsilci, bir Windows başlığında olduğu gibi soru üzerinde de çalışabilir." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1174,7 +1182,7 @@ msgstr "" " yeni bir çalışma şekliyle baştan başlamaya zorlamadı. Mimari sorunu " "tanımladı; iş akışı hala bize bunu çözmenin bir yolunu verdi." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1191,7 +1199,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1202,12 +1210,12 @@ msgstr "" "manuel test{ph1} · {ph2}64 bit bağlantı{ph3} noktası. Liman geliştirme " "aşamasındadır." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Tam koddan okunabilir koda" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1216,7 +1224,7 @@ msgstr "" "Bir yeniden yapılanma işe yaradığında, başka birinin bunu anlayabilmesini " "istiyorum." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1231,7 +1239,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1248,7 +1256,7 @@ msgstr "" "kaynakla birlikte tutarız, böylece bir sonraki kişi bu yorumun nereden " "geldiğini görebilir." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1263,14 +1271,14 @@ msgstr "" "karar vermede çok az yardım sağlar. Davranışı güvenli bir şekilde taşımak " "için eski bellek erişiminin arkasındaki ilişkiyi kurtarmamız gerekiyor." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Şu anda kullandığım sipariş:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1286,7 +1294,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1302,7 +1310,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1318,7 +1326,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1333,7 +1341,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1350,7 +1358,7 @@ msgstr "" "programın egzersiz yaptığımız yollar boyunca hala doğru şekilde " "oluşturulduğunu ve davrandığını kontrol eder." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1364,7 +1372,7 @@ msgstr "" "acenteye bir refaktörü daha fazla taşımadan önce soruşturmada somut bir " "başarısızlık sağlar." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1382,7 +1390,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1400,7 +1408,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1411,12 +1419,12 @@ msgstr "" "yapılanma, kurtarılan bilgiyi kullanılabilir hale getirir.{ph1} Daha sonra " "her ikisine de bir liman inşa edilebilir." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Bunu endüstriyel bir değişim yapan nedir" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1429,7 +1437,7 @@ msgstr "" "en faydalı şeylerden biri haline geldi. Daha iyi bir araç, ihtiyacı olan " "sonraki her işleve yardımcı olabilir." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1442,7 +1450,7 @@ msgstr "" "yerde takip etmek için yeterli özgürlüğe ihtiyacı vardır. Her adımı yazmamı " "beklemek zorunda kalırsa, işin çoğu dikkatime bağlı kalır." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1456,7 +1464,7 @@ msgstr "" "proje kilometre taşını destekleyip desteklemediğine hala karar vermem " "gerekiyor." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1471,7 +1479,7 @@ msgstr "" "Aracı, önerdiği kaynağı test etmek ve açıklamasının nerede geçerli olduğunu " "görmek için bunları kullanabilir." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1489,7 +1497,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1509,7 +1517,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1526,7 +1534,7 @@ msgstr "" "onarmalı ve etkilediği sonuçları tekrar gözden geçirmeliyiz. Bir sonraki " "proje daha sonra daha güçlü bir aracı devralabilir." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1541,7 +1549,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1553,7 +1561,7 @@ msgstr "" "çeklerini ve derslerini ileriye taşımak için ortak bir yol sunar. Bir oyun " "üzerinde çalışmak, diğerinin başlangıç koşullarını iyileştirebilir." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1565,12 +1573,12 @@ msgstr "" "araçları geliştirmek, bir sonraki kişinin - veya bir sonraki temsilcinin - " "ne kadarını yapabileceğini değiştirir." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Şimdi düşünebileceğimiz projeler" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1582,7 +1590,7 @@ msgstr "" "verebileceğimden daha fazla kendi dikkatimi talep edebilir. Birçok proje " "fikir olarak kalacaktır." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1600,7 +1608,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1611,7 +1619,7 @@ msgstr "" "geri bildirim ve birikmiş bilgi, bir temsilcinin bu konuda güvenilir bir " "şekilde çalışmasına izin verir?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1622,12 +1630,12 @@ msgstr "" " bir sonrakine yaklaşma şeklimizi geliştirebilir. Bunun bizi ne kadar ileri " "götürebileceğini araştırmaya devam etmek istiyorum." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Proje kilometre taşları ve kaynakları" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1661,7 +1669,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1695,7 +1703,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1713,7 +1721,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1737,7 +1745,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1759,7 +1767,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1775,7 +1783,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1796,7 +1804,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1810,7 +1818,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1831,27 +1839,27 @@ msgstr "" "N0zoM1z0, manuel tersine mühendislik, AI ajanlarıyla Touhou rekonstrüksiyonu" " ve bilginin TH08, TH095 ve PC-98 TH04'DA nasıl birleştiğini yansıtır." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Projeler arasında taşınan deneyim" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Touhou yeniden yapılanma denemesi" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -1860,18 +1868,18 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Ana{ph1}{ph2} Sayfa/{ph3} Dinozor hız laboratuvarı" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "İncele → yeniden oluştur → değiştir" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Dinozorun hız kuralını yeniden oluşturun." @@ -1880,7 +1888,7 @@ msgstr "Dinozorun hız kuralını yeniden oluşturun." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1892,15 +1900,15 @@ msgstr "" "bulun. REA {ph0}çalışan komut dosyasını döndürdü;{ph1} Bu mini oyunu " "{ph2}ayarlanabilir hızda oluşturmak için kuralını kullandık.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Bu sayfada" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1908,7 +1916,7 @@ msgstr "{ph0}Hızı oynayın ve değiştirin{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1916,7 +1924,7 @@ msgstr "{ph0}Kurtarılan kuralı okuyun{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1924,18 +1932,18 @@ msgstr "{ph0}Yeniden yapılanmayı kontrol edin{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Analizi deneyin{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Hızı oynayın ve değiştirin" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1947,49 +1955,49 @@ msgstr "" "bir hıza geçer. 6'dan başlamak ve yavaş yavaş tekrar hızlandırmak için " "kurtarılan kuralı seçin." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Yeniden oluşturulan oyunu oyna" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Oyna" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Zıpla ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Yeniden başlat" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Hız" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Kurtarılan hızlanma kuralını kullanın" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Orijinal kural: 6'dan başlayın, ardından 13'e doğru artırın." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Kendi hızınızı ayarlamak için kaydırıcıyı hareket ettirin. Boşluk veya " "Atlama bir kaktüsü temizler." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -1998,7 +2006,7 @@ msgstr "" "Yeniden yapılandırmayı oynatmak için JavaScript'YU etkinleştirin. Yukarıdaki" " kod ve açıklama okunabilir durumda kalır." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Döndürülen REA komut dosyasını okuyun" @@ -2006,7 +2014,7 @@ msgstr "Döndürülen REA komut dosyasını okuyun" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2020,7 +2028,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2030,18 +2038,18 @@ msgstr "" "Ayarlar {ph0}, {ph1} ve {ph2}'tür. Oyun bu dalı çarpışma olmadan bir " "güncellemede çalıştırır." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Yeni oyunda aynı kuralı kullanın" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Kopyala" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2058,18 +2066,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}Hız kuralını indirin{ph1} * {ph2}Oyun kodunu okuyun{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Yeniden yapılanmayı kontrol edin" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2080,27 +2088,27 @@ msgstr "" "dışı olarak adlandırdık. Kaydedilen hızları, kurtarılan kuralın tekrarı ile " "karşılaştırın." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Güncellemeler" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Orijinal oyun" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Yeniden kural" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Hız kontrolünü çalıştırın" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2109,14 +2117,14 @@ msgstr "" "Değerler üç ondalık basamağa yuvarlanır. Şube eklemeden önce kontrol eder, " "böylece son artış 13'ün biraz üzerinde hız alabilir." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Analizi kendiniz deneyin" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2125,7 +2133,7 @@ msgstr "{ph0}Kodlama aracınızla REA'YU ayarlayın.{ph1}" #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2133,7 +2141,7 @@ msgid "" msgstr "" "Kullanarak {ph0}{ph1}tarayıcı bağlantı adımlarını{ph2} sayfa URL'si olarak." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2150,7 +2158,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2162,7 +2170,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2176,7 +2184,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2191,7 +2199,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2217,12 +2225,12 @@ msgstr "" "Dinozor oyununun hız kuralını REA ile okuyun, yeniden oluşturun, ardından " "hızı değiştirin ve oynayın." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Dinozor hız rekonstrüksiyonu" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2231,52 +2239,52 @@ msgstr "" "Dinozor mini oyunu. Oyun odaklanırken Atlama düğmesini kullanın veya Boşluk " "tuşuna basın." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Yeniden oluşturulan hız kuralını kopyala" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Dinozor analizi istemini kopyala" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "İçeriğe geç" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Anasayfa{ph1} / SSS" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA SSS." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Kurulum, güncellemeler, analiz ve sorun giderme." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Konular" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2284,7 +2292,7 @@ msgstr "{ph0}Kurulum ve güncellemeler{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2292,7 +2300,7 @@ msgstr "{ph0}Analiz{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2300,31 +2308,31 @@ msgstr "{ph0}Sorun giderme{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Veri ve paylaşım{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Kurulum ve güncellemeler" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "REA’yı nasıl kurarım?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Terminal * aracı kurulumu" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Kopyala" @@ -2332,7 +2340,7 @@ msgstr "Kopyala" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2346,12 +2354,12 @@ msgstr "" " sorunuzu verin. Gereksinimler ve ilk analiz için {ph0}kurulum " "kılavuzuna{ph1} bakın." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Hangi kodlama aracıları REA kullanabilir?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2366,18 +2374,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Kodlama aracınızı bağlayın{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "REA’yı nasıl güncellerim?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2386,13 +2394,13 @@ msgstr "" "REA, hata düzeltmeleri de dahil olmak üzere sık sık yayınlanır. CLI'YU npm " "ile kurduysanız :" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Terminal * kurulu CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2402,14 +2410,14 @@ msgstr "" "Güncelleştirme tarafından yazdırılan kur yenile komutunu izleyin. Aracınızı " "{ph0} aracılığıyla kurarsanız, çalıştırın:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Terminal * aracı kurulumunu yenile" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2422,14 +2430,14 @@ msgstr "" " çalıştırın. Tek seferlik CLI kullanımı için {ph0} ifadesinden sonra komutu " "ekleyin." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Beceriyi yüklüyor mu skills.sh yeter mi?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2441,24 +2449,24 @@ msgstr "" "için MCP {ph0}kurulumunu{ph1} çalıştırın ve eşleşen beceriyi yükleyin, " "ardından aracınızı yeniden başlatın, böylece araçları çağırabilir." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Analiz" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "REA ile neleri analiz edebilirim?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Sahip olduğunuz yazılım türüyle başlayın:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2470,7 +2478,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2482,7 +2490,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2492,7 +2500,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2504,12 +2512,12 @@ msgstr "" "paketlenmiş kaynaklar için iş akışlarına sahiptir. Çalışılan soruşturmalar " "için {ph0}vaka incelemelerine bakın{ph1}." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Hopper, Ghidra veya IDA'YA ihtiyacım var mı?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2521,7 +2529,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2534,12 +2542,12 @@ msgstr "" "hangi sağlayıcının kullanılabileceğini belirler. {ph0}Makine kodu " "programlarının analizini ayarlayın{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "REA'YU kodlama aracısı olmadan kullanabilir miyim?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2548,14 +2556,14 @@ msgstr "" "Evet. CLI aynı analiz iş akışlarını kullanır. Yerel bir JavaScript veya " "Electron uygulaması için:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Terminal * statik uygulama analizi" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2566,13 +2574,13 @@ msgstr "" " seçenekleri için CLI'YU {ph0}kullanın.{ph1}" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA hangi kodu döndürür?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2587,7 +2595,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2599,12 +2607,12 @@ msgstr "" "test etmek için kullanır. DX-Ball {ph0}hesaplaması{ph1} ve {ph2}CTF bayrak " "denetleyicisi{ph3}, bu işlemin nasıl çalıştığını gösterir." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Ajanıma ne sormalıyım?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2621,7 +2629,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2629,7 +2637,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2639,18 +2647,18 @@ msgstr "" "Yolu hedefinizle değiştirin. {ph0}Kılavuzlar{ph1}, yerel, Electron ve " "tarayıcı örnekleri için bilgi istemleri sağlar." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Sorun giderme" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Temsilcim neden REA araçlarını göremiyor?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2660,7 +2668,7 @@ msgstr "" "Aracınızı Kur'dan sonra yeniden başlatın veya yeniden bağlayın. REA kaydını " "{ph0} kontrol edin; Codex için :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Terminal * bir müşteriyi kontrol edin" @@ -2668,7 +2676,7 @@ msgstr "Terminal * bir müşteriyi kontrol edin" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2679,14 +2687,14 @@ msgstr "" "Rapor eksik veya eski bir kayıt gösteriyorsa, bu istemci için kur'u " "çalıştırın:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Terminal * bir müşterinin kurulumunu onarın" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2698,14 +2706,14 @@ msgstr "" "ancak araçlar yoksa, istemcinin MCP bağlantı hatasını kontrol edin. Daha " "{ph0}fazla kurulum teşhisi{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Önce Hopper'YU çalıştırmam gerekiyor mu?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2717,14 +2725,14 @@ msgstr "" "analizden önce ilk çalıştırma demo modu seçimini veya lisans aktivasyonunu " "tamamlayın. {ph0}Yerel sağlayıcı kurulumuna bakın{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Bir hatayla karşılaşırsam ne yapmalıyım?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2736,7 +2744,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2749,17 +2757,17 @@ msgstr "" "Sorun, makine kodu programlarının analizini içerdiğinde sağlayıcı adını " "ekleyin." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Veri ve paylaşım" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "REA uygulamamı yüklüyor mu?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2768,7 +2776,7 @@ msgstr "" "REA makinenizdeki hedefleri analiz eder. Aracınız sonuçları alır ve model " "sağlayıcısının veri politikası bu sonuçlar için geçerlidir." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Bir örneği nasıl paylaşabilir veya katkıda bulunabilirim?" @@ -2777,7 +2785,7 @@ msgstr "Bir örneği nasıl paylaşabilir veya katkıda bulunabilirim?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2793,7 +2801,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2818,77 +2826,77 @@ msgstr "" "Yaygın REA sorularının yanıtları: kurulum, güncellemeler, analiz araçları, " "kodlama aracıları, sorun giderme ve paylaşım örnekleri." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "REA hakkında sıkça sorulan sorular" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "REA kurulum komutunu kopyalayın" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "REA güncelleme komutunu kopyala" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Aracı kurulum yenileme komutunu kopyala" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "REA CLI analiz komutunu kopyalayın" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Örnek çözümleme istemini kopyala" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "İstemci tanılama komutunu kopyala" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Kapsamlı kurulum komutunu kopyala" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "İçeriğe geç" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Home{ph1} / İlk araştırmanız" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Nerede olduğunu öğrenin{ph0}dışa aktarılan notlar gider." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2897,14 +2905,14 @@ msgstr "" "Küçük bir uygulamayı incelemek, Notları dışa aktar düğmesini takip etmek ve " "bir ayrıntıyı kendiniz kontrol etmek için REA kullanın." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "Bu alıştırmada" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2912,7 +2920,7 @@ msgstr "{ph0}1. Kurmak{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2920,7 +2928,7 @@ msgstr "{ph0}2. İhracat hakkında soru sorun{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2928,7 +2936,7 @@ msgstr "{ph0}3. Cevabı takip et{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2936,13 +2944,13 @@ msgstr "{ph0}4. Bir tahmini kontrol edin{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Başka bir soru sor{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Aracınızı REA'ya bağlayın" @@ -2955,29 +2963,29 @@ msgstr "1. Aracınızı REA'ya bağlayın" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Kopyala" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Veya bu komutu terminalinizde çalıştırın:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2986,14 +2994,14 @@ msgstr "" "Planı gözden geçirin, kurulumu onaylayın ve aracınızı yeniden başlatın. " "Zaten bağlandınız mı? Aşağıdan devam edin." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. CSV'NUN nerede yazıldığını sorun" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3005,7 +3013,7 @@ msgstr "" " Electron uygulamasıdır. Aracınız, Electron'YU yüklemeden veya başlatmadan " "kodunu inceleyebilir." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3017,14 +3025,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Örnek ZİP dosyasını indirin{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3034,12 +3042,12 @@ msgstr "" "Temsilciniz dosya indiremiyorsa, bu arşivi kendiniz açın. {ph0} klasörünün " "yolunu ve aynı dışa aktarma sorusunu verin." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Cevabı koda geri takip edin" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Dosya ve satır referanslarıyla kısa bir açıklama arayın:" @@ -3048,7 +3056,7 @@ msgstr "Dosya ve satır referanslarıyla kısa bir açıklama arayın:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3059,12 +3067,12 @@ msgstr "" "Düğme bir {ph0} mesajı gönderir. Ana işlem notları CSV olarak biçimlendirir " "ve {ph1}. Sütunlar {ph2} ve {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Düğmeden dosya yazıcısına" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3073,7 +3081,7 @@ msgstr "" "REA'NUN statik analizi, mesajı işleyicisiyle eşleştirir. Hedef koddan " "okunur." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3085,18 +3093,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}Tam kod izlemesine ve kaydedilen REA sonucuna bakın{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Bir tahmini kontrol edin" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3105,19 +3113,19 @@ msgstr "" "Virgül, CSV sütunlarını ayırır. Bir not başlığının kendisi virgül veya " "tırnak işareti içeriyorsa ne olur?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Kontrolü kendin yap" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Paketlenmemiş {ph0} klasöründe bir terminal açın:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3127,24 +3135,24 @@ msgstr "" "kullanır. Aracınız aynı JavaScript'YU platformunuzun kabuğunda " "çalıştırabilir." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Başka bir soru sor" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Aynı sohbette bir takip yapmayı deneyin:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "Dosya yazılamazsa ne olur? Hatayı sayfaya geri izleyin." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3157,7 +3165,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3171,7 +3179,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3185,7 +3193,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3210,65 +3218,65 @@ msgstr "" "aktarılan notların nereye gittiğini sorun ve örnek bir başlıkla CSV " "biçimlendiriciyi kontrol edin." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "İlk REA araştırmanız" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "REA kurulum istemini kopyalayın" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Kurulum komutunu kopyala" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Notları Kopyala soruşturma istemi" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "CSV onay istemini kopyala" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Biçimlendirici onay komutunu kopyala" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "İçeriğe geç" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Ana{ph1} sayfa / Başlayın" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "REA'YU ayarlayın." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3276,49 +3284,49 @@ msgstr "" "REA'YU kodlama aracınıza bağlayın veya terminalinizden yerel bir uygulamayı " "inceleyin." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Bir terminal açın ve kontrol edin:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Terminal" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Kopyala" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3331,7 +3339,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3341,17 +3349,17 @@ msgstr "" "PowerShell daha sonra {ph0}npx'i{ph1} çalıştırdığınızda {ph2} diyorsa, bunu " "bir kez çalıştırın ve tekrar deneyin:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Homebrew kullanıyorsanız :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Aksi takdirde:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Terminali kapatın, tekrar açın, ardından:" @@ -3359,7 +3367,7 @@ msgstr "Terminali kapatın, tekrar açın, ardından:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3371,7 +3379,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3383,7 +3391,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3393,14 +3401,14 @@ msgstr "" "Normal bir yükleyiciyi mi tercih edersiniz? LTS sürümünü şuradan indirin: " "{ph0}nodejs.org{ph1} ." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Kurulum seçenekleri" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3408,7 +3416,7 @@ msgstr "{ph0}Kodlama aracınızı bağlayın{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3416,7 +3424,7 @@ msgstr "{ph0}CLI'YU kullanın{ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3424,18 +3432,18 @@ msgstr "{ph0}Makine kodu programlarının analizini ayarlama{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Yardım almak{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Kodlama aracınızı bağlayın" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3447,12 +3455,12 @@ msgstr "" "desteklenen diğer MCP istemcileri bulunur. Grok Bot'un konektörü sohbetinden" " eklenir." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Kodlama ajanlarında yeni misiniz?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3463,7 +3471,7 @@ msgstr "" "zeka yardımcısıdır. Dosyaları okuyabilir ve komutları çalıştırabilir ve " "değişiklik yapmadan önce sorar. REA, tersine mühendislik araçları sağlar." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3475,7 +3483,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3488,7 +3496,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3501,7 +3509,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3511,7 +3519,7 @@ msgstr "" "{ph0}{ph1} OpenCode{ph2}{ph3}, açık kaynak. Seçtiğiniz model sağlayıcısını " "bağlayın." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3529,18 +3537,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Veya kurulumu kendiniz çalıştırın" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Terminali nasıl açarım?" @@ -3549,7 +3557,7 @@ msgstr "Terminali nasıl açarım?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3565,7 +3573,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3579,7 +3587,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3592,7 +3600,7 @@ msgstr "{ph0} Linux:{ph1} çoğu masaüstünde {ph2} {ph3} {ph4} tuşlarına bas #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3602,7 +3610,7 @@ msgstr "" "{ph0} {ph1} ile bir komut yapıştırın ( macOS : {ph2} {ph3}; Linux " "terminalleri: {ph4} {ph5} {ph6}), ardından Enter tuşuna basın." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3613,12 +3621,12 @@ msgstr "" "ve eşleşen araştırma becerisini ekleyerek mevcut yapılandırmanın yedeğini " "alır. Değişiklikleri uygulamadan önce sorar." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Kur tamamlandığında istemcinizi yeniden başlatın." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Müvekkilimi nasıl yeniden başlatırım?" @@ -3627,7 +3635,7 @@ msgstr "Müvekkilimi nasıl yeniden başlatırım?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3643,7 +3651,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3653,7 +3661,7 @@ msgstr "" "{ph0}Terminal aracıları{ph1} (Claude Code, Codex , Gemini CLI ): oturumdan " "çıkın ve yeniden başlatın." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3663,7 +3671,7 @@ msgstr "" "Electron uygulaması için şununla başlayabilirsiniz:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3674,12 +3682,12 @@ msgstr "" " noktalarını, aramaları ve bağımlılıkları, bulgularınızın kaynak " "konumlarıyla birlikte gösterin." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Yolu yerel hedefinizle değiştirin." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Bir klasörün tam yolunu nasıl alabilirim?" @@ -3688,7 +3696,7 @@ msgstr "Bir klasörün tam yolunu nasıl alabilirim?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3703,7 +3711,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3715,7 +3723,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3725,18 +3733,18 @@ msgstr "" "{ph0}Herhangi bir sistem:{ph1} klasörü bir terminal penceresine sürükleyin " "ve yolu görünür." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "Bir terminalde, boşluk içeren bir yolun etrafına tırnak işaretleri koyun." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "CLI'YU kullanın" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3745,14 +3753,14 @@ msgstr "" "Uygulamayı çalıştırmadan bir JavaScript veya Electron uygulama klasörünü " "veya ASAR arşivini analiz edin:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Statik uygulama analizi" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3762,13 +3770,13 @@ msgstr "" "Yolu çıkarılan uygulama dizininizle değiştirin veya {ph0} dosyası. " "Windows'DA {ph1} burada çalışıyor." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Bir uygulamayı nerede bulabilirim.asar dosyası mı?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3779,7 +3787,7 @@ msgstr "Electron uygulamaları genellikle bir {ph0} klasöründe saklar:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3791,7 +3799,7 @@ msgstr "{ph0}Windows:{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3804,20 +3812,20 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux:{ph1} genellikle {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "Bazı uygulamalar başka bir yere yüklenir. Uygulama için {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3829,31 +3837,31 @@ msgstr "" "işaretlenir." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Kabuğunuzda kalıcı bir {ph0} komutu istiyorsanız:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "CLI'YU kurun" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}JavaScript uygulama kılavuzu ile devam edin{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Makine kodu programlarının analizini ayarlama" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3863,12 +3871,12 @@ msgstr "" "Aşağıdan birini seçin ve yapılandırın, ardından REA'YA yürütülebilir " "dosyanızı veya kitaplığınızı verin." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Bir araç seçin: Ghidra, Hopper veya IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3880,17 +3888,17 @@ msgstr "" " mimariniz için yerel bir kod çözücüye ihtiyacı vardır. Kur'u çalıştırmadan " "önce yolları ayarlama:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Ghidra kurulumunuzu bağlayın" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra bağlantısı · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3901,12 +3909,12 @@ msgstr "" "seçtiğiniz istemci için geçerli ayarları kaydeder. Linux arm64'te, " "Ghidra'NUN yerel kod çözücüsünü ayrı ayrı oluşturmanız gerekebilir." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Ghidra'YU Windows'ya bağlayın" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3917,12 +3925,12 @@ msgstr "" "sürücülerindeki dll'ler için deneysel, salt okunur desteğe sahiptir. Mevcut " "bir Ghidra 12.1 kullanın.x kurulum ve 64 bit JDK 21 veya daha yenisi:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra bağlantısı * Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3930,7 +3938,7 @@ msgstr "" "İki yolu kurulumlarınızla değiştirin, ardından kurulum planını gözden " "geçirin." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3940,7 +3948,7 @@ msgstr "" "çalıştırın; Mevcut bir kurulumu algılar veya onayınız için bir kurulum planı" " sunar." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3949,7 +3957,7 @@ msgstr "" "macOS'DA, katılımsız bir analizden önce Hopper'NUN ilk deneme modu seçimini " "veya lisans etkinleştirmesini tamamlayın." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3960,7 +3968,7 @@ msgstr "" "mevcut bir MCP kaydıyla Windows kullanır. Linux ve macOS başsız analizi " "doğrulanmamıştır." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Mevcut bir IDA MCP kaydını bağlayın" @@ -3970,7 +3978,7 @@ msgstr "Mevcut bir IDA MCP kaydını bağlayın" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3982,13 +3990,13 @@ msgstr "" "dosyasında saklayın. {ph3} girdisi olan varolan bir {ph4} nesnesi de kabul " "edilir. Kurulumdan önce REA dosyasını bu dosyaya yönlendirin:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA bağlantısı * Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4005,7 +4013,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4017,30 +4025,30 @@ msgstr "" " için, {ph1}REA kayıt ortamına REA_İDA_MCP_CONFİG ekleyin ve ikili dosyayı " "açarken IDA öğesini seçin." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "" "Mevcut bir Ghidra kurulumu için aşağıdaki işlevlerden birini inceleyin::" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Fonksiyon analizi" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "{ph0} incelemek istediğiniz işlev adı veya adresle değiştirin." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Makine kodu programları oturumlarının analizi nasıl çalışır?" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4053,7 +4061,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4063,18 +4071,18 @@ msgstr "" "{ph0}İşlev sonucunun kurtarılmış bir hesaplamaya nasıl yol açtığını görmek " "için makine kodu programlarının analizi örneğini izleyin{ph1}." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Yardım almak" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Temsilciniz REA'YU görmüyorsa" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4084,27 +4092,27 @@ msgstr "" "Kur'dan sonra istemciyi yeniden başlatın veya yeniden bağlayın. REA " "bağlantısını {ph0} kontrol edin; Codex için :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Bir müşteriyi kontrol et" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Bir sağlayıcının dikkat etmesi gerekiyorsa" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Kullandığınız sağlayıcıyı kontrol edin. Ghidra için :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Bir sağlayıcıyı kontrol edin" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "Rapor, başarısız kontrolü ve önerilen bir sonraki adımı verir." @@ -4113,7 +4121,7 @@ msgstr "Rapor, başarısız kontrolü ve önerilen bir sonraki adımı verir." #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4126,7 +4134,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4140,7 +4148,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4154,7 +4162,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4179,112 +4187,112 @@ msgstr "" " Electron uygulamasını inceleyin. Kurulum, ilk sorular ve yerel sağlayıcı " "kılavuzları." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Node.js sürüm kontrolünü kopyalayın" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Windows için Node.js kurulum komutunu kopyalayın" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "PowerShell yürütme ilkesi komutunu kopyala" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Homebrew Node.js kurulum komutunu kopyalayın" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "macOS için fnm kurulum komutunu kopyalayın" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "macOS için Node.js 24 komutlarını kopyalayın" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Linux için fnm kurulum komutunu kopyalayın" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Linux için Node.js 24 komutlarını kopyalayın" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA başlangıç kılavuzu" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "REA kurulum istemini kopyalayın" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Aracı kurulum komutunu kopyala" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "JavaScript analiz komutunu kopyalayın" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "CLI kurulum komutunu kopyalayın" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "macOS ve Linux için Ghidra bağlantı komutunu kopyala" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Windows PowerShell için Ghidra bağlantısını kopyalayın" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Windows PowerShell için IDA bağlantısını kopyalayın" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Yerel işlev analizi komutunu kopyala" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "İstemci tanılama komutunu kopyala" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Sağlayıcı tanılama komutunu kopyala" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -4293,20 +4301,20 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Ana{ph1} Sayfa / {ph2}Kılavuzlar{ph3} / Tarayıcı gözlemi" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Ne olduğunu görün{ph0}tıkladığınızda." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4315,14 +4323,14 @@ msgstr "" "Bir eylemi, ağ isteğini ve bir indirme oluşturan JavaScript'YU bağlamak için" " küçük bir tarayıcı uygulaması kullanın." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "Bu kılavuzda" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4330,7 +4338,7 @@ msgstr "{ph0}Örnek{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4338,7 +4346,7 @@ msgstr "{ph0}Tarayıcıyı aç{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4346,7 +4354,7 @@ msgstr "{ph0}Temsilcinize sorun{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4354,13 +4362,13 @@ msgstr "{ph0}CLI'DAN yakalama{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}İsteği ve komut dosyasını okuyun{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Dışa Aktar'ı tıklattığınızda ne olur?" @@ -4370,7 +4378,7 @@ msgstr "Dışa Aktar'ı tıklattığınızda ne olur?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4382,7 +4390,7 @@ msgstr "" "bulunur. Tıklamak {ph4}, iki notu CSV olarak biçimlendirir ve bir indirme " "başlatır." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "CSV indirmek için tıklayın" @@ -4393,7 +4401,7 @@ msgstr "CSV indirmek için tıklayın" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4409,7 +4417,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4427,7 +4435,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4437,17 +4445,17 @@ msgstr "" "{ph0}03 * Aracınız{ph1}{ph2} Dışa aktarma kodunu okudu{ph3}{ph4} Gözlenen " "isteği {ph5} dışa {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Notları Dışa Aktar'ı tıklatmadan önce yakalamayı başlatın." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Uzaktan hata ayıklama ile Chrome'yu açın" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4456,21 +4464,21 @@ msgstr "" "Barındırılan Notlar örneğini ayrı bir tarayıcı profili ve yerel hata " "ayıklama bağlantı noktasıyla açın. Linux üzerinde :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Örnek tarayıcıyı başlatın" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Kopyala" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4479,7 +4487,7 @@ msgstr "" "Yüklü tarayıcınızın yürütülebilir yolunu macOS veya Windows'DA kullanın. " "Sayfa URL'sini incelemek istediğiniz başka bir sayfayla değiştirebilirsiniz." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4488,7 +4496,7 @@ msgstr "" "REA bu mevcut tarayıcıya bağlanır. Sayfanın kontrolünü elinizde tutar, " "işlemi gerçekleştirir ve işiniz bittiğinde tarayıcıyı kapatırsınız." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Temsilcinizden bir eylemi izlemesini isteyin" @@ -4501,7 +4509,7 @@ msgstr "Temsilcinizden bir eylemi izlemesini isteyin" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4513,7 +4521,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4524,7 +4532,7 @@ msgstr "" "REA kullanın. Hangi isteği yapar ve CSV nasıl oluşturulur?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4534,7 +4542,7 @@ msgstr "" "Örnek istemi. Aracınıza hata ayıklama bitiş noktasını verin, {ph0} ve sayfa " "URL'si. Tıklamadan önce yakalamayı başlatmasına izin verin." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4545,23 +4553,23 @@ msgstr "" " çıkan kanıtları okur. Daha sonra dışa aktarmanın arkasındaki komut " "dosyasını inceleyebilir." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Veya terminalden yakalama" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Sayfanın hedef kimliğini bulun:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Sayfayı bul" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4571,14 +4579,14 @@ msgstr "" "Notes örnek URL'sini içeren hedefi seçin. {ph0}Aşağıdaki TARGET_İD öğesini " "kimliğiyle değiştirin, ardından çalıştırın:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Sonraki on saniyeyi yakalayın" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4589,7 +4597,7 @@ msgstr "" "{ph0}Notları dışa aktar'ı{ph1} tıklayın. Sonuç, gözlem penceresi sona " "erdikten sonra gelir." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4599,49 +4607,49 @@ msgstr "" "Yakalanan sonuç, seçilen sayfayı, o penceredeki ağ etkinliğini ve JSON " "yanıtının şeklini içerir. Daha önceki istekler bu yakalamanın dışındadır." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "İsteği okuyun ve komut dosyasını dışa aktarın" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Yerel Notlar örneğinde REA 4.1.0 ile kaydedildi" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Yakalanan gerçek" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Değer" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Talep" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Yanıt" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "İstek başlatıcı" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * komut dosyası" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Yanıt yapısı" @@ -4649,19 +4657,19 @@ msgstr "Yanıt yapısı" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} {ph1} ve {ph2} alanları ile" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Yüklenen komut dosyalarını okuyun" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4672,7 +4680,7 @@ msgstr "" "kullanıldığını görmek için yakalanan komut dosyası kaynağını okuyun:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4684,7 +4692,7 @@ msgstr "" "adımı komut dosyasından gelir; ağ yakalama, bu tıklamanın {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4694,7 +4702,7 @@ msgstr "{ph0}. Virgül veya tırnak işareti içeren başlıklardan nasıl kaça #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4719,65 +4727,65 @@ msgstr "" " tıklama yakalayın, isteği inceleyin ve dışa aktarma komut dosyasını " "izleyin." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Tarayıcı gözlemi" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Kopyala örnek tarayıcıyı başlat" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Örnek istemi kopyala" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Sayfayı kopyala bul" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Sonraki on saniyeyi kopyala" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Kopyala yüklenen komut dosyalarını oku" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "İçeriğe geç" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Ana{ph1} Sayfa / Rehberler" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA kılavuzları." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4786,37 +4794,37 @@ msgstr "" "Yerel bir işlevi, bir Electron dışa aktarımını veya bir tarayıcı isteğini " "analiz edin. Her kılavuz bir bilgi istemi, kod ve sonuçlar içerir." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "İlk soruşturma" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "REA'YU ayarlama" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Kodlama aracınızı bağlayın veya terminalden REA kullanın." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "REA ile başlayın" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Makine kodu programları" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Sol / sağ ses konumunun bir hesaplamasını kurtarın" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4826,22 +4834,22 @@ msgstr "" "bir arayanı takip edin, sayısal sabitleri okuyun ve kurtarılan C'yi kontrol " "edin." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Makine kodu programlarının analizi kılavuzu" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript VE Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Bir CSV dışa aktarımını izleyin" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4850,31 +4858,31 @@ msgstr "" "Küçük bir Not uygulaması, oluşturucu, ön yükleme ve ana işleme bir özellik " "yayar. API, IPC kanalı ve dosya yazıcısını bağlamak için REA kullanın." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript ve Electron kılavuzu" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "" "Daha büyük bir paketlenmiş uygulama için {ph0}Notion pano köprüsü{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Tarayıcı davranışı" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Bir tıklamayı gözlemleyin" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4883,7 +4891,7 @@ msgstr "" "Bir çalışma Notları örneği açın, bir dışa aktarma isteği yakalayın ve " "yanıtını karşıdan yüklemeye dönüştüren kodu bulun." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Tarayıcı gözlem kılavuzu" @@ -4902,12 +4910,12 @@ msgstr "" "Kısa çalışılmış örneklerle REA'YU öğrenin: yerel bir hesaplama, bir Electron" " CSV dışa aktarma ve bir tarayıcı isteği." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -4916,20 +4924,20 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Ana{ph1} Sayfa / {ph2}Kılavuzlar{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Bir Electron izleyin {ph0} CSV dışa aktarma." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4938,14 +4946,14 @@ msgstr "" "Sayfa apı'sinden Electron IPC aracılığıyla CSV dosya yazıcısına bir düğme " "tıklaması izleyin." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "Bu kılavuzda" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4953,7 +4961,7 @@ msgstr "{ph0}Örnek{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4961,7 +4969,7 @@ msgstr "{ph0}Temsilcinize sorun{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4969,7 +4977,7 @@ msgstr "{ph0}Dışa aktarma kodunu izleme{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4977,20 +4985,20 @@ msgstr "{ph0}Örneği deneyin{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}CSV yazıcısını inceleyin{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"Notları dışa aktar\" nereye gidiyor?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5002,7 +5010,7 @@ msgstr "" "Aktar'a{ph1} tıklamak sayfadaki bir API'yi çağırır, ana işleme geçer ve bir " "CSV yazar. Davranış birkaç dosyaya yayılmıştır." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "CSV, Electron süreçleri boyunca dışa aktarır" @@ -5016,7 +5024,7 @@ msgstr "CSV, Electron süreçleri boyunca dışa aktarır" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5033,7 +5041,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5050,7 +5058,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5063,13 +5071,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} notları biçimlendirir → {ph1} {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5080,14 +5088,14 @@ msgstr "" "tanımlar. Yol koddan çıkarılır; Bir çalışma zamanı yakalama neyin " "yürütüldüğünü kontrol edebilir." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "CSV dışa aktarma hakkında soru sorun" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5105,14 +5113,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Kopyala" @@ -5123,7 +5131,7 @@ msgstr "Kopyala" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5134,7 +5142,7 @@ msgstr "" " için REA kullanın. CSV nerede oluşturulur?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5142,7 +5150,7 @@ msgid "" "{ph0}." msgstr "Örnek istemi. Uygulama klasörünün veya {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5153,17 +5161,17 @@ msgstr "" "sınırlarının bir haritasını oluşturur. Aracınız, soruşturmayı dışa aktarma " "özelliğine daraltmak için bu haritayı kullanır." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Dışa aktarma kodunu izleme" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Sayfa küçük bir API çağırır" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5174,7 +5182,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5186,7 +5194,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5196,7 +5204,7 @@ msgstr "" "İşleyiciyi okumak orijinal soruyu yanıtlar: {ph0} notları biçimlendirir ve " "ana işlem {ph1}." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5205,7 +5213,7 @@ msgstr "" "Aşağıdaki indirilebilir örnekte REA 4.1.0 tarafından kaydedilmiştir. Kaynak " "konumları API, kanal ve işleyici bulgularına eşlik eder." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Örneği kendiniz analiz edin" @@ -5213,25 +5221,25 @@ msgstr "Örneği kendiniz analiz edin" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Örnek ZİP dosyasını indirin{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Altı kaynak dosyaya göz atın" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Statik uygulama analizi" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5242,7 +5250,7 @@ msgstr "" " IPC kanalı ve bir eşleşen işleyici bulmalısınız{ph0}. Kaynak konumları " "normalized_result {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5253,13 +5261,13 @@ msgstr "" "aracı, REA'NUN özellik izleme araçlarıyla değişmez bir dizeyi, API adını " "veya IPC kanalını takip edebilir." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "CSV yazıcısını inceleyin" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5269,7 +5277,7 @@ msgstr "" "{ph0}. Hangi girdiler CSV yazıcısına ulaşır ve dosyayı yazmak başarısız " "olursa ne olur?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5284,7 +5292,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5298,7 +5306,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5312,7 +5320,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5338,32 +5346,32 @@ msgstr "" " Notes CSV dışa aktarımını izleyin. İndirilebilir örnek dosyalar ve " "doğrulanmış bir analiz sonucu içerir." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript VE Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Örnek istemi kopyala" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Statik uygulama analizini kopyala" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -5372,7 +5380,7 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5381,13 +5389,13 @@ msgstr "" "analizi" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "DX-Ball'NUN kurtarma{ph0}sol / sağ ses konumunun hesaplanması." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5396,14 +5404,14 @@ msgstr "" "Orijinal talimatları inceleyin, girişi ve sabitleri belirleyin, ardından " "kurtarılan C'yi kontrol edin." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "Bu kılavuzda" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5411,7 +5419,7 @@ msgstr "{ph0}Örnek{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5419,7 +5427,7 @@ msgstr "{ph0}Temsilcinize sorun{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5427,7 +5435,7 @@ msgstr "{ph0}REA sonuçlarını okuyun{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5435,18 +5443,18 @@ msgstr "{ph0}Kurtar ve kontrol et{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Kendi ikili dosyanızı kullanın{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Sol / sağ stereo ses konumlandırmasını hesapla" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5457,7 +5465,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5469,7 +5477,7 @@ msgstr "" "sahiptir: {ph1} çağrısı. REA ayrıca aracıya eksik aritmetiği araştırmanın " "bir yolunu veren talimatlarını ve arayanlarını da döndürür." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Bu şartlarda yeni misiniz?" @@ -5478,7 +5486,7 @@ msgstr "Bu şartlarda yeni misiniz?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5490,7 +5498,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5503,7 +5511,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5516,7 +5524,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5527,7 +5535,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5537,7 +5545,7 @@ msgstr "" "{ph0}Sabitler:{ph1} programda saklanan, ham bayt olarak okunan ve kodu " "çözülen sabit sayılar." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Üç kanıt, bir hesaplama" @@ -5548,7 +5556,7 @@ msgstr "Üç kanıt, bir hesaplama" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5565,7 +5573,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5583,7 +5591,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5593,7 +5601,7 @@ msgstr "" "{ph0}03 * Veri baytları{ph1}{ph2} Başvurulan baytların sayısal " "sabitleri{ph3}{ph4} {ph5}, {ph6}'a ve bir ölçek değerine çözülür.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5602,7 +5610,7 @@ msgstr "" "REA yönergeleri, işlev çağrısı ilişkisini ve baytları sağlar. Ajan onları " "birlikte yorumluyor." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Davranış hakkında soru sorun" @@ -5611,7 +5619,7 @@ msgstr "Davranış hakkında soru sorun" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5622,19 +5630,19 @@ msgstr "" "analizi aracını kurduktan{ph3} sonra, yerel yürütülebilir dosyayı ve bir " "soruyu sağlayın:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Hangi analiz aracını kullanmalıyım?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA, yerel programları okumak için bunlardan birine ihtiyaç duyar:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5648,7 +5656,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5661,7 +5669,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5671,7 +5679,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5687,14 +5695,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Kopyala" @@ -5705,7 +5713,7 @@ msgstr "Kopyala" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5716,7 +5724,7 @@ msgstr "" "hesapladığını bulmak için REA kullanın. Hesaplamayı açıklayın ve kodu " "gösterin.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5728,7 +5736,7 @@ msgstr "" " olduğunuz başka bir küçük Windows programı hakkında aynı tür soruları " "sorun." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Bir dosyanın tam yolunu nasıl alabilirim?" @@ -5737,7 +5745,7 @@ msgstr "Bir dosyanın tam yolunu nasıl alabilirim?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5752,7 +5760,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5764,7 +5772,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5774,17 +5782,17 @@ msgstr "" "{ph0}Herhangi bir sistem:{ph1} dosyayı bir terminal penceresine sürükleyin " "ve yolu görünür." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "REA sonuçlarını okuyun" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Girişi oku" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5793,13 +5801,13 @@ msgstr "" "Talimatlar bir tamsayı argümanı yükler ve kayan nokta aritmetiği için " "dönüştürür. Bu, ilk sözde kod görünümünde bulunmayan girdidir." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Arayanı takip et" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5809,12 +5817,12 @@ msgstr "" "REA, tuğlaya çarpan arayanı tanımlar. Önceki talimatları döşeme koordinatını" " 30 ile çarpar; {ph0} (20) eklemek tuğlanın ekran konumunu verir." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Başvurulan sabitleri okuyun" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5823,12 +5831,12 @@ msgstr "" "Aritmetik bu adreslere başvurur. Baytları okumak gerçek değerleri sağlar; " "talimat sırası aracıya bunların nasıl kullanıldığını söyler." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Kurtarılan işlevi yazın ve kontrol edin" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5839,7 +5847,7 @@ msgstr "" "-500, 0 ve 500 ile eşleşir. Hesaplama, ekranın merkezini stereo alanın " "ortasına yerleştirir." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5852,20 +5860,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Tüm inceleme ve assembly-to-C karşılaştırmasına bakın{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Kendi ikili dosyanızla deneyin" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5879,7 +5887,7 @@ msgstr "" "araştırılacak bir özellik verin. Faydalı başlangıç soruları arasında \"Bu " "dosya nasıl ayrıştırılır?\" veya \"Bu menü eylemini hangi işlev işler?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5888,13 +5896,13 @@ msgstr "" "Bir işlev adını veya adresini zaten biliyorsanız, bunu terminalden " "sorgulayabilirsiniz. Yapılandırılmış bir Ghidra kurulumu için:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Fonksiyon analizi" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5908,7 +5916,7 @@ msgstr "" "kapatır. Aracınızın MCP sorguları, oturum açıkken içe aktarılan ikili " "dosyayı yeniden kullanır." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5932,50 +5940,50 @@ msgstr "" "REA ile yerel bir hesaplamayı kurtarın: talimatları inceleyin, bir arayanı " "takip edin, sabitleri okuyun ve yeniden yapılandırılmış C'yi kontrol edin." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Makine kodu programlarının analizi" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Örnek istemi kopyala" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Kopyalama işlevi analizi" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "İçeriğe geç" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "REA'YU ayarlama" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5983,7 +5991,7 @@ msgstr "{ph0}REA'YU ayarlama{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5991,7 +5999,7 @@ msgstr "{ph0}RE nedir?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5999,7 +6007,7 @@ msgstr "{ph0}REA nasıl yardımcı olur?{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6007,7 +6015,7 @@ msgstr "{ph0}Dinozor oyunu{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6015,7 +6023,7 @@ msgstr "{ph0}Hesap makinesi{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6023,7 +6031,7 @@ msgstr "{ph0}REA'YU deneyin{ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6031,7 +6039,7 @@ msgstr "{ph0}Daha derine inin{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6039,25 +6047,25 @@ msgstr "{ph0}Yardım ve geri bildirim{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Topluluk{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Kodlama aracınızla tersine mühendislik" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Yazılımın nasıl{ph0}çalıştığını öğrenin." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6068,7 +6076,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6076,13 +6084,13 @@ msgstr "RE'Yİ zaten biliyor musun? {ph0}Analiz kılavuzlarına atla →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Daha derine inmek ister misin? {ph0}Blogu Oku →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Bu istemi kodlama ajanınıza yapıştırın:" @@ -6095,39 +6103,39 @@ msgstr "Bu istemi kodlama ajanınıza yapıştırın:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Kopyala" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Ya da terminalde şu komutu çalıştırın:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "" "Kurulum planını inceleyip onaylayın, ardından ajanınızı yeniden başlatın." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Tersine mühendislik nedir?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6142,7 +6150,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6154,7 +6162,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6162,7 +6170,7 @@ msgstr "REA’dan önce · {ph0}Kendiniz{ph1} araştırırsınız" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6170,7 +6178,7 @@ msgstr "{ph0}01{ph1} Dalları çöz" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6178,7 +6186,7 @@ msgstr "{ph0}02{ph1} İzleme çağrıları" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6188,20 +6196,20 @@ msgstr "{ph0}03{ph1} Kuralı kurtar" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Orijinal x64 * seçilen talimatlar{ph1}{ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * Hangi şube?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6210,29 +6218,29 @@ msgid "" msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Aynı yere iki atlayış. Bunlar hangi operatörler?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Komut kimliklerine bakın, ardından dalı etiketleyin." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Böl ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Çarpın ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Çağrılan işlevler ne yapıyor?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6242,24 +6250,24 @@ msgstr "" "“100 açıktır. Aramalar sadece adres. {ph0}Hangisi bölünüyor? Hangi değer " "giriyor?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Yardımcı işlevleri inceleyin ve depolanan değerleri izleyin." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Bölmek" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * Kural nedir?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6269,19 +6277,19 @@ msgstr "" "\"Bu yol diğer girdiyle çarpılır. Yani% 10, + 'dan sonra {ph0}200'ün% 10'u " "anlamına{ph1} gelir.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "İşlenenleri adlandırın ve her iki operatör yolunu da kontrol edin." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Açıklayıcı uzman akıl yürütme" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6293,20 +6301,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "REA ile · {ph0}Ajanınıza{ph1} sorarsınız" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Tek bir istem." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6320,43 +6328,43 @@ msgstr "Ajanınıza {ph0}günlük dille{ph1} sorun." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Örnek bilgi istemi * Hesap Makinesi" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Örnek cevap · bulgulara dayanarak" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "+ 'Dan sonra, % düğmesi {ph0}ilk sayının bir yüzdesini alır.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA’nın sağladıkları" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "İşleyicinin talimatları, derlenmiş kod ve çağrılar." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Ajanınızın açıklaması" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "" @@ -6364,7 +6372,7 @@ msgstr "" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6376,7 +6384,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6386,37 +6394,37 @@ msgstr "" "{ph0}İki örnek deneyelim.{ph1} Bir oyunun hızını değiştirin, ardından Hesap " "Makinesine dönün ve% düğmesini yeniden oluşturun." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Örnek 01 * Chrome'nun dinozor oyunu" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Dinozor neden hızlanıyor?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Hedef" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Oyunu {ph0}ayarlanabilir hızda yeniden oluşturun.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Neden tersine mühendislik?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6426,49 +6434,49 @@ msgstr "" "İvmesini yeniden üretmek için {ph0}koşu oyununda kurala{ph1} ihtiyacımız " "var: ne kadar hızlı başladığı, ne kadar arttığı ve ne zaman durduğu." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Yeniden oluşturulan oyunu oyna" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Oyna" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Zıpla ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Yeniden başlat" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Hız" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Kurtarılan hızlanma kuralını kullanın" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Orijinal kural: 6'dan başlayın, ardından 13'e doğru artırın." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Kendi hızınızı ayarlamak için kaydırıcıyı hareket ettirin. Boşluk veya " "Atlama bir kaktüsü temizler." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6477,14 +6485,14 @@ msgstr "" "Yeniden yapılandırmayı oynatmak için JavaScript'YU etkinleştirin. Yukarıdaki" " kod ve açıklama okunabilir durumda kalır." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA’nın döndürdüğü sonuç" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6502,7 +6510,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6514,7 +6522,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Örnek istemi * Dinozor oyunu" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6528,7 +6536,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6542,7 +6550,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6552,12 +6560,12 @@ msgstr "" "{ph0}6'dan başla.{ph1} Hız {ph2}13{ph3}'ün altındayken çarpışma olmadan her " "güncellemeye {ph4}0,001{ph5} ekleyin." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Hız laboratuvarını açın" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Her bölüm ne yapar" @@ -6568,7 +6576,7 @@ msgstr "Her bölüm ne yapar" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6584,7 +6592,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6601,7 +6609,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6611,13 +6619,13 @@ msgstr "" "{ph0}03 *{ph1}{ph2} Hızı değiştirir ve oynarsınız{ph3}{ph4} Orijinal ivmeyi " "deneyin, ardından kendi hızınızı seçin.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Komut dosyasına, kontrollere ve analizin nasıl deneneceğine bakın" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6627,7 +6635,7 @@ msgstr "" "REA, HTTP tarayıcı sürümünü yerel bir hata ayıklama bağlantısı aracılığıyla " "denetledi ve yüklenen {ph0}, kaynağı ve özeti dahil." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6641,7 +6649,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6657,7 +6665,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6675,7 +6683,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6683,19 +6691,19 @@ msgid "" msgstr "" "{ph0}Denetlenen hız kodu{ph1} * {ph2}Chromium Yazarları · BSD lisansı{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Örnek 02 * Windows Hesap Makinesi" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Hesap Makinesi’nin % düğmesini yeniden oluşturun." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6706,7 +6714,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6716,29 +6724,29 @@ msgstr "" "Aynı düğme {ph0}+ ve × 'den sonra farklı kurallar kullanır.{ph1} Yüzdenin " "hangi sayıya uygulandığını bulmak için yüklü uygulamayı inceliyoruz." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Hesaplamayı deneyin" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Sıfırla" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "200'ün% 10'u = 20. Sonra 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Denetlenen yüzde kuralının etkileşimli gösterimi." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6750,7 +6758,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6764,7 +6772,7 @@ msgstr "Bu örnek için {ph0} ve {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6780,7 +6788,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6792,7 +6800,7 @@ msgstr "" "kullanın. Kuralları + ve × 'den sonra kurtarın, ardından her ikisini de " "kullanan küçük bir hesap makinesi oluşturun.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "İle +" @@ -6800,13 +6808,13 @@ msgstr "İle +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}İlk sayının% 10'unu alın.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "İle ×" @@ -6814,13 +6822,13 @@ msgstr "İle ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}% 10'u 0.1.200 × 0.1 = 20'ye çevirin{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Yüklü uygulamadan çalışan bir% düğmesine" @@ -6832,7 +6840,7 @@ msgstr "Yüklü uygulamadan çalışan bir% düğmesine" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6850,7 +6858,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6862,12 +6870,12 @@ msgstr "" "çoğaltın{ph3}{ph4} Dalı Microsoft'un kaynağıyla çapraz kontrol edin, " "ardından + ve × üstünü deneyin.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Gerçek kodu ve cevabın nasıl kontrol edildiğini görün" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6888,7 +6896,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6898,17 +6906,17 @@ msgstr "" "{ph0}Yüzde uygulaması{ph1} * {ph2}Microsoft'un test durumları{ph3} * " "{ph4}Yerel kurulum kılavuzu{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "İlk soruşturmanız" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Küçük bir uygulamada REA'yu deneyin." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6917,12 +6925,12 @@ msgstr "" "Notlar örneğimizi indirin, CSV dışa aktarımını izleyin ve değiştirilen bir " "girişi kontrol edin." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Kılavuzlu örneği deneyin" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Daha derine inmek ister misiniz?" @@ -6931,7 +6939,7 @@ msgstr "Daha derine inmek ister misiniz?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6952,14 +6960,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Örnek bilgi istemi * Web sitesi" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Evet, bu." @@ -6972,7 +6980,7 @@ msgstr "Evet, bu." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6986,7 +6994,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7000,23 +7008,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}DX-Ball örnek olay incelemesine bakın →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Kurulum ve analiz adımları için hedefinizi seçin:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Makine kodu programları" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7025,17 +7033,17 @@ msgstr "" "Yürütülebilir dosyalar ve kitaplıklardaki işlevleri, dizeleri, referansları " "ve işlev çağrısı ilişkilerini inceleyin." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Makine kodu programlarının analizi kılavuzu" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript VE Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7044,17 +7052,17 @@ msgstr "" "Modülleri, rotaları, ıpc'yi ve yerel bağımlılıkları bir uygulama klasöründen" " veya ASAR arşivinden eşleyin." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Uygulama iş akışları" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Tarayıcı ve çalışma zamanı etkinliği" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7063,12 +7071,12 @@ msgstr "" "Seçilen tarayıcıyı veya işlem etkinliğini yakalayın, ardından sonuçları " "koşular arasında karşılaştırın." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Tarayıcı gözlem kılavuzu" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Sorunuz var mı?" @@ -7079,7 +7087,7 @@ msgstr "Sorunuz var mı?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7089,12 +7097,12 @@ msgstr "" "{ph0}Sss'yi okuyun{ph1}, Discord'DA {ph2}bizimle sohbet{ph3} edin veya " "hatalar ve özellik istekleri için {ph4}bir GitHub sorunu açın{ph5}." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Topluluğa katıl" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7118,27 +7126,27 @@ msgstr "" "tersine mühendislik yapın. Net kılavuzları izleyin ve REA ile etkileşimli " "örnekleri deneyin." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "REA kurulum istemini kopyalayın" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Kurulum komutunu kopyala" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Manuel Hesap Makinesi analizini takip edin" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Hesap Makinesi yüzdesi sorusunu kopyala" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7147,37 +7155,37 @@ msgstr "" "Dinozor mini oyunu. Oyun odaklanırken Atlama düğmesini kullanın veya Boşluk " "tuşuna basın." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Dinozor analizi istemini kopyala" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Hesaplamayı seçin" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Hesap makinesi analiz istemini kopyala" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Web sitesi proje istemini kopyala" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Oyun yeniden yapılandırma istemini kopyala" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -7186,25 +7194,25 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Anasayfa{ph1} / {ph2}Vitrinler{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Örnek olay incelemesi * Aegis Kimlik Doğrulayıcı" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Bir kimlik doğrulayıcı nasıl çalışır{ph0}bir giriş kodu oluşturun?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7214,17 +7222,17 @@ msgstr "" "APK'da bulmak için REA kullanın, ardından kontrol edebileceğiniz bir saatle " "yeniden oluşturun." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * Resmi sürüm APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Aegis'YU GitHub'DA görüntüleyin" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Bir APK'DAN yeniden oluşturabileceğiniz bir koda" @@ -7235,7 +7243,7 @@ msgstr "Bir APK'DAN yeniden oluşturabileceğiniz bir koda" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7253,7 +7261,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7271,7 +7279,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7283,14 +7291,14 @@ msgstr "" "dikkat et.{ph3}{ph4}Yeni bir tarayıcı demosu kuralı yeniden üretir ve genel " "referans durumlarına karşı kontrol eder.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "Bu vaka çalışmasında" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7298,7 +7306,7 @@ msgstr "{ph0}Temsilcinize sorun{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7306,7 +7314,7 @@ msgstr "{ph0}Kod oluşturucuyu deneyin{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7314,7 +7322,7 @@ msgstr "{ph0}Kodu REA ile bulun{ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7322,7 +7330,7 @@ msgstr "{ph0}Hesaplamayı okuyun{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7330,20 +7338,20 @@ msgstr "{ph0}Yeniden yapılanmayı kontrol edin{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}APK'YU kendiniz inceleyin{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Temsilcinize sorun" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7361,21 +7369,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Kopyala" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7385,14 +7393,14 @@ msgstr "" "REA'NUN Android analizi yapılandırılmış olarak indirilen APK için bir örnek " "istemi. APK {ph0}ve analiz kurulumunu edinin ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Kod oluşturucuyu deneyin" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7404,33 +7412,33 @@ msgstr "" " oluşturmak için blok numarasını hesap anahtarıyla birleştirir. Aynı anahtar" " ve blok aynı kodu üretir." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Saati 60 saniye boyunca hareket ettirin" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Zaman" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "saniyeler" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Ayarlanabilir örnek saatimiz" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30 saniyelik blok" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Engel" @@ -7439,35 +7447,35 @@ msgstr "Engel" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 saniye{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Oluşturulan kod" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Hesap anahtarı + blok → altı basamak" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Örnek zaman, saniye cinsinden" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 saniye" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 saniye" @@ -7476,7 +7484,7 @@ msgstr "60 saniye" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7488,7 +7496,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7498,7 +7506,7 @@ msgstr "" "Anahtar sabit, genel {ph0}RFC 6238 test verileridir{ph1}. Demo, APK'dan " "kurtarılan hesaplamayı uygular." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7507,18 +7515,18 @@ msgstr "" "Diyagram sonucu 59 saniyede göstermektedir. Saati değiştirmek için " "JavaScript'YU etkinleştirin." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Kodu REA ile bulun" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "APK'YU üç sınıfa daraltın" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7528,14 +7536,14 @@ msgstr "" "{ph0} hesaplama adayıdır; diğer ikisi ilerleme çubuğu ve içe aktarılan " "hesaplarla ilgilidir. TOTP, zamana dayalı bir kerelik şifre anlamına gelir." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Jeneratörü uygulamanın ekranına bağlayın" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7547,7 +7555,7 @@ msgstr "" "çağıran ekranı {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7557,14 +7565,14 @@ msgstr "" "İstekler kısaltılmış bir giriş yolu gösterir. Sonuç sınıfı adları ortak " "{ph0} öneki." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Hesaplamayı okuyun" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7578,7 +7586,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7586,7 +7594,7 @@ msgstr "{ph0}01{ph1} Zaman bloğu" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7594,7 +7602,7 @@ msgstr "{ph0}02{ph1} Anahtar + blok" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7602,7 +7610,7 @@ msgstr "{ph0}03{ph1} Altı basamak" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7614,7 +7622,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7628,7 +7636,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7642,7 +7650,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7652,7 +7660,7 @@ msgstr "" "Ekran için çizgi sarma ile çeşitli denetlenen yöntemlerden alıntılar. Sağ " "panel açıklayıcı bir özettir. {ph0}Aegis kodu GPL-3.0'dır.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Jeneratörün içinde" @@ -7661,7 +7669,7 @@ msgstr "Jeneratörün içinde" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7672,7 +7680,7 @@ msgstr "" " TotpInfo çağrısını {ph2} ve bu gövdeyi döndürür; Orijinal kaynak yardımcı " "hotp'yi {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7689,20 +7697,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Eşleşen sürüm kaynağıyla karşılaştırın{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Yeniden yapılanmayı kontrol edin" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7715,29 +7723,29 @@ msgstr "" " da dahil olmak üzere {ph0}133 test vakasında{ph1} bağımsız bir yeniden " "yapılandırmayla eşleşti." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Örnek zaman" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Altı haneli kod" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 saniye" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 saniye" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7747,17 +7755,17 @@ msgstr "" "Jeneratör ayrıca {ph0}RFC 6238'de yayınlanan altı SHA-1 referans durumuyla " "da eşleşir{ph1}. Tarayıcı uygulamasını bunlara karşı kontrol edin:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Referans kontrollerini çalıştırın" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Demonun hesaplamasını okuyun" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7766,7 +7774,7 @@ msgstr "" "Referans durumlarda sekiz basamak kullanılır. Kontrol ayrıca altı basamaklı " "sonuçlarını da doğrular." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7775,14 +7783,14 @@ msgstr "" "Doğrulama, çıkarılan Java yöntemlerini ve yeni demoyu çalıştırır. Android " "APK statik olarak denetlendi." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "APK'YU kendiniz inceleyin" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7794,7 +7802,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7804,19 +7812,19 @@ msgstr "" "Android analizinin tam bir JDK 17 veya daha yenisine ihtiyacı var. {ph0} " "veya {ph1} ile seçin. Bu durumda JDK 21 kullanıldı." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "" "REA dosyasını sağlayıcı dosyasına yönlendirin ve APK dosyasını inceleyin :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux'NIN sohbeti" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7829,7 +7837,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7839,7 +7847,7 @@ msgstr "" "Sıradaki soru: {ph0}Bir hesap sekiz basamak veya farklı bir zaman aralığı " "kullandığında ne olur?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Kaynaklar" @@ -7855,7 +7863,7 @@ msgstr "Kaynaklar" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7869,13 +7877,13 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}RFC 6238 referans durumları{ph1} * {ph2}Demo test verileri{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7901,37 +7909,37 @@ msgstr "" "hesaplamasını kurtarın ve ayarlanabilir bir saatle yeniden yapılandırmayı " "deneyin." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK örnek olay incelemesi" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Aegis örnek istemini kopyala" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Giriş kodu hesaplamasını takip edin" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "APK denetim komutunu kopyalayın" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -7940,26 +7948,26 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Anasayfa{ph1} / {ph2}Vitrinler{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Örnek olay incelemesi * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Bayrağı bulun{ph0}bir CTF ikilisi." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7969,17 +7977,17 @@ msgstr "" "Küçük bir bayrak denetleyicisini incelemek, kurallarını denklemlere " "dönüştürmek ve orijinal program baskısını REArea'yı{ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "maskeli kareler bayrak denetleyicisi * Kolay * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Orijinal meydan okumayı görüntüle" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Bir ikiliden doğrulanmış bir cevaba" @@ -7990,7 +7998,7 @@ msgstr "Bir ikiliden doğrulanmış bir cevaba" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8008,7 +8016,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8026,7 +8034,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8038,21 +8046,21 @@ msgstr "" "Düzeltin!{ph3}{ph4}Bir Python betiği denklemleri çözer. REA, sonucu kabul " "eden orijinal programı yakalar.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" "Zorluk, Downunderctf'nin resmi deposunda yayınlanan joseph tarafından." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "Bu vaka çalışmasında" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8060,7 +8068,7 @@ msgstr "{ph0}Kontrol kodunu bulun{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8068,7 +8076,7 @@ msgstr "{ph0}Bir maske oku{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8076,7 +8084,7 @@ msgstr "{ph0}Okunabilir koda derleme{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8084,7 +8092,7 @@ msgstr "{ph0}Denklemleri çözün{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8092,20 +8100,20 @@ msgstr "{ph0}Cevabı kontrol et{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Kendin dene{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Kontrol kodunu bulun" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8123,17 +8131,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Kopyala" @@ -8144,7 +8152,7 @@ msgstr "Kopyala" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8156,7 +8164,7 @@ msgstr "" "kullanın. Kontrollerin nasıl çalıştığını açıklayın, ardından cevabı orijinal" " programla doğrulayın.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8166,12 +8174,12 @@ msgstr "" "programlarının sağlayıcısına bağlı bir analizinin yapıldığı örnek bir bilgi " "istemi." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "İşlevine giriş istemini takip edin" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8180,14 +8188,14 @@ msgstr "" "Başvuru, yürütülebilir dosyanın özgün işlev adları kaldırılmış olsa bile " "aracıya araştırılacak bir yer verir." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Denetleyiciyi ve iki yardımcısını okuyun" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8199,7 +8207,7 @@ msgstr "" "çözer, seçilen kodları toplar ve sonucu saklanan bir sayı ile karşılaştırır." " 0x270 bayttaki {ph0}0x18{ph1} baytlık adımları 26 maske verir." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8208,12 +8216,12 @@ msgstr "" "Bunlar, yeni bir REA analizinden seçilen sonuçlardır. Yerel hedef yol " "görüntüleme için kısaltılmıştır; adresler REA içe aktarılan görüntüsü." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Bir kontrol bir karakteri ortaya çıkarır" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8226,13 +8234,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "Yedinci kontrol sadece bir pozisyon seçer. {ph0}Açık rakam{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Maskeyi ve hedefini ikiliden okuyun" @@ -8241,7 +8249,7 @@ msgstr "Maskeyi ve hedefini ikiliden okuyun" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8253,12 +8261,12 @@ msgstr "" "{ph1} -21 anlamına gelir. Hedef küçük endian bir tamsayıdır. Birlikte, bu " "baytlar aracıya {ph2}55{ph3} olduğunu söyler, böylece karakter 7olur." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Talimatlardan okunabilir bir kontrole" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8269,7 +8277,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8277,7 +8285,7 @@ msgstr "{ph0}01{ph1} Başlangıç" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8285,7 +8293,7 @@ msgstr "{ph0}02{ph1} Seçiniz" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8293,7 +8301,7 @@ msgstr "{ph0}03{ph1} Ekle" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8301,18 +8309,18 @@ msgstr "{ph0}04{ph1} Peşin" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Karşılaştır" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * seçilen orijinal talimatlar" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Okunabilir C * tek kontrol özeti" @@ -8320,7 +8328,7 @@ msgstr "Okunabilir C * tek kontrol özeti" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8328,7 +8336,7 @@ msgstr "{ph0}01 * Sıfırdan başlayın.{ph1} {ph2} çalışan toplamı tutar." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8340,7 +8348,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8352,7 +8360,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8366,7 +8374,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8376,7 +8384,7 @@ msgstr "" "{ph0}05 * Saklanan hedefle karşılaştırın.{ph1} Arayan, toplamı {ph2} " "cinsinden alır. Bir uyumsuzluk {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8385,12 +8393,12 @@ msgstr "" "Talimatlar toplama yardımcısından ve arayanından gelir. C, açıklayıcı adlara" " ve düzleştirilmiş 36 hücreli bir döngüye sahip açıklayıcı bir özettir." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "26 Denklemi çözün" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8401,13 +8409,13 @@ msgstr "" "ve toplam 1441 gerektirir. Örtüşen seçimler, küçük bir Python betiğinin " "birlikte çözebileceği denklemler verir." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * çözücü alıntı" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8420,19 +8428,19 @@ msgstr "" "çıkarılan çekleri kullanır ve harf, rakam, alt çizgi ve parantez içeren bir " "{ph0} bayrağı varsayar. Tam indirme, 26 maskenin ve hedefin tümünü içerir." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Tam çözücüyü indirin" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Cevabı orijinal programla kontrol edin" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8444,47 +8452,47 @@ msgstr "" "dosyayı kaydeder. Seçilen bir karakteri {ph0} {ph1} değiştirmek, ilk toplamı" " 1441 yerine 1440 yapar ve program bunu reddeder." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Giriş" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Gözlenen çıktı" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Çıkış kodu" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Çözücünün bayrağı" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Bir karakter değişti" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Kurtarılan bayrağı ve yakalanan çıktıyı göster" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * orijinal program çıktısı" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Bayrağı kopyala" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8494,12 +8502,12 @@ msgstr "" "düzenleyicilerin yayınlanmış meydan okuma meta verilerindeki bayrakla da " "eşleşir." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Kaynak, hedef kimliği ve analiz detayları" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8509,7 +8517,7 @@ msgstr "" "Linux x64'te Ghidra 12.1.4 ile REA 4.1.0 kullanılarak 8 Ekim 2026'da yeni " "analiz ve iki işlem kaydı. İkili, soyulmuş bir x86-64 ELF, 15.248 bayttır." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8532,7 +8540,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8542,12 +8550,12 @@ msgstr "" "{ph0}Organizatörlerin kaynağıyla karşılaştırın{ph1} * {ph2}Meta verilere ve " "bayrağa meydan{ph3} okuyun * {ph4}REA kanıt notları{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Kendin dene" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8557,13 +8565,13 @@ msgstr "" "araştırmak veya birlikte verilen komut dosyasını çalıştırmak için yukarıdaki" " istemi kullanın." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Terminal * çöz ve çalıştır" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8575,7 +8583,7 @@ msgstr "" "Çözmenin Python ve {ph0} ihtiyacı var. Orijinal yürütülebilir dosyayı " "çalıştırmak için Linux x86-64 gerekir." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Kodlama aracınızla REA'YU kurun" @@ -8596,27 +8604,27 @@ msgstr "" "kullanın. Kontrol işlevlerini bulun, maskeleri çıkarın ve kurtarılan bir " "bayrağı orijinal programla karşılaştırın." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTF bayrak denetleyicisi vaka çalışması" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "CTF örnek istemini kopyala" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "CTF maskesi denklemi; daha küçük ekranlarda yatay kaydırma" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8627,42 +8635,42 @@ msgstr "" "Sadece bu hücre toplamına katkıda bulunur. Gerekli karakter kodu 55'tir, " "yani karakter 7'dir." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "CTF kontrolünü takip edin" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "CTF derlemesini kopyala" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Okunabilir CTF kontrolünü kopyala" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "CTF çözücü alıntısını kopyala" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Kurtarılan bayrağı kopyala" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "CTF çözücü komutlarını kopyala" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -8671,25 +8679,25 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Anasayfa{ph1} / {ph2}Vitrinler{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Örnek olay incelemesi * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "DX-Ball'YU yeniden oluşturma {ph0}yürütülebilir dosyasından." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8698,14 +8706,14 @@ msgstr "" "Amaç, 1996 Windows oyununun sürdürülebilir bir C versiyonudur. REA, " "acentenin orijinali, her seferinde bir işlevi incelemesine yardımcı olur." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows ı386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8716,14 +8724,14 @@ msgstr "" "REA talimatları, arayanları ve veri okumalarını sağlar; yeniden yapılandırma" " projesi sonucu uygular ve test eder. {ph0}Açık şekil{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "Bu vaka çalışmasında" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8731,7 +8739,7 @@ msgstr "{ph0}Proje{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8739,7 +8747,7 @@ msgstr "{ph0}Ses tavası{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8747,23 +8755,23 @@ msgstr "{ph0}Sonucu kontrol etme{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Çalışmaya devam et{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "tutulan C fonksiyonları" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "orijinal kodla karşılaştırmalar" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "eşleşen derlenmiş baytlara sahip işlevler" @@ -8774,7 +8782,7 @@ msgstr "eşleşen derlenmiş baytlara sahip işlevler" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8784,12 +8792,12 @@ msgstr "" "Proje kontrol noktası: 7 Ekim 2026. {ph0}İlerleme defteri{ph1} * {ph2}Test " "kapsamı{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Proje şu ana kadar" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8804,12 +8812,12 @@ msgstr "" "çalışmalar top ve kürek fiziği, güçlendirme kullanımı ve Windows " "entegrasyonu ile devam ediyor." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Sol / sağ ses konumunun hesaplanmasını bulma" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8828,17 +8836,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Kopyala" @@ -8849,7 +8857,7 @@ msgstr "Kopyala" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8860,7 +8868,7 @@ msgstr "" "hesapladığını bulmak için REA kullanın. Hesaplamayı açıklayın ve kodu " "gösterin.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8871,7 +8879,7 @@ msgstr "" " istemi. Aşağıdaki araştırma, REA sorgularını ve cevabın arkasındaki " "kanıtları göstermektedir." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8885,7 +8893,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8899,12 +8907,12 @@ msgstr "" "kayan nokta işlemleri gösterdi. Bu tutarsızlık, ajana araştırmaya devam " "etmesi için somut bir neden verdi." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "İlk decompiler görünümü" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8913,18 +8921,18 @@ msgstr "" "Çıktı bir dönüşüm çağrısı gösterir. Aşağıdaki talimatları okumak, o çağrıyı " "besleyen girdiyi ve hesaplamayı ortaya çıkarır." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "REA aracılığıyla yanıtlanan üç soru" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Eksik girdiyi kurtar" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8934,14 +8942,14 @@ msgstr "" "İşlev sonucu, sahte kod ve arayanların yanı sıra talimatları içerir. Burada," " {ph0} kod çözücü görünümünde eksik olan tamsayı girdisini gösterir." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Girişi anlamak için arayanı takip edin" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8951,12 +8959,12 @@ msgstr "" "REA bu arayanı ilk sonuçta tanımladı. Önceki talimatları {ph0}tile_x'i 30'a " "ölçeklendirir; 20 eklemek tuğlanın ekran koordinatını verir, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Bellek adreslerinin arkasındaki değerleri okuyun" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -8965,12 +8973,12 @@ msgstr "" "Döndürülen baytlar, iki aritmetik sabiti ve ilk kaydırma ölçeğini oluşturur." " Aracı artık C ifadesi için gereken değerlere sahiptir." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "REA'NUN bulgularından C'ye" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8981,7 +8989,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8989,7 +8997,7 @@ msgstr "{ph0}01{ph1} Giriş" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8997,7 +9005,7 @@ msgstr "{ph0}02{ph1} Çarpın" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9005,7 +9013,7 @@ msgstr "{ph0}03{ph1} Çıkar" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9013,18 +9021,18 @@ msgstr "{ph0}04{ph1} Ölçek" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Dönüş" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Orijinal x86 * alıntı" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Yeniden inşa edilmiş C" @@ -9034,7 +9042,7 @@ msgstr "Yeniden inşa edilmiş C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9053,7 +9061,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9070,7 +9078,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9088,7 +9096,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9106,7 +9114,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9118,7 +9126,7 @@ msgstr "" "sonuçlar. C sonucu {ph4} atar; original-x86 karşılaştırmaları döndürülen " "değeri kontrol eder." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9129,23 +9137,23 @@ msgstr "" "tam liste, araya giren depoları ve işlev kurulumunu ve temizlemeyi de " "içerir." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Tam montaj ve destekleyici kanıtlar" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA sonucu * 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Arayan ne sağlar" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9155,54 +9163,54 @@ msgstr "" "0x411f40 değerindeki tuğla çarpma işlevi{ph0}, döşeme koordinatını 30 " "ölçeklendirir, 20 ekler ve ardından çağrıdan önce iter:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Verilerin okuduğu şey" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA bayt okur, küçük uçlu çiftler olarak çözülür" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Adres" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Değer" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "İçin kullanılır" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "İlk çarpma" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Çıkarma" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} başlangıçta" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Saklanan pan ölçeği" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9218,7 +9226,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9228,12 +9236,12 @@ msgstr "" "{ph0}Tutulan kaynak{ph1} * {ph2}Soruşturma notları ve kanıt " "referansları{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Kurtarılan işlevi kontrol etme" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9242,12 +9250,12 @@ msgstr "" "Kurtarılan işlev iki denetimden geçer: dönüş değerleri orijinaliyle eşleşir " "ve derlenmiş baytları yürütülebilir dosyayla eşleşir." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 davranış vakası" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9258,12 +9266,12 @@ msgstr "" "karşılaştırır. 0, 0,5, 1, 20 ve -1 olmak üzere beş kaydırma ölçeğinde 0'dan " "640'a kadar olan her tamsayı konumunu kapsar." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 eşleşen bayt" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9274,7 +9282,7 @@ msgstr "" "gözden geçirilen yer değiştirmeleri uyguladıktan ve başvurulan sabitleri " "kontrol ettikten sonra tam işlevle eşleşir." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9289,18 +9297,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Derleyici tekrar ayrıntılarını okuyun{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Soruşturmaya devam et" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9311,7 +9319,7 @@ msgstr "" "için de kullanılıyor: ilgili işlevleri inceleyin, durumlarını ve " "bağımlılıklarını kurtarın, ardından uygulamayı orijinaliyle karşılaştırın." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9320,7 +9328,7 @@ msgstr "" "Ses kaydırma işlevini kendiniz incelemek için DX-Ball projesinin kurulum " "talimatlarını izleyin ve eşleşen orijinal hedefini sağlayın. Sonra koş:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "DX-Ball kasasında" @@ -9329,7 +9337,7 @@ msgstr "DX-Ball kasasında" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9342,7 +9350,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9358,7 +9366,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9383,13 +9391,13 @@ msgstr "" "derlenmiş işlev baytlarının eşleşmesine kadar bir DX-Ball yeniden " "yapılandırmasını izleyin." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ball ses kaydırma incelemesi; daha küçük ekranlarda yatay kaydırma" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9404,70 +9412,70 @@ msgstr "" "3.205 durumda orijinal x86'ya karşı bağımsız olarak ve 63 baytla eşleşen " "VC4.0 derleyici tekrarı ile kontrol edilir." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball rekonstrüksiyon vaka çalışması" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Örnek istemi kopyala" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Sol / sağ ses konumunun hesaplanmasını takip edin" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Orijinal derleme alıntısını kopyala" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Sesi kopyala-kaydırma işlevi" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Tam ses kaydırma düzeneğini kopyalayın" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "DX-Ball analiz komutunu kopyalayın" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "İçeriğe geç" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Anasayfa{ph1} / Vitrinler" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA vaka çalışmaları." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9476,17 +9484,17 @@ msgstr "" "Android, oyunlar, Electron ve kod, rakamlar ve kontrol edilen sonuçlarla CTF" " mücadelesi." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * APK analizi" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Bir kimlik doğrulayıcı oturum açma kodunu nasıl oluşturur?" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9497,22 +9505,22 @@ msgstr "" "Oluşturma yöntemlerini REA ile izleyin, ardından kodun neden her 30 saniyede" " bir değiştiğini görmek için bir demo saatini hareket ettirin." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Android vaka çalışmasını okuyun" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Makine kodu programlarının analizi" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "CTF bayrak denetleyicisini çözme" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9523,22 +9531,22 @@ msgstr "" "bulun, maskeleri ve toplamları denklemlere dönüştürün, ardından çözülen " "bayrağı orijinal programla doğrulayın." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "CTF vaka çalışmasını okuyun" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Yerli * Yeniden Yapılanma" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball'NUN sol / sağ ses pozisyonunun hesaplanması" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9550,22 +9558,22 @@ msgstr "" "derlenmiş 63 baytın tümüne karşı kontrol edilen küçük bir C işlevine yol " "açar." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "DX-Ball örnek olay incelemesini okuyun" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Özellik izleme" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Notion metni ve HTML'yi nasıl kopyalar" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9577,22 +9585,22 @@ msgstr "" "işaretleyicisinin zengin blok verilerini bir kopyaya nasıl bağlı tuttuğunu " "görün." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Notion örnek olay incelemesini okuyun" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * Yeniden Yapılandırma" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "TH04 bir mermi halkasını nasıl hedefliyor" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9603,17 +9611,17 @@ msgstr "" "koordinat işlemlerini okunabilir C ++ ile eşleştirin, ardından oynatıcıya " "yönelik bir halkayı nasıl ürettiklerini görün." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "TH04 örnek olay incelemesini okuyun" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Adım adım kılavuzlar" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9622,7 +9630,7 @@ msgstr "" "Kılavuzlar yerel bir hesaplama, bir Electron dışa aktarma ve bir tarayıcı " "isteğinden geçer. Her biri bir bilgi istemi ve somut bir hedefle başlar." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Kılavuzları okuyun" @@ -9642,12 +9650,12 @@ msgstr "" "Android kimlik doğrulayıcı, DX-Ball, Notion, TH04 ve bir DownUnderCTF bayrak" " denetleyicisi." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -9656,25 +9664,25 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Anasayfa{ph1} / {ph2}Vitrinler{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Örnek olay incelemesi * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Notion nasıl kopyalanır{ph0}metin ve HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9683,12 +9691,12 @@ msgstr "" "Bir pano çağrısını izleyin Notion 's sayfa API'sı, ön yükleme ve ana işlem " "aracılığıyla Electron 's pano yazıcısı." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Masaüstü 7.6.1 · JavaScript * REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Notion'NUN masaüstü paketinin içindeki köprü" @@ -9700,7 +9708,7 @@ msgstr "Notion'NUN masaüstü paketinin içindeki köprü" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9717,7 +9725,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9734,7 +9742,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9751,7 +9759,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9762,13 +9770,13 @@ msgstr "" "sağlanan metni ve HTML'yi yazar.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Bir kanal iki tarafa katılır: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9778,14 +9786,14 @@ msgstr "" "Sarmalayıcıların çözülmesi, bu adların arkasındaki Electron çağrılarını " "ortaya çıkarır." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "Bu vaka çalışmasında" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9793,7 +9801,7 @@ msgstr "{ph0}Pano köprüsünü takip edin{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9801,19 +9809,19 @@ msgstr "{ph0}Bir bloğun yapısını korumak{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Daha fazla örnek ve kaynak{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Kopyalama işlemi nereye gidiyor?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9832,17 +9840,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Kopyala" @@ -9853,7 +9861,7 @@ msgstr "Kopyala" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9864,7 +9872,7 @@ msgstr "" "kopyaladığını izlemek için REA kullanın. Her adımda kodu " "gösterin.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9873,12 +9881,12 @@ msgstr "" "Kodlama aracınız tarafından kullanılabilen Notion'NUN yerel uygulama " "paketine sahip örnek bir komut istemi." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA okumaya nereden başlayacağınızı bulur" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9889,13 +9897,13 @@ msgstr "" "IPC isteği gönderen çağrıyı bulur. Her iki bulgu da küçültülmüş paketteki " "kaynak aralıklarıyla birlikte gelir:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA bulguları → açılacak iki yer" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9909,7 +9917,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9923,12 +9931,12 @@ msgstr "" "pakette araması gereken kesin bir şey verir. Aşağıdaki dört alıntı, " "bağlandığı rotayı göstermektedir." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Dört kısa kod parçası" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9937,13 +9945,13 @@ msgstr "" "Okunabilir değişken adlarıyla paketlenmiş JavaScript'DAN " "basitleştirilmiştir. İlgisiz üyeler atlanır." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Sayfaya maruz kalan apı'den başlayın" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9953,13 +9961,13 @@ msgstr "" "Bu üye kanal adını sağlar. ınvokerInMain uygulaması, isteğin sayfanın " "sürecinden nasıl ayrıldığını {ph0} anlatır." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Önyüklemenin sarmalayıcısını çözme" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9969,14 +9977,14 @@ msgstr "" "Döndürülen işlev, bağımsız değişkenleri Electron istek ve yanıt IPC'Sİ " "aracılığıyla iletir. Artık ana işlem tarafında {ph0} arayabiliriz." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Alıcının nasıl kaydedildiğini kontrol edin" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9986,12 +9994,12 @@ msgstr "" "Ana işlem başka bir sarmalayıcı kullanır. {ph0} yöntemi bir ıpcMain " "kaydeder{ph1}." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Yazıyı ve gönderen kontrolünü bulun" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10002,13 +10010,13 @@ msgstr "" "verileri Electron pano API'sı. Kanal ve çözümlenen iki sarmalayıcı, açıkta " "kalan yöntemi bu çağrıya bağlar." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Kopyalanan bir blok yapısını nasıl korur?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10019,27 +10027,27 @@ msgstr "" "verilerini yerel olarak saklar ve bunları bağlamak için kopyalanan HTML'ye " "bir kimlik koyar." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "Kayıtlı blok verilerine HTML bağlantıları" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "HTML Kimliğini oku" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Aynı yerel kimliği bulun" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Notion blok verilerini geri yükle" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10048,7 +10056,7 @@ msgstr "" "Açıklayıcı metin ve kimlik. Kaydedilen modül testi, kimlikler eşleştiğinde " "blok verilerini geri yükler; eski bir girdi yalnızca metin ve HTML döndürür." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10057,24 +10065,24 @@ msgstr "" "Yapıştırmada, Notion HTML kimliğini arar ve kaydedilen kopyaya karşı kontrol" " eder. Eşleşen kimlikler blok verilerini geri yükler." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "13 Temmuz 2026'da önbelleğe alınan web varlıklarından kaydedilen pano " "biçimi." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Daha fazla örnek ve kaynak" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Başka bir örnek: İşaretleme tabloları" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10083,12 +10091,12 @@ msgstr "" "Notion, Markdown'u blok verilerine ayrıştırır. Bu örnek, bir tablonun " "üstbilgi ve veri satırlarına nasıl dönüştüğünü gösterir." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Notion'NUN Markdown ayrıştırıcısı aracılığıyla bir tablo" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10097,13 +10105,13 @@ msgstr "" "Çıkarılan bir Markdown ayrıştırıcısından kaydedilen çıktı. Tablo satırlar ve" " hücreler haline gelir." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Başka bir yol: çevrimdışı SQLite bağlantısı" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10117,7 +10125,7 @@ msgstr "" "diğeri ise bir SQLite yardımcı programı işlemine verir. Sonraki ifade " "grupları ve sonuçları bu bağlantı noktası üzerinden gider." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10126,7 +10134,7 @@ msgstr "" "Bu aktarımın ardından, veritabanı çalışmasının nerede çalıştığı ve yalnızca " "ilk IPC isteğinin izlenmesinin neden sonraki konuşmayı kaçırdığı açıklanır." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Kaynaklar ve alıntıların nasıl okunacağı" @@ -10134,7 +10142,7 @@ msgstr "Kaynaklar ve alıntıların nasıl okunacağı" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10151,7 +10159,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10167,7 +10175,7 @@ msgstr "" "çıkarılan modülleri ve küçük kablo demetlerini çalıştırdı; çıktıları, " "yakalanan bir masaüstü UI oturumundan ziyade bu probları tanımlar." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10181,7 +10189,7 @@ msgstr "" "uygulamalarını okuyarak bağlanır." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10199,7 +10207,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10213,7 +10221,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10239,52 +10247,52 @@ msgstr "" "Notion'NUN pano API'sini kısa kod alıntıları ve zengin pano formatına bir " "bakışla takip edin." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron örnek olay incelemesi" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Notion analiz istemini kopyala" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Notion ön yükleme alıntısını kopyalayın" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Kopyala Notion sarmalayıcı alıntısını çağır" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Notion işleyici sarmalayıcı alıntısını kopyala" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Kopya Notion pano alıcısı alıntı" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Yapıştırmada zengin pano verilerini geri yükleme" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Başa dön" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "İçeriğe geç" @@ -10293,25 +10301,25 @@ msgstr "İçeriğe geç" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Anasayfa{ph1} / {ph2}Vitrinler{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Örnek olay incelemesi * Touhou 4: Lotus Ülkesi Hikayesi" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "TH04'NUN yeniden yapılandırılması{ph0}kurşun izleri." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10321,17 +10329,17 @@ msgstr "" "incelemek için REA kullanın, ardından talimatlarını okunabilir C ++ olarak " "izleyin." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * 16 bit DOS * C ++ ve derleme" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "TH04 rekonstrüksiyonunu görüntüleyin" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Orijinal talimatlardan kontrol edilen kaynağa" @@ -10342,7 +10350,7 @@ msgstr "Orijinal talimatlardan kontrol edilen kaynağa" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10358,7 +10366,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10376,7 +10384,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10392,7 +10400,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10404,7 +10412,7 @@ msgstr "" "bayt{ph3}{ph4} derleyici kontrolleri, bu yardımcıyı içeren madde işareti " "oluşturma kodunu kapsar.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10413,14 +10421,14 @@ msgstr "" "REA, orijinal kodu ve analiz kanıtını döndürür. TH04 projesi, bakımı yapılan" " kaynak ve derleyici denetimlerini sağlar." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "Bu vaka çalışmasında" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10428,7 +10436,7 @@ msgstr "{ph0}Kurşun halkası{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10436,7 +10444,7 @@ msgstr "{ph0}REA ne döndürür{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10444,7 +10452,7 @@ msgstr "{ph0}C ++ 'ya derleme{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10452,18 +10460,18 @@ msgstr "{ph0}Kaynağı kontrol etme{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Projenin tamamı{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Bir yüzük oyuncuya nasıl nişan alır" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10482,16 +10490,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Kodlama aracınız" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Kopyala" @@ -10502,7 +10510,7 @@ msgstr "Kopyala" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10513,7 +10521,7 @@ msgstr "" "oyuncuya nasıl hedeflediğini bulmak için REA kullanın. Hesaplamayı açıklayın" " ve kodu gösterin.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10523,7 +10531,7 @@ msgstr "" "kullanılabildiği örnek bir komut istemi." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10537,7 +10545,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10547,12 +10555,12 @@ msgstr "" "Sayı 16, oyuncu yönü 40 ve şablon dönüşü 0 için kurtarılan açı matematiğinin" " bir örneği. {ph0}Açık şekil{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Kurtarılan kaynaktaki ateşleme şablonu" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Elly'nin halka saldırısı * kaynak alıntı" @@ -10561,7 +10569,7 @@ msgstr "Elly'nin halka saldırısı * kaynak alıntı" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10571,13 +10579,13 @@ msgstr "" "Bu çizgiler, zorluk ve performans ayarından önce deseni seçer. " "{ph0}Saldırının kaynağını okuyun{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "REA ne döndürür" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10589,12 +10597,12 @@ msgstr "" "bullet_velocity_and_angle_set{ph0} REA yönergelerini, sözde kodunu ve " "referanslarını döndürür. Bu sonucun üç kısmı modeli açıklıyor." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Kodunu okumadan önce DOS görüntüsünü kontrol edin" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10603,7 +10611,7 @@ msgstr "" "Kontrol, yüklenen kodu ve yer değiştirme kayıtlarını sağlanan yürütülebilir " "dosyaya bağlar. Yukarıdaki yol görüntüleme için kısaltılmıştır." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Yüzüğün çarpımını ve bölünmesini okuyun" @@ -10611,7 +10619,7 @@ msgstr "Yüzüğün çarpımını ve bölünmesini okuyun" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10622,12 +10630,12 @@ msgstr "" "{ph0} madde işareti dizinini tutar. Vardiya 256 ile çarpar, ardından bölme " "{ph1}. Bullet_template alanı tutulan kaynak {ph2}. Tam sıra aşağıda görünür." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Desenin oyuncuya doğru nereye döndüğünü bulun" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10640,12 +10648,12 @@ msgstr "" "adresleri okunabilir hale getirir; REA, aracının arkalarındaki orijinal " "işlemleri kontrol etmesini sağlar." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Montajdan okunabilir C ++ 'ya" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10658,7 +10666,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10666,7 +10674,7 @@ msgstr "{ph0}01{ph1} Dizin" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10674,7 +10682,7 @@ msgstr "{ph0}02{ph1} Boşluk" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10682,7 +10690,7 @@ msgstr "{ph0}03{ph1} Amaç" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10690,18 +10698,18 @@ msgstr "{ph0}04{ph1} Döndür" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Mağaza" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * orijinal 16 bit talimatlar" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Okunabilir C ++ * hedeflenmiş halka özeti" @@ -10709,7 +10717,7 @@ msgstr "Okunabilir C ++ * hedeflenmiş halka özeti" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10723,7 +10731,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10738,7 +10746,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10753,7 +10761,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10768,7 +10776,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10781,7 +10789,7 @@ msgstr "" "{ph2} yazar. Değerler, tıpkı imzasız bayt dökümünün yaptığı gibi 255'ten " "sonra sarılır. Çevreleyen kaynak da bu açıyı ve hızı hıza dönüştürür." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10792,7 +10800,7 @@ msgstr "" "Yukarıdaki C ++ okunabilir bir özettir. Aşağıdaki derleyici denetimleri, " "bağlantılı projedeki tutulan kaynak için geçerlidir." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Tutulan halkayı okuyun ve kaynağı hedefleyin" @@ -10809,7 +10817,7 @@ msgstr "Tutulan halkayı okuyun ve kaynağı hedefleyin" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10819,12 +10827,12 @@ msgstr "" "{ph0}Halka makro{ph1} * {ph2}Amaç ve hız kaynağı{ph3} * {ph4}Açı " "gösterimi{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Tutulan kaynağı kontrol etme" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10834,12 +10842,12 @@ msgstr "" "zinciri ile bu yardımcı da dahil olmak üzere madde işareti oluşturma kodunu " "derler." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 eşleşen bayt" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10848,12 +10856,12 @@ msgstr "" "Derlenmiş madde işareti oluşturma kodu, özgün yürütülebilir dosyanın 2.139 " "baytlık bir bölümüyle eşleşir." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "İki temiz yapı" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10866,65 +10874,65 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "3 Ekim 2026'da kaydedildi. {ph0}Derleyici denetimlerini okuyun{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Hedef kimlik ve analiz kapsamı" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Orijinal hedef" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156,258 bayt, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Yardımcı giriş" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0}rea'nınREA yüklenen görüntüsünde 0x2cfc8" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Orijinal dosya ofseti" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0} döndürülen {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Kayıtlı kod denetimi" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 Ekim 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10935,7 +10943,7 @@ msgstr "" "değiştirmeyi karşılaştırırlar." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10950,7 +10958,7 @@ msgstr "" " aralıklarda bulunur." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10966,7 +10974,7 @@ msgstr "" "incelemesini ekler. Sağlanan oyunun kimliği, bağımsız bozulmamış döküm " "kaynağı hala açıkken, depo bildirimi tarafından sabitlenir." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10977,12 +10985,12 @@ msgstr "" "PC-98 donanım davranışı, yeniden yapılandırma projesinde ayrı çalışma zamanı" " denetimlerine sahiptir." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "Tam TH04 rekonstrüksiyonu" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10995,7 +11003,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11007,7 +11015,7 @@ msgstr "{ph0}TH04 deposunu keşfedin{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11023,7 +11031,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11039,7 +11047,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11065,22 +11073,22 @@ msgstr "" "nasıl aralıklı ve oyuncuya yönelik olduğunu görmek için montajı ve " "kurtarılan C ++ 'yı takip edin." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Bu sayfada" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 mermi deseni vaka çalışması" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "TH04 örnek istemini kopyala" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11088,7 +11096,7 @@ msgstr "" "TH04 sabit ve hedeflenmiş mermi halkaları; daha küçük ekranlarda yatay " "olarak kaydırın" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11101,27 +11109,27 @@ msgstr "" "mermi oyuncuya işaret eder. Her ikisi de 16 açı birimi veya 22,5 derecelik " "bir aralık tutar." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "TH04 ateşleme şablonunu kopyala" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "TH04 hedefli halka hesaplamasını takip edin" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "TH04 derleme alıntısını kopyalayın" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Okunabilir hedefli halka hesaplamasını kopyala" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Başa dön" @@ -11231,7 +11239,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Sabit hız: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11240,7 +11248,7 @@ msgstr "" "Kurtarılan kuralı tekrar oynattı. Dört değerin tümü, üç ondalık basamağa " "yuvarlandığında kontrol edilen orijinal oyun kontrolüyle eşleşir." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11604,591 +11612,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Aynı aralık: 256 ÷ 16 = 16 açı birimi = 22,5 °" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Örnekler" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Başlangıç" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Rehberler" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Kaynak kod" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "MIT lisansı" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Topluluğa katıl" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "X’te takip et" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * seçilen komut dosyası kaynağı" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Kaynak kod" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Beklenen biçimlendirici çıktısı" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Talimatlar" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Arayan" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Sabitler" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "C işlevi" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Düğme" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "Ön yükleme API'sı" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV dosyası" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Tıklamanız" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Yakalanan istek" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Komut dosyasını dışa aktar" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA sonuç * özet.ıpc'den alıntı" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA talimat alıntısı * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA arayan alıntı * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA bayt sonuçları * küçük endian çiftleri olarak yorumlanır" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Kurtarılan C * alıntı" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "REA’nın nasıl çalıştığını görün ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Vitrinler →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Denetlenen komut dosyasından seçilen ayarlar" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "% işleyicisinin okunabilir özeti" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * seçilen orijinal talimatlar" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Operatör Kimlikleri * Microsoft'un kaynağı" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "X'te @reatools'u takip edin" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Ajan → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → temsilci * seçilen sonuçlar" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → aracı * yöntemler ve arayanlar" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * seçilen derlenmiş Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Okunabilir özet * temsilcinin yorumu" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, komple gövde" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "İndir Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Android analiz sağlayıcısını indirin" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Ajan → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → temsilci * seçilen sonuçlar" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → ajan * seçilen talimatlar" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Aracı → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → aracı * yedinci girişler" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Orijinal çalıştırılabilir * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Orijinal mücadeleyi indirin" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Çözücüyü indirin" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA sonuç * sözde kod alıntısı" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Ajan → REA * {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → ajan * talimat alıntısı" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → temsilci * arayan alıntı" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Aracı → REA * iki {ph0} isteği" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA bayt sonuçları * çiftler olarak deşifre edildi" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Kendi hedefinizle başlayın" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK'NIN sohbeti" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Kod oluşturma" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Kurtarılan kural" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Ayarlanabilir saat" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "İkili" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Kodu kontrol etme" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Denklemler" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Doğru!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Çalıştırılabilir" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA bulguları" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Kurtarılan C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Doğrulama" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Paketlenmiş uygulama" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Açık API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "IPC sarmalayıcıları" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Pano" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Orijinal DOS kodu" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA talimatları" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Açı hesaplaması" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Mermi halkası" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Açık sayfa API'sı" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Oluşturucu IPC çağrısı" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Sistem panosuna gönderildi" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Notion tarafından yerel olarak kaydedildi" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "İşaretleme girişi" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Yapılandırılmış ayrıştırıcı çıktısı * alıntı" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Kendi uygulamanızı analiz edin" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Ajan → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → aracı * seçilen alanlar" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Ajan → REA * {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → ajan * talimat alıntısı" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Aynı işlev sonucu * amaç alıntısı" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "İlgili tutulan C ++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Halka makro * TH04 şubesi, alıntı" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Açı ve hız * kaynak alıntı" @@ -12220,7 +12236,7 @@ msgstr "Çeviri güncelleniyor. Şimdilik bu sayfayı ingilizce olarak okuyun." #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12238,7 +12254,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12259,7 +12275,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12280,7 +12296,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12299,7 +12315,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12318,7 +12334,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12329,14 +12345,14 @@ msgstr "" "için klonla.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Yeniden yapılanma ·{ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12347,7 +12363,7 @@ msgstr "" " önerilen değişiklikleri gözden geçirin." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12356,7 +12372,7 @@ msgstr "Verilen bir örnek * {ph0} ve npm * Kodlama aracınız" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12374,7 +12390,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12389,7 +12405,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12408,7 +12424,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12419,7 +12435,7 @@ msgstr "" "dosyayı yazar.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12434,7 +12450,7 @@ msgstr "{ph0} * satır 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12447,7 +12463,7 @@ msgstr "" " çalıştırın. Tahmini ve gerçek çıktıyı gösterin.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12458,7 +12474,7 @@ msgstr "" "biçimlendiriciyi doğrudan {ph0} ile kontrol eder." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12466,7 +12482,7 @@ msgstr "{ph0} * CSV biçimlendirici" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12476,7 +12492,7 @@ msgstr "" "gelir{ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12484,7 +12500,7 @@ msgstr "{ph0} yok mu, emin değil misiniz?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12497,7 +12513,7 @@ msgstr "" " 24 LT:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12511,7 +12527,7 @@ msgstr "{ph0} * örnek kaynak alıntı" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12520,9 +12536,9 @@ msgid "" msgstr "{ph0}Örneği açın{ph1} * {ph2}İndir {ph3}{ph4}* {ph5}İndir{ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12530,7 +12546,7 @@ msgstr "{ph0} * örnek kaynak" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12544,7 +12560,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12557,7 +12573,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12571,7 +12587,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12582,7 +12598,7 @@ msgstr "" " {ph3}220 veriyor?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12591,7 +12607,7 @@ msgstr "REA * yüklendi {ph0}* seçili satırlar" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12609,7 +12625,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12628,7 +12644,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12641,28 +12657,28 @@ msgstr "" "değiştirebileceğim küçük bir demo yap.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * API üyesi" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * IPC yardımcısı" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "main /{ph0} * işleyici yardımcısı" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12672,12 +12688,1410 @@ msgstr "ana /{ph0} * pano alıcısı" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Başlangıç {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Açık temaya geç" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Koyu temaya geç" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"HTTP istek ve yanıt gövdelerini incelemek için {ph0}Fiddler Everywhere: SAZ " +"kayıtları, MCP ve herkese açık beceriler{ph1} rehberini kullanın. REA ile " +"çevrimdışı kayıt Evidence elde etmek için SAZ veya HAR 1.2 dışa aktarın veya" +" kaydedilen trafiği ajanınızla incelemek için Everywhere MCP sunucusunu " +"bağlayın." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Uzmanlaşmış modeller{ph0}Deneme" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Tersine mühendislik için daha büyük bir model gerekli mi?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Touhou yeniden yapılandırma deneyiminden genel amaçlı modeller, uzmanlaşmış " +"modeller ve derleyici geri bildiriminden öğrenme üzerine düşünceler." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Yazan N0zoM1z0 · 13 Ekim 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "İçeriğe geç" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" +"{ph0}Ana Sayfa{ph1} / {ph2}Blog{ph3} / Modeller ve tersine mühendislik" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Deneme" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Tersine mühendisliğin daha büyük bir modele ihtiyacı var mı?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Yazan N0zoM1z0 · 13 Ekim 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Önemli noktalar" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Model yeteneği, bir yapay zeka aracısının hangi hipotezleri " +"önerebileceğini etkiler.{ph1} Daha sonraki oturumlarda, daha önceki " +"çalışmaların çözümsüz bıraktığı sorunlar çözüldü." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Tanıdık bir derleyici, özel bir modelin öğrenilmesi için somut modeller" +" sunar.{ph1} Bazı tam makine kodu eşleşmeleri, belirli, yeniden " +"kullanılabilir kaynak kodu modellerine bağlıdır." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Adil bir karşılaştırmaya veri deposu bilgisini dahil edin.{ph1} İyi " +"bilgi erişimine sahip daha küçük bir model, ilerleme kaydetmek için zaten " +"yeterli bilgiye sahip olabilir." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Modeli, bir sonraki faydalı deneyi seçecek şekilde eğitin ve doğrulama " +"denetleyicisini test edin.{ph1} Geri bildirim, yalnızca denetleyicinin doğru" +" şeyleri doğruladığı ölçüde faydalıdır." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Doğrulanmış yeniden yapılandırma sonuçlarını zaman ve maliyetle " +"birlikte değerlendirin.{ph1} Yapay zeka aracısı iş akışının tamamı için " +"ölçmek istediğim şey bu." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "Bu makalede" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Daha güçlü modeller neyi değiştirdi?{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Neden uzmanlaşalım?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Bu deneyim nerede saklanmalı?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Bir sonraki faydalı deneyi öğrenmek{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Tersine mühendislik ve takviyeli öğrenme{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Doğrulama denetleyicisi yanlış olduğunda{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Çalıştırılmaya değer bir karşılaştırma{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Bu ne tür bir yapay zeka ajanını akla getiriyor?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Daha güçlü modeller neyi değiştirdi?" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Ağustos 2026'dan bu yana, bir aracının bir programa erişim ve onun " +"çalışmasını kontrol etmenin bir yolu ile ne kadar tersine mühendislik " +"gerçekleştirebileceğini araştırıyorum. Deneyimlerimin çoğu, özellikle Touhou" +" olmak üzere oyunların yeniden yapılandırılmasından geliyor. Modelleri " +"değiştirdiğimde, depolar her oturumda kurtarılanların kaydını tuttu." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Bu çalışmanın büyük bir kısmı tam olarak yeniden yapılanmayı amaçlamaktadır:" +" Bakımı yapılan kaynağı, sabit versiyonlara sahip tarihsel bir araç zinciri " +"altında derliyoruz ve hedef işlevi yeniden üretip üretmediğini kontrol " +"ediyoruz. Önceki çalışmaların durduğu yerde daha sonraki bir model başarılı " +"olduğunda, kaynak değişiklikleri bu ilerlemeyi neyin mümkün kıldığını " +"gösterir." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Geçici değişkenler örtüşen yaşam sürelerine ihtiyaç duyuyordu" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"TH09 saldırı fonksiyonunun mantığının büyük bir kısmı zaten yeniden " +"oluşturulmuştu, ancak derleyici hala geçici sonuçları orijinalinden farklı " +"şekilde saklıyordu. Geriye kalan sorun, bu sonuçların ne kadar süreyle canlı" +" kalması gerektiği ve depolarının ne zaman yeniden kullanılabileceğiydi." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Bir {ph0}GPT-6-Sol oturum kaydı{ph1}, birkaç sıradan kaynak kodu " +"düzenlemesini test ettikten sonra bu uyumsuzluğu bildirdi. {ph2}GPT-6.1-Sol " +"sorunu tekrar incelediğinde{ph3}, bu geçici değişkenlerin yaşam süreleri " +"hakkında yararlı bir hipotez öne sürdü." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"İşlev geçici sonuçlar üretti ve bunları animasyon konumlarına kopyaladı. " +"C++'da geçici bir sonuç, onu kullanan ifade bitene kadar canlı kalır. Gerçek" +" işlemleri tek bir ifadede gruplandırmak bu sonuçları bir arada canlı tuttu," +" böylece derleyici artık aynı depolamayı hepsi için yeniden kullanamıyordu." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Sonuçlardan biri, daha sonra çarpışma kontrolleri için kullanılan bir " +"değerle depolamayı hâlâ paylaşıyordu. Bu değere kendi ömrünü vermek, kalan " +"örtüşmeyi çözdü. Birkaç hedefli denemeden sonra, {ph0}kaynaktan yapılan " +"temiz bir yeniden derleme, tam işlevin eşleştiğini doğruladı{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Keşif ve testlerin birbirini nasıl desteklediğiyle ilgileniyorum. Geçici " +"nesne yaşam süreleri hakkındaki hipotez, yapay zeka ajanına yeni bir yön " +"verdi. Derleyici geri bildirimi, bu hipotezi eşleşen bir kaynak kodu " +"düzenlemesine dönüştürmeye yardımcı oldu." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Farklı bir kontrol akışı grafiği" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"İkinci bir TH09 işlevi, bu yeni yönün neden önemli olabileceğini gösterir. " +"Buradaki engel, birden fazla şubenin nihai çalışmalarını paylaşmasıydı. " +"{ph0}GPT-6.1-Sol'nin önceki çalışması{ph1} işlevin bazı kısımlarını " +"eşleştirdi ancak dallar yine de orijinalinden farklı bir şekilde birleşti." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra çevredeki kontrol akışı grafiğini değiştirdi{ph1}. Ana " +"yollar artık paylaşılan bir son güncellemeye ve geri dönüşe yol açıyordu. Bu" +" kaynak yapısında derleyici, dalları orijinaldekiyle aynı şekilde " +"birleştirdi. İşlevin tamamı eşleşti ve {ph2}ayrı bir yeniden oluşturma " +"kontrolü bunu doğruladı{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Temsili değiştirmek daha verimli bir arama alanı açtı.{ph1} Her iki " +"durum da bana genel model yeteneğini ciddiye almam için bir neden veriyor: " +"Bir temsilci, çevredeki işi ifade etmenin daha iyi bir yolunu bulmadan önce " +"yerel varyasyonları uzun süre denemeye devam edebilir." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Sonraki oturumlar önceki kaynak kodu ve kaydedilmiş başarısız denemeleri de " +"devraldı. Bu birikim avantajlarının bir parçasıydı. Geçmiş, keşifleri ve " +"doğrulamalarını incelememizi sağlar; kontrollü bir karşılaştırma ise modelin" +" etkisini devraldığı deneyimin etkisinden ayırmaya yardımcı olur." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Soruyu benim için ilginç kılan da bu. Yeni bir temsil bulma konusunda bir " +"miktar ilerleme sağlandı. Geriye kalan çalışmaların çoğu, farklı kaynak kodu" +" düzenlemelerinin tanıdık bir derleyiciye karşı test edilmesini içeriyordu. " +"Bunun ne kadarı geniş muhakeme yeteneği gerektiriyor? Bir model, o derleyici" +" ve kodla tekrar tekrar çalışarak ne kadar öğrenebilir?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Özel bir yapay zeka modeli neden başarılı olabilir?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou bize bu deneyimin yardımcı olmasını beklememiz için somut bir neden " +"veriyor. Oyun kodunun büyük bir kısmı aynı yazardan (ZUN) geliyor, " +"dolayısıyla yinelenen alışkanlıklar makul bir başlangıç ​​varsayımıdır. " +"Depolar bunu yararlı örneklerle desteklemektedir: İlgili döngüler ve " +"yardımcı düzenlemeler, oyunlar arasında hipotezler sağlamıştır." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Derleyiciyi dahil ettiğimizde bu kaynak kalıpları daha spesifik hale gelir. " +"Belirli bir sürüm ve seçenekler kümesi altında, kaynaktaki küçük " +"değişiklikler makine kodunda tekrarlanabilir farklılıklara neden olabilir. " +"Bu farklılıkların bazıları şaşırtıcı derecede belirsizdir." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Örneğin TH095'de, {ph0}yerel bir değişkenin adı bile VC7.1'nin onu nerede " +"sakladığını etkileyebilir{ph1}. Bildiriminin taşınması depolama düzenini " +"çözmedi. Ancak daha önceki bir arka plan işlevi, derleyicinin seçimini " +"etkileyen bir adlandırma modelini ortaya çıkarmıştı. Bu, {ph2}yeniden inşa " +"etmek{ph3}{ph4} için daha umut verici bir hipotez önerdi." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Dosya boyutu değişkeni için bu kalıbın yeniden kullanılması, depolama alanı " +"eklemeden gerekli düzeni oluşturdu. Daha sonra tam işlev eşleşti." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Bu, genel amaçlı bir yapay zeka modelinin sorunla ilk karşılaştığında " +"bilemeyeceği çok özel bir ayrıntıdır. Bu derleyici için uzmanlaşmış bir " +"model, bu tür birçok durumu görebilir ve hangi kaynak kodu varyasyonlarının " +"ilk önce test edilmeye değer olduğunu öğrenebilir." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Davranışı zaten anladığımız son eşleştirme problemlerinde bu fırsat " +"özellikle açıktır. Daha sonra bu derleyicinin hangi sıradan kaynak kodu " +"düzenlemesini gözlemlenen talimatlara dönüştürdüğünü soruyoruz. Uzmanlaşma, " +"modelin bu formları daha verimli bir şekilde önermesine yardımcı olurken, " +"hedef hâlâ hangi hipotezlerin hayatta kalacağını belirliyor." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Yararlı kalıplar bağlamlarını korumalıdır. TH08, TH095 ve TH09’dan daha eski" +" bir Visual C++ sürümü kullanır. TH04 ise DOS dönemine ait başka bir " +"derleyici kullanır. {ph0}Oyuncu kodunun yeniden yapılandırılması{ph1}, " +"kaynak kalıpları ve kodun çalıştırılabilir dosyaya nasıl bağlandığı hakkında" +" farklı hipotezler gerektirdi. Aynı yazar bize bir başlangıç varsayımı " +"verir; bunun geçerli olup olmadığını her hedefte kontrol ederiz. Uzman model" +" bu bağlamları ayırt etmeyi öğrenmelidir." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Bu deneyim nerede saklanmalı?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Bu kalıpları model eğitimi yoluyla öğretmeye karar vermeden önce, " +"halihazırda depoda tuttuğumuz bilgilere bakardım. {ph0}Önceki makalemde{ph1}" +" bunun projenin çalışma belleği haline geldiğini yazmıştım. Bu hafıza, " +"derleyici derslerini, kaynağı ve onları faydalı kılan başarısız deneyleri " +"içerir." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Bir aracı, bu kaydı alarak bilinen bir sonuçla başlayabilir ve bu sonuca " +"nasıl ulaştığımızı inceleyebilir. Aynı bağlamda halihazırda başarısız olan " +"alternatiflerden de kaçınılabilir. Başlangıç ​​noktası, modelin eğitilmiş " +"parametrelerini değiştirmeden iyileşir." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"TH09'nin düşman yaratma işlevi yeniden yapılandırılırken, bir " +"{ph0}GPT-6-Luna-max oturumu{ph1} ilgili TH08 kaynak kodundan bir hipotez " +"aldı. Önceki kod, döngünün nasıl organize edileceğini ve içindeki arızaların" +" nasıl ele alınacağını öneriyordu. TH09'in kendi kanıtları oyuna özgü " +"ayrıntıları sağladı. Kaynaktan yapılan yeniden derlemeler, işlevin tamamının" +" eşleştiğini doğruladı." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"Model, derleyici tuhaflığını bilmiyordu\" ve \"model bunu " +"kullanamadı\" farklı sorunlardır.{ph1} Geri getirme ilk sorunu çözebilir, " +"ancak bu gerçeği yararlı bir adaya dönüştürmek yine de çalışma gerektirir. " +"Aday kaynak kodu başarısız olursa modelin bir sonraki denemesinde sonucun ne" +" anlama geldiğine karar vermesi gerekir. İlgili modeli bilmek bu sürecin " +"yalnızca başlangıcıdır." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Bu nedenle, herhangi bir karşılaştırmaya, iyi geri çağırma özelliğine sahip," +" daha küçük, genel amaçlı bir yapay zeka modelini dahil ederim. Aynı deneyim" +" kitaplığını ona vermek, eğitimin ne gibi katkılar sağladığını belirlememize" +" yardımcı olacaktır: daha iyi aday oluşturma, geri bildirim sonrasında daha " +"iyi kararlar veya her ikisi." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Bir sonraki faydalı deneyi öğrenmek" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Geri bildirim sonrasında verilen kararlar, üzerinde çalışmayı en çok " +"istediğim şeylerdir. Failsel yeniden yapılanmada model bir açıklama önerir " +"ve bunu programa karşı test eder. Aday kaynak kodu başarısız olsa bile " +"sonuç, kalan olasılıkları daraltabilir ve bir sonraki deneyin daha yararlı " +"olmasını önerebilir." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Geçici sonuçlar örneğini tekrar düşünün. Son kaynağı işe yarayan düzenlemeyi" +" gösteriyor ancak bu kaynağa giden yol daha fazla bilgi içeriyor. Aşağıdaki " +"deneylerin her biri, hala neyin değişmesi gerektiğinin belirlenmesine " +"yardımcı oldu." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Deney" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Sonucunun bize öğrettikleri" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Sonuçları kopyalamanın farklı bir yolunu deneyin" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Kopya kodu değişir ancak işlev hâlâ farklıdır." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Döndürülen değerleri doğrudan kullanın" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"Kopyalama orijinal düzeni takip eder ancak geçici depolama yine de " +"farklıdır." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Tüm geçici değişkenleri aynı anda geçerli tutun" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Ayrı bir depolamaya sahipler, ancak bir tanesi daha sonra çarpışma " +"kontrolleri için kullanılan bir değerle örtüşüyor." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Çarpışma kontrolü değerini ayrı tutun" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Kaynaktan alınan temiz bir yeniden derleme, eşleşmenin tamamını doğrular." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Yukarıdaki saldırı fonksiyonunun yeniden yapılandırılmasından bize " +"öğrettiklerine göre gruplandırılmış seçilmiş deneyler." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Bu sırayı tutan bir eğitim kaydı, tek başına nihai kaynaktan daha fazlasını " +"öğretebilir. Önerilen her değişikliği gözlemlenen bir sonuca ve bir sonraki " +"karara bağlar. Etkisiz varyasyonları korumak da önemlidir: Daha sonraki bir " +"temsilciye, o bağlamda hangi hipotezlerin zaten test edildiğini söylerler." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Modelin geri bildirimi nasıl kullanacağını öğrenmesini isterim.{ph1} " +"Nötr bir sonuç, varyasyonun yeniden değerlendirilmesi için bir nedendir; " +"değişen bir uyumsuzluk başka bir nedene işaret edebilir. Yerel düzenlemeler " +"bilgilendirici olmayı bıraktığında, aracının kaynak temsilini yeniden gözden" +" geçirebilmesi veya kanıtları yeniden inceleyebilmesi gerekir." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Bu seçimleri yapmayı öğrenmek özerklik gerektirir. Bazen bir sonraki yararlı" +" adım, başka bir düzenleme derlemek yerine başka bir arayanı incelemektir. " +"Gerekli yeniden yazma işlemlerinin katı bir dizisi, modelin öğrenmesini " +"istediğimiz davranışın bir kısmıyla birlikte bu seçimi de ortadan " +"kaldıracaktır." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "Takviyeli öğrenme için tersine mühendislik neden ilgi çekicidir?" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Sınırlı yeniden yapılandırma bize bu seçimleri incelemek için pratik bir " +"ortam sağlar. Hedef ve derleyici sürümleri sabitlendikten sonra birçok " +"kaynak denemesi hızlı, tekrarlanabilir geri bildirim üretir. Temsilci bir " +"adayı derleyebilir, uyumsuzluğu inceleyebilir ve bu gözlemi bir sonraki " +"adımını seçmek için kullanabilir." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Takviyeli öğrenme, aldığı geri bildirim yoluyla karar verme sürecini " +"eğitebilir. Belirli bir kontrolle kabul edilen bir aday bize somut bir sonuç" +" verirken, denemelerin sırası bu sonuca ulaşmak için ne kadar çaba " +"harcandığını gözlemlememize olanak tanır." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Bu yönü destekleyen araştırmalar zaten var. {ph0}LLM4Decompile{ph1} kaynak " +"koda dönüştürme için uzmanlaşmış modelleri inceliyor. " +"{ph2}AutoDecompiler{ph3}, derleyici ve yürütme geri bildirimini kullanarak " +"çok turlu iyileştirmeyi eğitir. Çalışmaları fonksiyonel iyileşmeye " +"odaklanıyor. Bu çalışma için bunları, tarihsel bir derleyicinin çıktısıyla " +"eşleşen kaynağı bulma görevi için bir başlangıç ​​noktası olarak " +"kullanacağım." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Böylesine iyi tanımlanmış bir göreve ulaşmak için öncelikle bir fonksiyonun " +"hangi kaynaklara sahip olduğunu belirlememiz veya programın çalışırkenki " +"davranışını gözlemlemek için yeni bir yöntem tasarlamamız gerekebilir. " +"Örneğin TH08'de, bir {ph0}çarpışma farkı, orijinal programın kayan nokta " +"hesaplamalarını{ph1} nasıl işlediğini ortaya çıkardı. Aracının yararlı bir " +"düzeltmeyi test edebilmesi için önce neyi ölçeceğini bulması gerekiyordu." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Bu, geniş kapsamlı bir model için başka bir rol öneriyor: ilk etapta sorunun" +" kontrol edilebilir olmasına yardımcı olmak. Bu kontrol bir kez mevcut " +"olduğunda, öğrenilmiş bir arama politikasının bununla ne kadar ileri " +"gidebileceğini araştırabiliriz." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Doğrulama denetleyicisi yanlış olduğunda" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Bir kontrolü eğitimde kullandığımızda, kapsamı da öğrenme ortamının bir " +"parçası olur. Böyle bir referansa veya doğrulayıcıya oracle diyorum. " +"Tekrarlanabilir bir yanıt bile gerçekte neyi doğruladığına göre " +"anlaşılmalıdır." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 bu kapsamın dışında ne kadar şeyin saklanabileceğini gösterdi. Yeniden " +"oluşturulan bazı işlevler, tam karşılaştırmalarını yanlış kayan sabitlerle " +"geçti. Karşılaştırıcı, talimatları kontrol etmeden önce yeniden " +"konumlandırılan adresleri ayarladı, ancak bu adreslerin arkasındaki " +"değerleri yalnızca doğrulama için açıkça kaydedildiklerinde kontrol etti. " +"Diğer gerçek referanslar, değerleri incelenmeden geçebilir." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Bu boşluğu gidermek için, {ph0}daha geniş bir denetim{ph1}, doğrulamayı " +"zaten geçmiş işlevlerde hatalı sabitler buldu. Bir hesaplamada, yeniden " +"oluşturulan kaynak kodu {ph2}'yi eklerken, orijinali {ph3}'ü ekledi." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Eski doğrulama denetimiyle ödüllendirilen bir model, hatalı bir yeniden" +" yapılandırma üretmeyi öğrenebilir.{ph1} Bu denetleyiciyi kullanarak bir RL " +"modelini eğitmedik. Gözlemlediğimiz başarısızlık kontrolün kendisindeydi. " +"Ancak bunu bir ödül olarak kullanırsak aynı kör nokta öğrenme ortamının bir " +"parçası haline gelecektir." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Fonksiyonel bir testin de benzer bir kör noktası olabilir. {ph0}LLM kod " +"çözücüler üzerinde diferansiyel bulanıklaştırmayı kullanan araştırma{ph1}, " +"sağlanan testlerin dışında davranışsal farklılıklar buldu. Bu nedenle geçme " +"testini, uyguladığı durumlar açısından anlamamız gerekir. Benzer şekilde, " +"bir talimat eşleşmesinin, doğruladığı baytlar ve veriler açısından " +"anlaşılması gerekir." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Her iki doğrulama kontrolünü de ödül olarak kullanmadan önce, bunu kasıtlı " +"olarak yanlış sonuçlarla test ederim. Ayrıca nihai kabulü, yapay zeka " +"aracısının düzenleyebileceği kaynak kodundan ayrı tutacağım. Model, programı" +" doğru bir şekilde yeniden oluşturarak doğrulamayı geçmelidir. Aksi " +"takdirde, hedeften bir bayt dizisinin basitçe kopyalanması, yararlı kaynak " +"kodunu kurtarmadan saf bir puanlama sistemini kandırabilir." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Öğreneni geliştirmek ve doğrulama denetleyicisini geliştirmek aynı " +"araştırma probleminin bir parçasıdır.{ph1} Öğrenci, ona verdiğimiz geri " +"bildirimi optimize etme konusunda daha iyi hale geldikçe, geri bildirimin " +"anlaşılması da daha önemli hale gelir." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Çalıştırılmaya değer bir karşılaştırma" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Bu kontroller uygulandığında, karşılaştırmaya sabit bir VC7.1 görev ailesi " +"üzerinde başlayacağım. İlk olarak, güçlü bir genel amaçlı yapay zeka modeli " +"ve daha küçük bir model için temeller oluşturacaktım. Daha küçük modele depo" +" bilgisinin eklenmesi, geri almanın ne gibi değişikliklere yol açtığını " +"gösterecektir. Buradan itibaren, denetimli uzmanlık ve RL ile eğitilmiş bir " +"sürüm, eğitimin neleri eklediğini incelememize olanak tanır." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Bu karşılaştırmaları bilgilendirici kılmak için her model aynı hedef " +"kanıtları ve araçları alacaktır. Eğitime özel karşılaştırmalar için temel " +"modeli ve mevcut bilgiyi de sabit tutardım. Tekrarlanan denemeler, güvenilir" +" bir arama stratejisini şans eseri başarılı olan aday bir çözümden ayırmaya " +"yardımcı olacaktır." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Daha sonra iki başlangıç koşulunu ayıracağım: bir fonksiyonu talimatlarından" +" yeniden oluşturmak ve korunan kaynaktaki son birkaç farklılığı kapatmak. " +"Özel bir yapay zeka modeli ikinci görevde mükemmel olabilirken, genel amaçlı" +" bir yapay zeka modeli, ona ulaşmak için gereken işin çoğunu yapar. Bunları " +"ayrı ayrı ölçmek o iş bölümünü ortaya çıkaracaktır." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Her iki görevin de eğitim ve erişim dışında bırakılan test örneklerine " +"ihtiyacı vardır. İlgili Touhou oyunları motor kodunu paylaşır. Bir oyunu " +"eğitimden hariç tutmak, eğitim setinde neredeyse aynı işlevlerin kalmasına " +"neden olabilir. Bunun yerine, ilgili kaynak kodu gruplarının tamamını hariç " +"tutar ve doğrulanmış yanıtlarını hem eğitim verilerinin hem de erişim " +"kütüphanesinin dışında tutardım." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Bu örnekler için sonuç, eksiksiz, bağımsız olarak doğrulanmış eşleşmeler " +"olacaktır. Aday teklifleri veya derleme girişimleri için eşit bütçeler, " +"arama kalitesinin karşılaştırılmasına yardımcı olacaktır. Derleme de dahil " +"olmak üzere toplam süre ve maliyetin ölçülmesi, bu kalitenin verimli bir iş " +"akışı üretip üretmediğini gösterecektir. Eğitim maliyetleri ayrı olarak " +"ölçülmelidir." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Her iki ölçüm de önemlidir. Ucuz bir teklif, hiçbir yararlı bilgi sağlamayan" +" daha fazla derlemeye neden olursa pahalı bir iş akışına yol açabilir. " +"Tersine, daha yavaş bir model, yararlı bir deneyi daha erken bulursa daha " +"ekonomik olabilir. Karşılaştırma bu maliyetleri içermelidir." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Kabul edilen sonuçların sayılması aynı zamanda ara ilerlemeyi de perspektif " +"içinde tutar. Bir TH09 {ph0}tekrar oynatma-kaydetme adayı{ph1}, derlenmiş " +"işlevin beklenen boyuta sahip olması nedeniyle umut verici görünüyordu, " +"ancak tam bir karşılaştırma yine de önemli farklılıklar buldu. Derleyicinin " +"talimatları düzenleme biçimindeki değişiklikler, altta yatan sorunu çözmeden" +" adayın daha yakından bakmasını da sağlayabilir. Bu tür teşhisler bir " +"sonraki deneye rehberlik edebilir, ancak \"yaklaşmanın\" herhangi bir " +"ödülünü tam kabul kontrolüne göre doğrularım." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Bu sonuçlardaki model ilgimi çeker. Özel bir yapay zeka modeli tanıdık bir " +"derleyici ailesinde başarılı olursa, bu avantaj bir takım zinciri " +"değişikliğinden sonra da ayakta kalabilir mi? Her iki yapay zeka modeli de " +"iyi bir erişime sahip olduğunda, eğitimin hâlâ ne kadar katkısı olur? " +"Cevaplar, her model türünün en yararlı olduğu yerin neresi olduğuna karar " +"vermemize yardımcı olacaktır." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Bu ne tür bir yapay zeka ajanını akla getiriyor?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Modellerin farklı aşamalarda yardımcı olduğu ortaya çıkarsa, özel bir yapay " +"zeka modeline erişimi olan geniş bir temsilci yararlı bir düzenleme " +"olabilir. Bir görev tanıdık bir derleyici araması haline geldiğinde, adaylar" +" için özel yapay zeka modelini isteyebilir. Sonuçların artık bir anlamı " +"kalmazsa, daha geniş kapsamlı temsilci hedef kanıtlara geri dönebilir veya " +"ölçümün kendisini araştırabilir." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"Bu düzenlemede uzmanlaşma, soruşturma geliştikçe temsilcinin seçebileceği " +"bir araç haline gelir. Temsilci, daha önceki atılımları mümkün kılan yön " +"değiştirme özgürlüğünü elinde tutar." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Bu, doğal olarak önceki makalede anlattığım endüstriyel değişimin sonucudur." +" Daha fazla deney yürütebilmek, işi organize etme şeklimizi değiştirir. Aynı" +" zamanda bize, hangi kararların geniş muhakeme gerektirdiğini ve " +"hangilerinin belirli bir zanaatta tekrarlanan deneyimlerle geliştirildiğini " +"sormamız için bir neden de verir." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Şimdilik en güçlü genel model, daha önce çözemediğim sorunları çözerek iş " +"akışımda yerini kazandı. Bu başarılar süreci daha yakından incelemek " +"istememe yol açıyor: Ne kadarı modelin geniş yeteneklerine bağlıydı? Ne " +"kadarı bu yeniden yapılandırma türüne özel olarak eğitilmiş bir model " +"tarafından yapılabilirdi?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Depolar bize soruyu test etmemiz için bir yol sağlıyor.{ph1} Bu kaydı " +"karşılaştırmayı oluşturmak ve ne öğrendiğimizi görmek için kullanmak " +"istiyorum." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Kanıt ve model ilişkilendirme" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Örnekler, bağlantılı taahhütlerde kaydedilen geçmiş işlev düzeyi " +"karşılaştırmalarını açıklamaktadır. Tüm oyun çalışma zamanı kontrolleri ayrı" +" kilometre taşlarıdır. Kaynak ve eşleşen kayıtlar 13 Ekim 2026'da incelendi." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"TH09 etiketi {ph0}, GPT-6-Astra anlamına gelir. {ph1} ile ilişkilendirilen " +"model zaman içinde değiştiği için etiket tek başına belirli bir çalıştırmada" +" kullanılan modeli tanımlayamaz. Belirtilen diğer taahhütlerdeki açık model " +"adları, kaydedilen atıfları sağlar. Bu geçmişler, her çalıştırma için " +"tutarlı maliyet veya çaba ölçümlerini içermez." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 geçici nesne yaşam süreleri:{ph1} {ph2}önceki bağlam " +"incelemesi{ph3} ve {ph4}kaynaktan temiz bir yeniden derlemeyle doğrulanan " +"tam yeniden yapılandırma{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front geri arama:{ph1} {ph2}eşleşmeyen tanılama bölgeleri{ph3}, " +"{ph4}Astra'nin yeni kontrol akışı grafiği{ph5} ve onun {ph6}kabul edilen " +"yeniden derleme kontrolü{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Derleyici bilgisi:{ph1} {ph2}TH095 tanımlayıcı grubu davranışının " +"yeniden kullanımı{ph3}, {ph4}TH04 oyuncu kaynak kodu ve bağlayıcı " +"sırası{ph5} ve {ph6}Luna'nin TH09'nin düşman oluşturma işlevini tamamen " +"yeniden yapılandırması{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Kontroller ve teşhisler:{ph1} {ph2}TH08 kayan nokta sabiti " +"denetimi{ph3}, {ph4}TH08 sayısal inceleme{ph5} ve {ph6}TH09 yeniden " +"oynatmayı kaydeden yeniden yapılandırma{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Özel modellerin ve RL eğitiminin önerilen karşılaştırmaları gelecekteki " +"deneylerdir. Proje geçmişleri onları motive ediyor. Bu makale için hiçbir " +"eğitimli özel model değerlendirilmemiştir." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Tersine mühendisliğin daha büyük bir modele ihtiyacı var mı? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Touhou yeniden yapılandırma bana genel modeller, uzman modeller ve derleyici" +" geri bildirimlerinden daha iyi hipotezler önermeyi öğrenme hakkında neler " +"öğretti?" + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Bu sayfada" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Modeller ve tersine mühendislik makalesi" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Seçilmiş yeniden yapılanma deneyleri" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Başa dön" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}Ayrıntılı kanıt notları{ph1}, kaydedilen karşılaştırmaları ve " +"deneylerin bağlamını içerir." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "N0zoM1z0 · 13 Ekim 2026 · İnceleme taslağı" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Kurulum rehberi" diff --git a/website/locales/uk/messages.po b/website/locales/uk/messages.po index 3debfedc1..55afe918d 100644 --- a/website/locales/uk/messages.po +++ b/website/locales/uk/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Перейти до змісту" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Головний{ph1} сторінка / Блог" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Блог." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Думки про реверс-інжиніринг." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Реконструкція гри{ph0}Вигадування" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Промислова революція в області реверс-інжинірингу" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "Чому мене навчив посібник з оновлення та реконструкції TH08, TH095 та TH04 " "про агентів, перевірку та знання, які використовуються в різних проектах." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Прочитайте статтю" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Автор: N0zoM1z0 · 10 жовтня 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" " і агентами штучного інтелекту." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -135,112 +138,117 @@ msgstr "" "REA-Дізнайтеся, як працює програмне забезпечення. Зворотне проектування за " "допомогою вашого програміста." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Головна REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Основна навігація" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA на GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Приєднатися до REA в Discord" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Стежити за REA в X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -249,35 +257,35 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Блог{ph3} / Реконструкція Тохоу" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Есе · Реконструкція Тохоу" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Промислова революція в області реверс-інжинірингу." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Автор: N0zoM1z0 · 10 жовтня 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Головне" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -290,7 +298,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -304,7 +312,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -317,7 +325,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -330,7 +338,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -340,65 +348,65 @@ msgstr "" "{ph0}Ми знаходимося на зорі промислової революції в RE.{ph1} Методи все ще " "розробляються. Нам ще багато чого належить вивчити." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Як досвід з'єднує" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Управління{ph1} персоналом * мета і критерії прийнятності" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Самостійність" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Агент" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Виберіть експеримент.{ph0}Висуньте гіпотезу." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Перевірка" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Еталон перевірки" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Тестування на{ph0}конкретні посилання." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Репозиторій" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Робоча пам’ять" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -407,7 +415,7 @@ msgstr "Кодекс, докази,{ph0}перевірки та уроки." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -416,26 +424,26 @@ msgstr "Невідповідність{ph0}{ph1}Перегляньте гіпо #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Краще{ph0}{ph1}вихідна точка{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Повторне використання" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Минути{ph1} * Зберегти результат і його докази" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -444,14 +452,14 @@ msgstr "" "Кожен наступний проект стає найкращою відправною точкою. Це включає " "виправлення перевірок, коли ми виявляємо прогалини." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "У цій статті" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -459,7 +467,7 @@ msgstr "{ph0}Серпень 2026 року{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -467,7 +475,7 @@ msgstr "{ph0} TH08: продовження{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -475,7 +483,7 @@ msgstr "{ph0}Два підходи{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -483,7 +491,7 @@ msgstr "{ph0} TH095: рецептура{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -491,7 +499,7 @@ msgstr "{ph0} TH04: різні архітектури{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -499,7 +507,7 @@ msgstr "{ph0}Від точного до читабельного{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -507,18 +515,18 @@ msgstr "{ph0}Промисловий зсув{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Що стає можливим{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Що змінилося в серпні 2026 року" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -532,7 +540,7 @@ msgstr "" "програмі. Просуваючись далі, я витрачав більше свого часу на наступну " "функцію. Це також означало, що я тримав у голові все більш об'ємну картину." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -546,7 +554,7 @@ msgstr "" "інших областях, але в кожній області потрібно встановити, що можна " "перевірити за допомогою надійних посилань." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -559,7 +567,7 @@ msgstr "" "інструментів розробки. Touhou reconstruction дав мені значний проект, де я " "міг це зрозуміти." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -576,7 +584,7 @@ msgstr "" "цієї свободи змінило ситуацію на краще: я зміг приділяти більше уваги " "напрямку проекту і тому, чи заслуговують довіри його перевірки." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -587,7 +595,7 @@ msgstr "" " що залишиться після поточного проекту. Чи буде в наступній грі корисно все," " що ми тільки що дізналися?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: опора на людську працю" @@ -596,7 +604,7 @@ msgstr "TH08: опора на людську працю" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -610,7 +618,7 @@ msgstr "" "основу. Це прийшло разом із знанням конструкції та історією внеску, яку я " "зберіг у продовженні." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -622,7 +630,7 @@ msgstr "" "журналі були зареєстровані вихідні дані для всіх 1107 ідентифікованих " "ігрових функцій." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -634,7 +642,7 @@ msgstr "" "випущена веб-версія. 64-розрядна версія Linux для власної версії вийшла 30 " "Серпня." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -650,7 +658,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -668,12 +676,12 @@ msgstr "" "досягає очікуваного стану. Агент пропонує пояснення та перевіряє його; " "невідповідність дає йому можливість дослідити щось конкретне." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Точний збіг з неправильною константою" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -685,7 +693,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -698,7 +706,7 @@ msgstr "" "була перевірена на рівні {ph0}. В оригіналі використовувалося значення {ph1}" " - поріг максимальної потужності." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -713,13 +721,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}Однак функція вже пройшла точне порівняння.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -734,7 +742,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -750,7 +758,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -765,7 +773,7 @@ msgstr "" " було проаналізовано 1548 посилань на константи з плаваючою комою. Було " "виявлено ще дванадцять неправильних посилань у п'яти прийнятих функціях." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -779,7 +787,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -789,7 +797,7 @@ msgstr "" "{ph0}Посилання для перевірки (oracle) також потребувало відновлення.{ph1} Її" " виправлення було частиною оновлення гри." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -807,7 +815,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -823,7 +831,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -833,7 +841,7 @@ msgstr "" "{ph0}Успішний запуск пакета дозволив нам відновити код та покращити " "середовище для наступного пакета.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Дві різні ідеї реконструкції" @@ -842,7 +850,7 @@ msgstr "Дві різні ідеї реконструкції" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -854,7 +862,7 @@ msgstr "" "роду роботою. У повідомленні повідомляється, що подальша розробка буде " "вестися в приватному порядку до завершення. В одному уривку сказано:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -864,7 +872,7 @@ msgstr "" "інтелекту) у цій галузі на основі нашої роботи створює погану картину для " "майбутніх зусиль з декомпіляції…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -882,7 +890,7 @@ msgstr "" "стосуються того, як повинна проходити реконструкція і як слід оцінювати " "внесок." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -895,7 +903,7 @@ msgstr "" " мірою залежав від досвіду цієї людини. Довіра до розробника мала значення, " "оскільки більша частина міркувань виникла під час його роботи." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -907,7 +915,7 @@ msgstr "" "використовувати ці знання для проведення наступного розслідування " "самостійно." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -922,7 +930,7 @@ msgstr "" "могла проаналізувати, чому ми вибрали певну реалізацію, навіть якщо агент " "зробив більшу частину роботи." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -935,7 +943,7 @@ msgstr "" "цим виникають серйозні питання про кредитоспроможність. Це також змінює те, " "що розробники повинні знати, перш ніж приймати внесок." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -950,7 +958,7 @@ msgstr "" "розробляти процес і розпізнавати, коли його результати неправильні. Різні " "спільноти можуть вибрати, яку частину цих змін вони хочуть взяти на себе." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -975,7 +983,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -987,14 +995,14 @@ msgstr "" " 2026 року, і його {ph2}Політика щодо внесків{ph3}. Цитата є скороченою " "витримкою. {ph4}Титри та Походження{ph5} TH08 вказують на межу продовження." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: досвід починає накопичуватися" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1009,7 +1017,7 @@ msgstr "" "набагато більше про те, як розпочати реконструкцію та як підтримувати її в " "робочому стані." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1022,7 +1030,7 @@ msgstr "" "підключена. Реконструкція Windows i386 була позначена як відтворювана 10 " "вересня, приблизно через дванадцять днів після ініціалізації." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1033,7 +1041,7 @@ msgstr "" "могла б отримати вигоду від роботи над іншою грою. Досвід вже був присутній " "в інструментах і в тому, як був організований проект." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1048,7 +1056,7 @@ msgstr "" "побачити, як вони працюють разом. Цей урок допоміг нам сформулювати підхід " "до побудови всієї програми TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1061,7 +1069,7 @@ msgstr "" "допомагати і після того, як я перейду далі. Наступний агент може використати" " результат, не повторюючи розслідування, яке призвело до нього." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1076,7 +1084,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1088,7 +1096,7 @@ msgstr "" "наступному проекті ми можемо витратити більше зусиль, щоб внести щось " "справді нове у свою мету." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1101,7 +1109,7 @@ msgstr "" "роботу. Їм не потрібно відновлювати всю історію проекту, щоб з'ясувати, чому" " вихідний код виглядає саме так." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: робочий процес функціонує відповідно до іншої архітектури" @@ -1110,7 +1118,7 @@ msgstr "TH04: робочий процес функціонує відповід #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1126,7 +1134,7 @@ msgstr "" "інші дані, отримані з ігор Windows. Існуючий {ph2}робота{ph3} за ReC98 також" " дала нам цінні знання та вихідні матеріали." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1139,7 +1147,7 @@ msgstr "" "використовується власний 64-розрядний порт. При установці робочої версії DOS" " спочатку вказується посилання на цей порт." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1152,7 +1160,7 @@ msgstr "" "Але агент все-таки міг довести питання до результату і використати цей " "результат для наступного експерименту." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1167,7 +1175,7 @@ msgstr "" "будуть доступні, агент зможе опрацювати питання приблизно так само, як це " "було з заголовком Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1178,7 +1186,7 @@ msgstr "" "змусила нас почати все спочатку з нового способу роботи. Архітектура " "визначила проблему; робочий процес все ще давав нам можливість її вирішити." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1195,7 +1203,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1205,12 +1213,12 @@ msgstr "" "Стан проекту на 10 жовтня 2026 року: {ph0}реконструкція DOS та ручне " "тестування{ph1} · {ph2}64-розрядний порт{ph3}. Порт знаходиться в розробці." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Від точного коду до читабельного коду" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1219,7 +1227,7 @@ msgstr "" "Як тільки реконструкція завершиться, я хочу, щоб хтось інший міг це " "зрозуміти." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1234,7 +1242,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1251,7 +1259,7 @@ msgstr "" "відповідно до джерела, щоб наступна людина могла зрозуміти, звідки походить " "ця інтерпретація." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1266,14 +1274,14 @@ msgstr "" "безпечно змінити поведінку, нам потрібно відновити зв'язок, що стоїть за " "старим доступом до пам'яті." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Порядок, який я зараз використовую, такий:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1289,7 +1297,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1306,7 +1314,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1322,7 +1330,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1336,7 +1344,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1352,7 +1360,7 @@ msgstr "" "відповідний вихідний код та дані. Другий перевіряє, що відновлена програма " "як і раніше будує і поводиться коректно відповідно до обраних нами шляхами." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1366,7 +1374,7 @@ msgstr "" "будуть доступні, агенту не вдасться провести розслідування, перш ніж " "проводити подальший рефакторинг." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1384,7 +1392,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1403,7 +1411,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1414,12 +1422,12 @@ msgstr "" "дозволяє використовувати відновлені знання.{ph1} Потім порт може " "використовувати обидва." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Що робить це промисловим зрушенням" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1433,7 +1441,7 @@ msgstr "" "досконалий інструмент міг би допомогти в будь-якій подальшій роботі, яка " "його потребувала." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1447,7 +1455,7 @@ msgstr "" "я пропишу кожен крок, більша частина роботи залишається залежною від моєї " "уваги." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1460,7 +1468,7 @@ msgstr "" "йому зрозуміти помилку досить добре, щоб спробувати ще раз. Мені все ще " "потрібно вирішити, чи зібрані дані відповідають етапу проекту." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1475,7 +1483,7 @@ msgstr "" "Агент може використовувати їх, щоб протестувати запропоноване джерело та " "перевірити, чи відповідає його пояснення дійсності." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1493,7 +1501,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1513,7 +1521,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1530,7 +1538,7 @@ msgstr "" "інструменті, ми повинні його усунути та переглянути результати, на які він " "вплинув. Наступний проект може успадкувати більш потужний інструмент." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1546,7 +1554,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1558,7 +1566,7 @@ msgstr "" " проектам можливість спільно проводити перевірки і витягувати уроки. Робота " "над однією грою може покращити стартові умови для іншої." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1570,12 +1578,12 @@ msgstr "" "інструментів впливає на те, скільки може зробити наступна людина — або " "наступний агент." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Проекти, які ми тепер можемо розглянути" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1586,7 +1594,7 @@ msgstr "" " цікавою для реінжинірингу і все одно вимагати від мене більше уваги, ніж я " "міг би їй приділити. Багато проектів так і залишаться ідеями." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1603,7 +1611,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1614,7 +1622,7 @@ msgstr "" " зв'язок та накопичені знання дозволили б агенту надійно працювати з " "нею?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1625,12 +1633,12 @@ msgstr "" "спокої. Кожен з них може покращити наш підхід до наступного. Я хочу " "продовжувати вивчати, як далеко це може нас завести." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Основні етапи та джерела реалізації проекту" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1664,7 +1672,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1698,7 +1706,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1717,7 +1725,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1741,7 +1749,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1763,7 +1771,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1779,7 +1787,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1801,7 +1809,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1815,7 +1823,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1837,27 +1845,27 @@ msgstr "" "допомогою агентів штучного інтелекту та про те, як знання об'єднуються в " "TH08, TH095 та PC-98, TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Досвід, накопичений в період між проектами" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Есе про реконструкцію Тохоу" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -1866,19 +1874,19 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "" "{ph0}Головний{ph1}{ph2} сторінка/{ph3}Лабораторія швидкості динозаврів" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Перевірити → перебудувати → змінити" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Відновіть правило швидкості динозавра." @@ -1887,7 +1895,7 @@ msgstr "Відновіть правило швидкості динозавра. #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1899,15 +1907,15 @@ msgstr "" "швидкістю. {ph0}REA повернув запущений сценарій;{ph1} ми використовували " "його правило для створення цієї міні-гри з {ph2}регульованою швидкістю.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "На цій сторінці" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1915,7 +1923,7 @@ msgstr "{ph0}Грайте і змінюйте швидкість{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1923,7 +1931,7 @@ msgstr "{ph0}Прочитайте Відновлене правило{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1931,18 +1939,18 @@ msgstr "{ph0}Перевірте реконструкцію{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Спробуйте провести аналіз{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Грайте і змінюйте швидкість" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1954,49 +1962,49 @@ msgstr "" "фіксовану швидкість. Виберіть Відновлене правило, щоб почати з 6 і поступово" " збільшувати швидкість знову." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Грати у відтворену версію" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Грати" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Стрибок ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Почати знову" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Швидкість" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Використовуйте правило відновленого прискорення" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Початкове правило: починайте з 6, потім збільшуйте до 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Перемістіть повзунок, щоб встановити власну швидкість. Пробіл або стрибок " "прибирають кактус." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2005,7 +2013,7 @@ msgstr "" "Увімкніть JavaScript для відтворення реконструкції. Наведений вище код та " "пояснення залишаються читабельними." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Прочитав повернутий скрипт REA" @@ -2013,7 +2021,7 @@ msgstr "Прочитав повернутий скрипт REA" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2028,7 +2036,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2038,18 +2046,18 @@ msgstr "" "Задані наступні параметри: {ph0}, {ph1} і максимальна {ph2}. Гра запускає цю" " гілку в оновленні без будь-яких колізій." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Використовуйте те саме правило в новій грі" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Копіювати" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2066,18 +2074,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}Скачайте правила швидкості{ph1} · {ph2}Прочитайте код гри{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Перевірте реконструкцію" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2088,27 +2096,27 @@ msgstr "" " автоматичним плануванням. Порівняйте ці записані швидкості з відтворенням " "відновленого правила." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Оновлення" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Оригінальна гра" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Реконструйоване правило" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Запустіть перевірку швидкості" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2117,14 +2125,14 @@ msgstr "" "Значення округлені до трьох знаків після коми. Розгалуження перевіряє перед " "додаванням, тому кінцевий приріст може бути трохи вище 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Спробуйте провести аналіз самостійно" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2133,7 +2141,7 @@ msgstr "{ph0}Налаштуйте REA{ph1} за допомогою вашого #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2142,7 +2150,7 @@ msgstr "" "Виконавши {ph0}дії по підключенню до браузеру{ph1}, використовувати {ph2} як" " URL-адреса сторінки." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2159,7 +2167,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2171,7 +2179,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий аген #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2185,7 +2193,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2200,7 +2208,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2226,12 +2234,12 @@ msgstr "" "Прочитайте правила швидкості в грі динозаврів за допомогою REA, перебудуйте " "їх, потім змініть швидкість і грайте." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Реконструкція швидкості динозавра" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2240,52 +2248,52 @@ msgstr "" "Міні-гра про динозаврів. Використовуйте кнопку переходу або натисніть " "пробіл, поки гра зосереджена." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Скопіюйте Відновлене правило швидкості" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Запит на копіювання результатів аналізу динозаврів" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Перейти до змісту" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Головний{ph1} сторінка / поширені запитання" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "Поширені запитання щодо REA." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Налаштування, Оновлення, аналіз та усунення несправностей." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Тим" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2293,7 +2301,7 @@ msgstr "{ph0}Налаштування та оновлення{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2301,7 +2309,7 @@ msgstr "{ph0}Аналіз{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2309,31 +2317,31 @@ msgstr "{ph0}Діагностика{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Дані та обмін ними{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Налаштування та оновлення" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Як встановити REA ?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Термінал * Налаштування агента" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Копіювати" @@ -2341,7 +2349,7 @@ msgstr "Копіювати" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2355,12 +2363,12 @@ msgstr "" "файлу та запитання. Вимоги й перші кроки описані в {ph0}посібнику з " "налаштування{ph1}." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "Які агенти кодування можуть використовувати REA?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2375,18 +2383,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Підключіть свій кодуючий агент{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Як оновити REA ?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2395,13 +2403,13 @@ msgstr "" "REA релізи часто, включаючи виправлення помилок. Якщо ви встановили CLI з " "npm:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Термінал * встановлений CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2411,14 +2419,14 @@ msgstr "" "Виконайте команду оновлення налаштувань, зазначену в оновленні. Якщо ви " "налаштовуєте свого агента через {ph0}, запустивши:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Термінал * Налаштування агента оновлення" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2430,14 +2438,14 @@ msgstr "" "визначену версію пакета. Повторіть налаштування, щоб агент перейшов на нову " "версію. Для разового виклику CLI додайте потрібну команду після {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Встановлюється навик з навичок.цього достатньо?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2450,24 +2458,24 @@ msgstr "" "відповідну навичку, а потім перезапустіть свій агент, щоб він міг викликати " "інструменти." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Аналіз" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Що я можу проаналізувати за допомогою REA?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Почніть з того програмного забезпечення, яке у вас є:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2479,7 +2487,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2491,7 +2499,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2501,7 +2509,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2513,12 +2521,12 @@ msgstr "" "Android, вбудованого ПЗ і упакованих ресурсів. {ph0}Дивіться приклади " "проведених досліджень{ph1}." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "Чи потрібен мені Hopper, Ghidra або IDA?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2530,7 +2538,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2543,12 +2551,12 @@ msgstr "" "визначають, якого постачальника можна використовувати. {ph0}Налаштуйте " "аналіз програм з машинним кодом{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Чи можу я використовувати REA без кодуючого агента?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2557,14 +2565,14 @@ msgstr "" "Так. У CLI використовуються ті ж робочі процеси аналізу. Для локальної " "програми JavaScript або Electron:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Термінал * статичний аналіз додатків" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2575,13 +2583,13 @@ msgstr "" "{ph0}Використовуйте CLI{ph1} для параметрів установки." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "Який код повертає REA?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2596,7 +2604,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2608,12 +2616,12 @@ msgstr "" "та тестування реалізації. {ph0}Розрахунок{ph1} DX-Ball і {ph2}перевірка " "прапора CTF{ph3} показують, як працює цей процес." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Що запитати в помічника?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2630,7 +2638,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2638,7 +2646,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий аген #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2648,18 +2656,18 @@ msgstr "" "Замініть шлях на цільовий. В {ph0}керівництво{ph1} наведені підказки для " "прикладів в native, Electron і браузері." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Діагностика" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Чому мій агент не може бачити інструменти REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2669,7 +2677,7 @@ msgstr "" "Перезапустіть або підключіть агент після налаштування. Перевірте його " "реєстрацію REA в {ph0}; для Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Термінал * перевірте одного клієнта" @@ -2677,7 +2685,7 @@ msgstr "Термінал * перевірте одного клієнта" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2688,14 +2696,14 @@ msgstr "" "Якщо у звіті відображається відсутність або застаріла реєстрація, запустіть " "програму встановлення для цього клієнта:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Термінал * виправлення налаштувань одного клієнта" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2707,14 +2715,14 @@ msgstr "" "інструменти все ще відсутні, перевірте помилку підключення клієнта MCP. " "{ph0}Додаткова діагностика налаштування{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Чи потрібно спочатку запускати Hopper?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2727,14 +2735,14 @@ msgstr "" "демонстраційний режим або активацію ліцензії. {ph0}Дивіться розділ " "Налаштування власного провайдера{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Що робити, якщо я знайшов помилку?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2746,7 +2754,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2759,17 +2767,17 @@ msgstr "" "ім'я постачальника, якщо проблема пов'язана з аналізом програм з машинним " "кодом." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Дані та обмін ними" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "Чи завантажує REA мій додаток?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2779,7 +2787,7 @@ msgstr "" "цих результатів застосовується політика щодо даних, встановлена його " "постачальником моделей." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Як я можу поділитися прикладом або зробити свій внесок?" @@ -2788,7 +2796,7 @@ msgstr "Як я можу поділитися прикладом або зроб #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2804,7 +2812,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2831,77 +2839,77 @@ msgstr "" "Відповіді на поширені питання REA: установка, оновлення, інструменти " "аналізу, засоби програмування, усунення неполадок і обмін прикладами." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "Поширені запитання про REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Скопіювати інсталяційну команду REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Скопіювати команду оновлення REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Команда оновлення Налаштування агента копіювання" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Скопіювати команду аналізу REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Запит на копіювання прикладу аналізу" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Скопіювати команду діагностики клієнта" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Команда налаштування в області копіювання" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Перейти до змісту" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Головний{ph1} / Ваше перше розслідування" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Дізнайтеся, куди відправляються{ph0}експортовані нотатки." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2910,14 +2918,14 @@ msgstr "" "Використовуйте REA для перевірки невеликого додатки, натисніть на кнопку " "\"Експорт заміток\" і перевірте одну деталь самостійно." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "У цій вправі" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2925,7 +2933,7 @@ msgstr "{ph0}1. Настройка{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2933,7 +2941,7 @@ msgstr "{ph0}2. Запитайте про експорт{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2941,7 +2949,7 @@ msgstr "{ph0}3. Дотримуйтесь відповіді{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2949,13 +2957,13 @@ msgstr "{ph0}4. Перевірте прогноз{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Задайте ще одне питання{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Підключіть свого агента до REA." @@ -2968,29 +2976,29 @@ msgstr "1. Підключіть свого агента до REA." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Копіювати" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Або запустіть цю команду у своєму терміналі:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2999,14 +3007,14 @@ msgstr "" "Ознайомтеся з планом, схваліть налаштування, а потім перезапустіть свого " "агента. Ви вже підключені? Продовження нижче." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Запитайте, де записаний CSV" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3018,7 +3026,7 @@ msgstr "" "кнопкою {ph0}експорту заміток{ph1}. Ваш агент може перевірити його код, не " "встановлюючи та не запускаючи Electron." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3029,14 +3037,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Приклад завантаження ZIP-файлу{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3046,12 +3054,12 @@ msgstr "" "Якщо ваш агент не може завантажити файли, розпакуйте цей архів самостійно. " "Вкажіть шлях до папки {ph0} і задайте те саме питання щодо експорту." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Дотримуйтесь відповіді назад до коду" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Шукайте коротке пояснення з посиланнями на файли та рядки:" @@ -3060,7 +3068,7 @@ msgstr "Шукайте коротке пояснення з посиланням #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3071,12 +3079,12 @@ msgstr "" "Кнопка надсилає повідомлення {ph0}. Основний процес форматує нотатки як CSV " "і записує {ph1} в папку завантажень користувача. Це стовпці {ph2} і {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Від кнопки до пристрою запису файлів" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3085,7 +3093,7 @@ msgstr "" "Статичний аналіз REA відображає повідомлення з його обробником. Адресат " "зчитується з коду." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3097,19 +3105,19 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "" "{ph0}Перегляньте повний трасування коду та записаний результат{ph1} REA." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Перевірте прогноз" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3118,19 +3126,19 @@ msgstr "" "Стовпці CSV розділені комою. Що відбувається, коли заголовок нотатки сам по " "собі містить кому або лапки?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Проведіть перевірку самостійно" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Відкрийте термінал у розпакованій папці {ph0}:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3140,17 +3148,17 @@ msgstr "" "або Zsh. Ваш агент може запустити той самий JavaScript в оболонці вашої " "платформи." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Задайте ще одне питання" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Спробуйте продовжити ту саму розмову:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3159,7 +3167,7 @@ msgstr "" "Що станеться, якщо файл не може бути записаний? Поверніться на сторінку, " "вказану в повідомленні про помилку." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3172,7 +3180,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3186,7 +3194,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3200,7 +3208,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3225,65 +3233,65 @@ msgstr "" "запитайте, куди надсилаються експортовані нотатки, і перевірте форматування " "CSV із прикладом заголовка." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "Ваше перше розслідування REA" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Скопіюйте запит на встановлення REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Команда Налаштування Копіювання" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Запит на копіювання нотаток для розслідування" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Скопіювати запит перевірки CSV" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Команда перевірки форматування копії" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Перейти до змісту" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Головний{ph1} сторінка / початок роботи" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Налаштуйте REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3291,49 +3299,49 @@ msgstr "" "Підключіть REA до свого програміста або перевірте локальну програму зі свого" " терміналу." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Відкрийте термінал і перевірте:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Термінал" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Копіювати" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3346,7 +3354,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3357,17 +3365,17 @@ msgstr "" " вимкнено\"{ph1}, коли ви запустите {ph2}, запустіть це один раз і повторіть" " спробу:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "Якщо ви використовуєте Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Не інакше як:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Закрийте термінал, відкрийте його знову, потім:" @@ -3375,7 +3383,7 @@ msgstr "Закрийте термінал, відкрийте його знов #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3387,7 +3395,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3399,7 +3407,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3409,14 +3417,14 @@ msgstr "" "Віддаєте перевагу звичайному інсталятору? Завантажте версію LTS з сайту " "{ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Параметри налаштування" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3424,7 +3432,7 @@ msgstr "{ph0}Підключіть свій кодуючий агент{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3432,7 +3440,7 @@ msgstr "{ph0}Використовуйте CLI{ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3440,18 +3448,18 @@ msgstr "{ph0}Налаштування аналізу програм з маши #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Отримання допомоги{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Підключіть свій кодуючий агент" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3463,12 +3471,12 @@ msgstr "" "Grok Build та інші підтримувані клієнти MCP. Коннектор Grok Bot доданий з " "його чату." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Новачок у кодуванні агентів?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3480,7 +3488,7 @@ msgstr "" "команди, а також запитує їх перед внесенням змін. REA надає йому " "інструменти для зворотного проектування." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3492,7 +3500,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3505,7 +3513,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3518,7 +3526,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3528,7 +3536,7 @@ msgstr "" "{ph0}{ph1} OpenCode{ph2}{ph3} , з відкритим кодом. Підключіть Постачальника " "моделі за вашим вибором." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3545,18 +3553,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Або запустіть програму налаштування самостійно" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Як відкрити термінал?" @@ -3565,7 +3573,7 @@ msgstr "Як відкрити термінал?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3581,7 +3589,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3595,7 +3603,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3610,7 +3618,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3620,7 +3628,7 @@ msgstr "" "Введіть команду за допомогою {ph0} {ph1} ( macOS : {ph2} {ph3}; Linux для " "терміналів: {ph4} {ph5} {ph6}), потім натисніть Enter." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3631,12 +3639,12 @@ msgstr "" "підключення MCP і відповідний навик дослідження, зберігаючи резервну копію " "існуючої конфігурації. Перед застосуванням змін програма запитує доступ." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Після завершення встановлення перезавантажте клієнт." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Як перезапустити клієнта?" @@ -3645,7 +3653,7 @@ msgstr "Як перезапустити клієнта?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3661,7 +3669,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3671,7 +3679,7 @@ msgstr "" "{ph0}Термінальні агенти{ph1} (Claude Code, Codex, Gemini CLI): вийдіть із " "сеансу та запустіть його знову." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3681,7 +3689,7 @@ msgstr "" "програми JavaScript або Electron ви можете почати з:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3691,12 +3699,12 @@ msgstr "" "Подивіться на {ph0} і дізнайтеся, як він експортує дані. Вкажіть точки " "входу, виклики та залежності, а також вихідні місця для Ваших результатів." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Замініть шлях на ваш локальний цільовий об'єкт." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Як отримати повний шлях до папки?" @@ -3705,7 +3713,7 @@ msgstr "Як отримати повний шлях до папки?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3720,7 +3728,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3732,7 +3740,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3742,17 +3750,17 @@ msgstr "" "{ph0}Будь-яка система:{ph1} перетягніть папку у вікно терміналу, і з'явиться" " шлях до неї." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "У терміналі вкладіть шлях, що містить пробіли, у лапки." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Використовуйте CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3761,14 +3769,14 @@ msgstr "" "Проаналізуйте папку Програми JavaScript або Electron або архів ASAR, не " "запускаючи програму:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Статичний аналіз додатків" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3778,13 +3786,13 @@ msgstr "" "Замініть шлях на каталог витягнутої Програми або файл {ph0}. У Windows тут " "працює шлях, наприклад {ph1}." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Де я можу знайти файл програми asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3795,7 +3803,7 @@ msgstr "Програми Electron зазвичай зберігають його #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3807,7 +3815,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3820,14 +3828,14 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} часто {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." @@ -3835,7 +3843,7 @@ msgstr "" "Деякі додатки встановлюються в іншому місці. Знайдіть у папці програми " "{ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3847,31 +3855,31 @@ msgstr "" "може вирішити." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Якщо ви хочете, щоб у вашій оболонці була постійна команда {ph0}:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Встановіть CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Продовжуйте читати посібник із застосування JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Налаштування аналізу програм з машинним кодом" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3881,12 +3889,12 @@ msgstr "" " налаштуйте один із наведених нижче інструментів, а потім вкажіть REA ваш " "виконуваний файл або бібліотеку." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Виберіть інструмент: Ghidra, Hopper або IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3898,17 +3906,17 @@ msgstr "" "потрібен власний декомпілятор для архітектури вашого хоста. Задайте шляхи " "перед запуском програми установки:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Підключіть вашу установку Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Підключення Ghidra * macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3919,12 +3927,12 @@ msgstr "" "і записує коректні настройки для обраного Вами клієнта. У Linux arm64 вам " "може знадобитися окремо зібрати власний декомпілятор Ghidra." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Підключіть Ghidra до Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3936,12 +3944,12 @@ msgstr "" "Використовуйте існуючу установку Ghidra 12.1.x і 64-розрядну версію JDK 21 " "або новіше:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Підключення Ghidra * Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3949,7 +3957,7 @@ msgstr "" "Замініть ці два шляхи на свої установки, а потім перегляньте план " "встановлення." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3959,7 +3967,7 @@ msgstr "" "встановлення; вона виявить існуючу установку або запропонує план " "встановлення для вашого схвалення." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3968,7 +3976,7 @@ msgstr "" "На macOS перед автоматичним аналізом виконайте перший запуск Hopper, " "вибравши демонстраційний режим або активацію ліцензії." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3979,7 +3987,7 @@ msgstr "" " для підключеного графічного інтерфейсу користувача або безголової бази " "даних. Аналіз Linux і macOS без урахування даних залишається неперевіреним." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Підключіть існуючу реєстрацію IDA MCP" @@ -3989,7 +3997,7 @@ msgstr "Підключіть існуючу реєстрацію IDA MCP" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4001,13 +4009,13 @@ msgstr "" "JSON. Також приймається існуючий {ph3}об'єкт mcpServers із записом {ph4}. " "Вкажіть REA у цьому файлі перед встановленням:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "Підключення IDA * Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4025,7 +4033,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4037,29 +4045,29 @@ msgstr "" "CLI. Для агента включіть {ph1} у середу реєстрації REA і виберіть IDA при " "відкритті двійкового файлу." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Для існуючого Налаштування Ghidra перевірте функцію за допомогою:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Функціональний аналіз" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "Замінивши {ph0} на ім'я функції або адресу, яку ви хочете перевірити." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Як працюють сеанси аналізу програм з машинним кодом" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4072,7 +4080,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4082,18 +4090,18 @@ msgstr "" "{ph0}Дотримуйтесь прикладу аналізу програм з машинним кодом{ph1}, щоб " "побачити, як результат функції призводить до відновленого обчислення." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Отримання допомоги" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Якщо ваш агент не бачить REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4103,27 +4111,27 @@ msgstr "" "Перезапустіть або підключіть клієнт після встановлення. Перевірте його " "REA-з'єднання з {ph0}; для Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Перевірте одного клієнта" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Якщо постачальник послуг потребує уваги" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Перевірте, яким провайдером ви користуєтесь. Для Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Перевірте одного постачальника" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "" @@ -4134,7 +4142,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4146,7 +4154,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4160,7 +4168,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4174,7 +4182,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4198,112 +4206,112 @@ msgstr "" "JavaScript або Electron з терміналу. Налаштування, перші Питання та " "інструкції для місцевих провайдерів." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Скопіюйте перевірку версії Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Скопіюйте команду встановлення Node.js для Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Скопіюйте команду політики виконання PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Скопіювати команду установки Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Скопіюйте команду встановлення fnm для macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Скопіюйте 24 команди Node.js для macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Скопіюйте команду встановлення fnm для Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Скопіюйте 24 команди Node.js для Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA Керівництво по початку роботи" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Скопіюйте запит на встановлення REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Команда Налаштування агента копіювання" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Скопіювати команду аналізу JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Скопіювати команду установки CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Скопіювати команду підключення Ghidra для macOS і Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Скопіюйте підключення Ghidra для Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Скопіюйте підключення IDA для Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Скопіювати команду аналізу власної функції" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Скопіювати команду діагностики клієнта" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Команда діагностики Постачальника копіювання" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -4312,20 +4320,20 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Керівництво{ph3} / Огляд браузера" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Подивимося, що станеться{ph0}коли ви натиснете." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4334,14 +4342,14 @@ msgstr "" "Використовуйте невеликий додаток браузера для підключення дії, його " "мережевого запиту та JavaScript, який створює завантаження." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "У цьому керівництві" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4349,7 +4357,7 @@ msgstr "{ph0}Навести приклад{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4357,7 +4365,7 @@ msgstr "{ph0}Відкрийте браузер{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4365,7 +4373,7 @@ msgstr "{ph0}Запитайте свого агента{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4373,13 +4381,13 @@ msgstr "{ph0}Захоплення з CLI{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Прочитайте запит і скрипт{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Що відбувається, коли ви натискаєте кнопку Експортувати?" @@ -4389,7 +4397,7 @@ msgstr "Що відбувається, коли ви натискаєте кно #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4401,7 +4409,7 @@ msgstr "" " натисканні на неї завантажується файл {ph4}, дві нотатки форматуються як " "CSV і починається завантаження." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Від кліка до завантаження CSV" @@ -4412,7 +4420,7 @@ msgstr "Від кліка до завантаження CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4428,7 +4436,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4446,7 +4454,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4456,17 +4464,17 @@ msgstr "" "{ph0}03 * ваш агент{ph1}{ph2} прочитав експортний код{ph3}{ph4}, що " "підключає спостережуваний запит до {ph5} в {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Запустіть запис, перш ніж натиснути кнопку Експортувати нотатки." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "Відкрийте Chrome з віддаленою налагодженням" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4475,21 +4483,21 @@ msgstr "" "Відкрийте хостинг-приклад Notes, використовуючи окремий профіль браузера та " "локальний порт для налагодження. На Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Запустіть приблизний браузер" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Копіювати" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4499,7 +4507,7 @@ msgstr "" " Windows . Ви можете замінити URL-адресу сторінки на іншу сторінку, яку ви " "хочете переглянути." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4508,7 +4516,7 @@ msgstr "" "REA підключається до цього існуючого браузера. Ви зберігаєте контроль над " "сторінкою, виконуєте дію та закриваєте браузер після завершення." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Попросіть свого агента Переглянути одну дію" @@ -4521,7 +4529,7 @@ msgstr "Попросіть свого агента Переглянути одн #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4533,7 +4541,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий аген #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4545,7 +4553,7 @@ msgstr "" "CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4555,7 +4563,7 @@ msgstr "" "Приклад запиту. Вкажіть своєму агенту кінцеву точку налагодження, {ph0} і " "URL-адреса сторінки. Нехай він запустить запис до того, як ви натиснете." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4566,23 +4574,23 @@ msgstr "" "отримані дані. Потім він може перевірити сценарій, що лежить в основі " "експорту." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Або захоплення з терміналу" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Знайдіть цільовий ідентифікатор сторінки:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Знайдіть потрібну сторінку" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4592,14 +4600,14 @@ msgstr "" "Виберіть цільовий об'єкт за допомогою URL-адреси, наведеної в прикладі " "Notes. Замінивши {ph0} нижче на його ідентифікатор, потім запустіть:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Зафіксуйте наступні десять секунд" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4610,7 +4618,7 @@ msgstr "" "\"{ph0}Експортувати нотатки{ph1}\"у цьому браузері. Результат з'явиться " "після завершення перегляду." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4621,49 +4629,49 @@ msgstr "" "цього вікна та форму відповіді у форматі JSON. Попередні запити не входять " "до цього списку." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Прочитайте запит і експортуйте скрипт" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Записано за допомогою REA 4.1.0 на прикладі local Notes" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Зафіксований факт" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Цінність" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Запит" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Відповідь" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Ініціатор запиту" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} · сценарій" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Структура відповіді" @@ -4671,19 +4679,19 @@ msgstr "Структура відповіді" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} з полями {ph1} і {ph2}" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Прочитайте завантажені скрипти" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4695,7 +4703,7 @@ msgstr "" "використовуються дані:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4708,7 +4716,7 @@ msgstr "" " цьому клацанні запитувався файл {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4720,7 +4728,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4745,65 +4753,65 @@ msgstr "" "браузера, зафіксуйте клацання, перегляньте запит і дотримуйтесь сценарію " "експорту." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Спостереження в браузері" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Скопіюйте та запустіть приклад браузера" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Запит на копіювання прикладу" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Скопіюйте знайдену сторінку" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Скопіюйте запис на наступні десять секунд" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Копіювати читати завантажені скрипти" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Перейти до змісту" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Головний{ph1} сторінка / Путівники" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "Напрямні REA." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4812,37 +4820,37 @@ msgstr "" "Проаналізуйте вбудовану функцію, експорт Electron або запит браузера. Кожен " "посібник містить підказку, код та результати." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Перше розслідування" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Налаштування REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Підключіть свій кодер або використовуйте REA з терміналу." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Почніть роботу з REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Програми з машинним кодом" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Відновлення розрахунку положення звуку зліва / справа" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4852,22 +4860,22 @@ msgstr "" "дотримуйтесь абонента, прочитайте Числові константи та перевірте відновлений" " C." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Керівництво по аналізу програм з машинним кодом" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript і Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Слідкуйте за експортом CSV" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4877,14 +4885,14 @@ msgstr "" "завантаження і основного процесу. Використовуйте REA для підключення API, " "каналу IPC та запису файлів." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "Керівництво по JavaScript і Electron" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4892,17 +4900,17 @@ msgstr "" "Щоб створити більший упакований додаток, скористайтеся {ph0}мостом " "буфера{ph1} обміну Notion." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Поведінка браузера" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Спостерігайте за клацанням" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4911,7 +4919,7 @@ msgstr "" "Відкрийте приклад working Notes, запишіть запит на експорт і знайдіть код, " "який перетворює його відповідь на завантаження." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Керівництво по спостереженню за браузером" @@ -4930,12 +4938,12 @@ msgstr "" "Вивчіть REA на коротких прикладах: власні обчислення, експорт Electron, CSV " "і запит з браузера." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -4944,7 +4952,7 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" @@ -4952,13 +4960,13 @@ msgstr "" "{ph0}Головний{ph1} сторінка / {ph2}Керівництво{ph3} / JavaScript і Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Простежте експорт Electron {ph0} CSV." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4967,14 +4975,14 @@ msgstr "" "Виконайте натискання кнопки на сторінці API, через Electron IPC, для запису " "файлів CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "У цьому керівництві" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4982,7 +4990,7 @@ msgstr "{ph0}Навести приклад{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4990,7 +4998,7 @@ msgstr "{ph0}Запитайте свого агента{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4998,7 +5006,7 @@ msgstr "{ph0}Відстеження експортного коду{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -5006,20 +5014,20 @@ msgstr "{ph0}Спробуйте на прикладі{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Перевірте пристрій запису CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "Куди дівається \"експорт нотаток\"?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5032,7 +5040,7 @@ msgstr "" "сторінці, виконується перехід до основного процесу і записується CSV . " "Поведінка розподілена по декількох файлах." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "Експорт CSV в рамках процесів Electron" @@ -5046,7 +5054,7 @@ msgstr "Експорт CSV в рамках процесів Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5063,7 +5071,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5081,7 +5089,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5094,13 +5102,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} форматує нотатки → {ph1} записує файли для {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5111,14 +5119,14 @@ msgstr "" "відкритий API. Шлях виводиться з коду; під час перехоплення під час " "виконання можна перевірити, що виконується." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Запитайте про експорт CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5136,14 +5144,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Копіювати" @@ -5154,7 +5162,7 @@ msgstr "Копіювати" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5165,7 +5173,7 @@ msgstr "" "експортую нотатки до цієї програми. Де створено CSV?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5173,7 +5181,7 @@ msgid "" "{ph0}." msgstr "Приклад запиту. Вкажіть абсолютний шлях до папки програми або {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5184,17 +5192,17 @@ msgstr "" "процесів. Ваш агент використовує цю карту, щоб звузити пошук до функції " "експорту." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Відстеження експортного коду" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Сторінка викликає невеликий API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5205,7 +5213,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5217,7 +5225,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5228,7 +5236,7 @@ msgstr "" "форматуються, і основний процес записує файл {ph1} в папку завантажень " "користувача." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5237,7 +5245,7 @@ msgstr "" "Записано за допомогою REA 4.1.0 на прикладі, який можна завантажити нижче. " "Розташування вихідних текстів відповідає висновкам API, каналу та обробника." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Проаналізуйте цей приклад самостійно" @@ -5245,25 +5253,25 @@ msgstr "Проаналізуйте цей приклад самостійно" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Приклад завантаження ZIP-файлу{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Перегляньте шість оригінальних файлів" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Статичний аналіз додатків" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5274,7 +5282,7 @@ msgstr "" " та один відповідний обробник у {ph0}. Місця розташування джерел вказані в " "{ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5285,13 +5293,13 @@ msgstr "" " шлях до ASAR. Агент може використовувати рядок літер, ІМ'Я API або канал " "IPC за допомогою інструментів відстеження функцій REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Перевірте пристрій запису CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5301,7 +5309,7 @@ msgstr "" "Випливати {ph0} в його обробник. Які вхідні дані надходять до CSV writer і " "що станеться, якщо запис файлу не вдасться?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5316,7 +5324,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5330,7 +5338,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5344,7 +5352,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5370,32 +5378,32 @@ msgstr "" "завантаження та обробника IPC за допомогою REA. Включає завантажувані файли " "прикладів і перевірений результат аналізу." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript і Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Запит на копіювання прикладу" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Копіювання статичного аналізу програми" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -5404,7 +5412,7 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5413,13 +5421,13 @@ msgstr "" "машинним кодом" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "Відновити дані DX-Ball{ph0}розрахунок положення звуку зліва / справа." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5428,14 +5436,14 @@ msgstr "" "Перегляньте оригінальні інструкції, визначте вхідні дані та константи, а " "потім перевірте відновлений C." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "У цьому керівництві" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5443,7 +5451,7 @@ msgstr "{ph0}Навести приклад{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5451,7 +5459,7 @@ msgstr "{ph0}Запитайте свого агента{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5459,7 +5467,7 @@ msgstr "{ph0}Ознайомтеся з результатами REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5467,18 +5475,18 @@ msgstr "{ph0}Відновіть і перевірте{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Використовуйте власний двійковий файл{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Розрахувати розташування стереозвуку зліва / справа" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5489,7 +5497,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5501,7 +5509,7 @@ msgstr "" "функції {ph1}. REA також повертає свої інструкції та пристрої виклику, які " "дають агенту можливість знайти відсутню арифметику." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Ви знайомі з цими умовами?" @@ -5510,7 +5518,7 @@ msgstr "Ви знайомі з цими умовами?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5522,7 +5530,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5535,7 +5543,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5548,7 +5556,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5560,7 +5568,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5570,7 +5578,7 @@ msgstr "" "{ph0}Константа:{ph1} фіксовані числа, що зберігаються в програмі, зчитуються" " як необроблені байти та декодуються." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Три докази, один розрахунок" @@ -5581,7 +5589,7 @@ msgstr "Три докази, один розрахунок" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5598,7 +5606,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5616,7 +5624,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5626,7 +5634,7 @@ msgstr "" "{ph0}03 * байти даних{ph1}{ph2} Числова константа{ph3}{ph4}, на які " "посилаються байти, декодуються як {ph5}, {ph6} і масштабне значення.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5635,7 +5643,7 @@ msgstr "" "REA надає інструкції, зв'язок між викликами функцій і байти. Агент " "інтерпретує їх разом." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Запитайте про поведінку" @@ -5644,7 +5652,7 @@ msgstr "Запитайте про поведінку" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5655,19 +5663,19 @@ msgstr "" "інструменту аналізу програм з машинним кодом{ph3} надайте локальний " "виконуваний файл та запитання:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Який інструмент аналізу слід використовувати?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA потрібен один з них для читання власних програм:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5681,7 +5689,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5694,7 +5702,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5704,7 +5712,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5720,14 +5728,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Копіювати" @@ -5738,7 +5746,7 @@ msgstr "Копіювати" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5748,7 +5756,7 @@ msgstr "" "{ph0}\"{ph1}{ph2}Використовуйте REA, щоб дізнатися, як DX-Ball обчислює " "розташування стереозвуку. Поясніть розрахунок і покажіть код.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5759,7 +5767,7 @@ msgstr "" "DX-Ball 1.07. REA не включає DX-Ball, тому використовуйте власну копію або " "задайте те саме питання про іншу невелику програму Windows, яку ви маєте." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Як отримати повний шлях до файлу?" @@ -5768,7 +5776,7 @@ msgstr "Як отримати повний шлях до файлу?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5783,7 +5791,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5795,7 +5803,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5805,17 +5813,17 @@ msgstr "" "{ph0}Будь-яка система:{ph1} перетягніть файл у вікно терміналу, і з'явиться " "шлях до нього." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Ознайомтеся з результатами REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Прочитайте вхідні дані" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5824,13 +5832,13 @@ msgstr "" "Інструкції завантажують цілий аргумент і перетворюють його в арифметику з " "плаваючою комою. Це вхідні дані, відсутні в першому поданні псевдокоду." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Слідуйте за абонентом" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5841,12 +5849,12 @@ msgstr "" "координату плитки множили на 30; додавання {ph0} (20) дає положення цегли на" " екрані." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Прочитайте зазначені константи" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5856,12 +5864,12 @@ msgstr "" "фактичні значення; порядок команд повідомляє агенту, як вони " "використовуються." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Запишіть і перевірте відновлену функцію" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5872,7 +5880,7 @@ msgstr "" "до перетворення в ціле число. При обчисленні центр екрану виявляється в " "центрі стереополя." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5885,20 +5893,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Дивіться повне дослідження та порівняння збірки з C{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Спробуйте це за допомогою власного двійкового коду" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5912,7 +5920,7 @@ msgstr "" "для вивчення. Корисні початкові запитання включають “як обробляється цей " "файл?\"або\" яка функція виконує цю дію в меню?”." -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5921,13 +5929,13 @@ msgstr "" "Якщо ви вже знаєте назву функції або адресу, ви можете запитати її з " "терміналу. Для налаштованої установки Ghidra:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Функціональний аналіз" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5941,7 +5949,7 @@ msgstr "" "сеанс. Запити вашого агента MCP повторно використовують імпортований " "двійковий файл, поки цей сеанс відкритий." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5965,50 +5973,50 @@ msgstr "" "Відновіть власні обчислення за допомогою REA: перегляньте інструкції, " "дотримуйтесь абонента, прочитайте константи та перевірте відновлений C." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Аналіз програм з машинним кодом" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Запит на копіювання прикладу" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Аналіз функції копіювання" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Перейти до змісту" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Налаштування REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -6016,7 +6024,7 @@ msgstr "{ph0}Налаштування REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -6024,7 +6032,7 @@ msgstr "{ph0}Що таке вогонь?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6032,7 +6040,7 @@ msgstr "{ph0}Як допомагає REA{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6040,7 +6048,7 @@ msgstr "{ph0}Гра в динозаврів{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6048,7 +6056,7 @@ msgstr "{ph0}Калькулятор{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6056,7 +6064,7 @@ msgstr "{ph0}Спробуйте REA{ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6064,7 +6072,7 @@ msgstr "{ph0}Дізнатися більше{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6072,25 +6080,25 @@ msgstr "{ph0}Допомога та зворотній зв'язок{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Товариство{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Зворотне проектування за допомогою агента кодування" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Дізнайтеся, як{ph0}працює програма." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6101,7 +6109,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6109,13 +6117,13 @@ msgstr "Вже знайомі з RE? {ph0}Перейти до посібникі #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Хочете копнути глибше? {ph0}Читати блог →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Вставте цей запит у свого ШІ-помічника для програмування:" @@ -6128,38 +6136,38 @@ msgstr "Вставте цей запит у свого ШІ-помічника #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Копіювати" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Або виконайте цю команду в терміналі:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Перевірте й схваліть план змін, а потім перезапустіть помічника." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Що таке зворотна розробка?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6174,7 +6182,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6186,7 +6194,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6194,7 +6202,7 @@ msgstr "До REA · Ви досліджуєте {ph0}самостійно{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6202,7 +6210,7 @@ msgstr "{ph0}01{ph1} Декодування гілок" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6210,7 +6218,7 @@ msgstr "{ph0}02{ph1} Відстеження викликів" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6220,20 +6228,20 @@ msgstr "{ph0}03{ph1} Відновіть правило" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Оригінальні вибрані інструкції для x64 ·{ph1}{ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * в якій філії?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6243,29 +6251,29 @@ msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Два переходи в одне і те ж місце. Що це за " "оператори?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Знайдіть ідентифікатори команд, а потім позначте гілку." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Розділити ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Помноживши ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Що роблять викликані функції?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6275,24 +6283,24 @@ msgstr "" "\"100-це чисто. Дзвінки-це лише адреси. {ph0}Який з них ділиться? Яке " "значення входить в?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Перевірте допоміжні функції та простежте збережені значення." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Діливши" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * яке це правило?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6302,19 +6310,19 @@ msgstr "" "\"Цей шлях множиться на інші вхідні дані. Таким чином, {ph0}10% означає 10% " "від 200{ph1} після +”." -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Назвіть операнди та перевірте обидва шляхи до операторів." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Наочне міркування експерта" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6326,20 +6334,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "З REA · Ви запитуєте {ph0}свого помічника{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Лише один запит." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6353,21 +6361,21 @@ msgstr "Запитайте помічника {ph0}звичайними слов #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "" "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Приклад підказки * Калькулятор" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Приклад відповіді * заснований на результатах дослідження" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6375,29 +6383,29 @@ msgid "" msgstr "" "Після + кнопка % виводить {ph0}процентне значення від першого числа.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA надає" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Інструкції обробника, декомпільований код та виклики." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Помічник пояснює" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Яка гілка застосовується, що вона обчислює і як її перебудувати." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6410,7 +6418,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6420,37 +6428,37 @@ msgstr "" "{ph0}Давайте розглянемо два приклади.{ph1} Змініть швидкість гри, потім " "поверніться до калькулятора та відновіть його кнопку %." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Приклад 01 * гра в динозаврів Chrome" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Чому динозавр прискорюється?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Мета" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Перебудовуйте гру з {ph0}регульованою швидкістю.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Навіщо його перепроектувати?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6461,49 +6469,49 @@ msgstr "" "грі{ph1}: як швидко воно починається, наскільки збільшується і коли " "припиняється." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Грати у відтворену версію" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Грати" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Стрибок ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Почати знову" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Швидкість" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Використовуйте правило відновленого прискорення" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Початкове правило: починайте з 6, потім збільшуйте до 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Перемістіть повзунок, щоб встановити власну швидкість. Пробіл або стрибок " "прибирають кактус." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6512,14 +6520,14 @@ msgstr "" "Увімкніть JavaScript для відтворення реконструкції. Наведений вище код та " "пояснення залишаються читабельними." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA повернув" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6538,7 +6546,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6551,7 +6559,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6565,7 +6573,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6578,7 +6586,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6588,12 +6596,12 @@ msgstr "" "{ph0}Почніть з 6.{ph1} Додавайте 0,001 при кожному оновленні без збоїв, поки" " швидкість нижче 13.{ph2}{ph3}{ph4}{ph5}" -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Відкрийте лабораторію швидкості →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Що робить кожна частина" @@ -6604,7 +6612,7 @@ msgstr "Що робить кожна частина" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6620,7 +6628,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6637,7 +6645,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6647,13 +6655,13 @@ msgstr "" "{ph0}03 * ви{ph1}{ph2} міняєте швидкість і граєте{ph3}{ph4} з оригінальним " "прискоренням, потім вибираєте свій власний темп.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Ознайомтеся зі сценарієм, перевірками та як спробувати аналіз" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6663,7 +6671,7 @@ msgstr "" "REA перевірив версію браузера HTTP через локальне з'єднання Налагодження та " "повернув завантажений {ph0}, включаючи його вихідний код та дайджест." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6677,7 +6685,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6694,7 +6702,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6712,7 +6720,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6721,19 +6729,19 @@ msgstr "" "{ph0}Перевірений код швидкості{ph1} · {ph2}Автори Chromium * Ліцензія " "BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Приклад 02 * Калькулятор Windows" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Відтворіть кнопку % калькулятора." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6744,7 +6752,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6755,29 +6763,29 @@ msgstr "" "перевіряємо встановлене додаток, щоб визначити, до якого числа " "застосовується процентне співвідношення." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Спробуйте зробити розрахунок" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Скинути" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% від 200 = 20. Тоді 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Інтерактивна ілюстрація перевіряється процентного правила." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6789,7 +6797,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6803,7 +6811,7 @@ msgstr "У цьому прикладі {ph0}, а {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6819,7 +6827,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6831,7 +6839,7 @@ msgstr "" "Windows. Відновіть правила після + і×, а потім створіть невеликий " "калькулятор, який використовує обидва параметри.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Со +" @@ -6839,13 +6847,13 @@ msgstr "Со +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Візьмемо 10% від першого числа.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Со ×" @@ -6853,13 +6861,13 @@ msgstr "Со ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Перетворіть 10% на 0,1200{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Від встановленого додатка до робочої кнопки %" @@ -6871,7 +6879,7 @@ msgstr "Від встановленого додатка до робочої к #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6888,7 +6896,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6900,12 +6908,12 @@ msgstr "" "правила{ph3}{ph4}, звіряє гілку з вихідним кодом Microsoft, а потім " "спробуйте + і × вище.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Подивіться реальний код і те, як була перевірена відповідь" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6926,7 +6934,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6936,17 +6944,17 @@ msgstr "" "{ph0}Відсоток реалізації{ph1} · {ph2}Тестові приклади Microsoft{ph3} * " "Керівництво по {ph4}вбудованої налаштуванні{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Ваше перше розслідування" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Спробуйте REA у невеликому додатку." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6955,12 +6963,12 @@ msgstr "" "Завантажте наш приклад Notes, простежте його експорт CSV і перевірте один " "змінений вхід." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Спробуйте керуватися наведеним прикладом" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Хочете дізнатися більше?" @@ -6969,7 +6977,7 @@ msgstr "Хочете дізнатися більше?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6989,13 +6997,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Приклад запиту * Веб-сайт" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Так, ось цей." @@ -7008,7 +7016,7 @@ msgstr "Так, ось цей." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7022,7 +7030,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7036,24 +7044,24 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Дивіться тематичне дослідження DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "" "Для виконання етапів настройки і аналізу виберіть свій цільовий об'єкт:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Програми з машинним кодом" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7062,17 +7070,17 @@ msgstr "" "Перевірте функції, рядки, посилання та зв'язки між викликами функцій у " "виконуваних файлах та бібліотеках." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Керівництво по аналізу програм з машинним кодом" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript і Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7081,17 +7089,17 @@ msgstr "" "Відображайте модулі, маршрути, IPC та власні залежності з папки програми або" " архіву ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Робочі процеси додатків" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Активність у браузері та під час виконання" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7100,12 +7108,12 @@ msgstr "" "Фіксуйте активність обраного браузера або процесу, а потім порівнюйте " "результати в різних запусках." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Керівництво по спостереженню за браузером" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Маєте запитання?" @@ -7116,7 +7124,7 @@ msgstr "Маєте запитання?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7127,12 +7135,12 @@ msgstr "" " Discord{ph3} або {ph4}відкрийте випуск{ph5} GitHub, щоб дізнатися про " "помилки та запити функцій." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Приєднатися до спільноти" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7156,27 +7164,27 @@ msgstr "" "агента кодування. Дотримуйтесь чітких інструкцій та спробуйте інтерактивні " "приклади з REA." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Скопіюйте запит на встановлення REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Команда Налаштування Копіювання" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Дотримуйтесь інструкцій ручного калькулятора для аналізу" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Процентне питання калькулятора копіювання" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7185,37 +7193,37 @@ msgstr "" "Міні-гра про динозаврів. Використовуйте кнопку переходу або натисніть " "пробіл, поки гра зосереджена." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Запит на копіювання результатів аналізу динозаврів" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Виберіть спосіб розрахунку" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Запит на аналіз за допомогою калькулятора копіювання" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Запит на копіювання проекту веб-сайту" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Запит на копіювання реконструкції гри" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -7224,25 +7232,25 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Вітрина{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Практичний приклад * аутентифікатор Aegis" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Звідки Аутентифікатор{ph0}генерувати код авторизації?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7252,17 +7260,17 @@ msgstr "" " обчислення в Android APK, а потім відновіть їх за допомогою годинника, яким" " ви можете керувати." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * офіційний реліз APK * 6,9 МБ" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Переглянути Aegis на GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "Від APK до коду, який ви можете відтворити" @@ -7273,7 +7281,7 @@ msgstr "Від APK до коду, який ви можете відтворит #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7291,7 +7299,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7309,7 +7317,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7321,14 +7329,14 @@ msgstr "" "Ознайомтеся з кодом.{ph3}{ph4}Нова демонстрація браузера відтворює правило і" " перевіряє його на відповідність загальнодоступним посиланням.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "У цьому тематичному дослідженні" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7336,7 +7344,7 @@ msgstr "{ph0}Запитайте свого агента{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7344,7 +7352,7 @@ msgstr "{ph0}Спробуйте скористатися генератором #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7352,7 +7360,7 @@ msgstr "{ph0}Знайдіть код за допомогою REA{ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7360,7 +7368,7 @@ msgstr "{ph0}Ознайомтеся з розрахунком{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7368,20 +7376,20 @@ msgstr "{ph0}Перевірте реконструкцію{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Перевірте APK самостійно{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Запитайте свого агента" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7399,21 +7407,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Копіювати" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7423,14 +7431,14 @@ msgstr "" "Приклад запиту для завантаженого APK з налаштованим аналізом REA для " "Android. {ph0}Отримайте APK і налаштування аналізу ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Спробуйте скористатися генератором коду" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7442,33 +7450,33 @@ msgstr "" "блоку об'єднується з ключем облікового запису. Один і той же ключ і блок " "генерують один і той же код." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Переведіть стрілки годинника на 60 секунд вперед" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Час" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "секунда" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Наші регульовані зразкові годинник" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30-секундний блок" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Блок" @@ -7477,35 +7485,35 @@ msgstr "Блок" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 секунд{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Згенерований код" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Ключ облікового запису + блокування → шість цифр" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Приблизний час, в секундах" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 секунд" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 секунд" @@ -7514,7 +7522,7 @@ msgstr "60 секунд" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7526,7 +7534,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7536,7 +7544,7 @@ msgstr "" "Ключ є фіксованим, загальнодоступні {ph0}тестові дані RFC 6238{ph1}. У " "демонстрації реалізований розрахунок, відновлений з APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " @@ -7545,18 +7553,18 @@ msgstr "" "На діаграмі показано результат за 59 секунд. Увімкніть JavaScript, щоб " "змінити час." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Знайдіть код за допомогою REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Скоротіть APK до трьох класів" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7567,14 +7575,14 @@ msgstr "" "індикатора виконання та імпортованих облікових записів. TOTP означає " "одноразовий пароль на основі часу." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Підключіть генератор до дисплея програми" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7585,7 +7593,7 @@ msgstr "" "метод. При перевірці {ph0} на дисплеї відображається виклик {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7595,14 +7603,14 @@ msgstr "" "Запити показують скорочений шлях введення. В іменах результуючих КЛАСІВ " "відсутній поширений префікс {ph0}." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Ознайомтеся з розрахунком" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7616,7 +7624,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7624,7 +7632,7 @@ msgstr "{ph0}Часовий блок 01{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7632,7 +7640,7 @@ msgstr "{ph0}02{ph1} Клавіша + блок" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7640,7 +7648,7 @@ msgstr "{ph0}03{ph1} Шість цифр" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7652,7 +7660,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7666,7 +7674,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7680,7 +7688,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7691,7 +7699,7 @@ msgstr "" "відображення. Права панель являє собою пояснювальне резюме. {ph0}Код Aegis " "відповідає GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Всередині генератора" @@ -7700,7 +7708,7 @@ msgstr "Всередині генератора" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7710,7 +7718,7 @@ msgstr "" "Випущений APK перекладає {ph0} в {ph1}. REA слідує за викликом з {ph2} і " "повертає це тіло; оригінальне джерело викликає допоміжне {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7727,20 +7735,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}Порівняйте з відповідним джерелом випуску{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Перевірте реконструкцію" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7753,29 +7761,29 @@ msgstr "" "прикладів{ph1}, включаючи межі тимчасових блоків і коди, що починаються з " "нуля." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Приблизний час" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Шестизначний код" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 секунд" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 секунди" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7785,17 +7793,17 @@ msgstr "" "Генератор також відповідає шести опублікованим посилальним варіантам SHA-1 в" " {ph0}RFC 6238{ph1}. Перевірте їх реалізацію в браузері:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Виконувати перевірку посилань" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Ознайомтеся з демонстраційним розрахунком" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7804,7 +7812,7 @@ msgstr "" "У контрольних випадках використовуються восьмизначні значення. Перевірка " "також підтверджує їх шестизначні результати." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7813,14 +7821,14 @@ msgstr "" "Для перевірки використовуються витягнуті методи Java та нова демонстрація. " "Android APK був перевірений статично." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Перевірте APK самостійно" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7832,7 +7840,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7842,18 +7850,18 @@ msgstr "" "Для аналізу Android потрібен повний JDK 17 або новішої версії. Виберіть його" " за допомогою {ph0} або {ph1}. У цьому випадку використовувався JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Наведіть курсор REA на файл постачальника та перевірте APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7866,7 +7874,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7876,7 +7884,7 @@ msgstr "" "Наступне питання: {ph0}що відбувається, коли в обліковому записі " "використовуються вісім цифр або інший інтервал часу?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Джерело" @@ -7892,7 +7900,7 @@ msgstr "Джерело" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7906,7 +7914,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" @@ -7914,7 +7922,7 @@ msgstr "" "{ph0}Довідкові приклади RFC 6238{ph1} · {ph2}Демонстраційні тестові " "дані{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7939,37 +7947,37 @@ msgstr "" "Перевірити Aegis Андроїд APK з REA, відновити його шестизначний логін-код " "розрахунків і спробувати реконструкція з регульованим годинник." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Тематичне дослідження Aegis APK" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Скопіювати запит як приклад Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Дотримуйтесь інструкцій щодо введення реєстраційного коду" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Скопіювати команду перевірки APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -7978,26 +7986,26 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Вітрина{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Тематичне дослідження * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Знайдіть прапор у{ph0}двійковому форматі CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8007,19 +8015,19 @@ msgstr "" "Використовуйте REA для перевірки невеликого засобу перевірки прапорів, " "перетворіть його правила в рівняння та знайдіть вхідні дані, які {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "" "пристрій для перевірки прапорців в маскованих квадратах * просте * Linux " "x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Перегляньте оригінальну задачу" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Від двійкового коду до перевіреної відповіді" @@ -8030,7 +8038,7 @@ msgstr "Від двійкового коду до перевіреної від #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8048,7 +8056,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8066,7 +8074,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8078,21 +8086,21 @@ msgstr "" "виправити!{ph3}{ph4}Рівняння вирішуються сценарієм Python. REA фіксує " "вихідну програму, яка приймає результат.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "" "Завдання написано Джозефом і опубліковано в офіційному сховищі DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "У цьому тематичному дослідженні" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8100,7 +8108,7 @@ msgstr "{ph0}Знайдіть код підтвердження{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8108,7 +8116,7 @@ msgstr "{ph0}Прочитайте одну маску{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8116,7 +8124,7 @@ msgstr "{ph0}Збірка в читається код{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8124,7 +8132,7 @@ msgstr "{ph0}Розв'яжіть рівняння{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8132,20 +8140,20 @@ msgstr "{ph0}Перевірте відповідь{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Спробуйте самі{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Знайдіть код підтвердження" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8164,17 +8172,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Копіювати" @@ -8185,7 +8193,7 @@ msgstr "Копіювати" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8197,7 +8205,7 @@ msgstr "" "прапора. Поясніть, як працюють перевірки, а потім перевірте відповідь за " "допомогою оригінальної програми.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8206,12 +8214,12 @@ msgstr "" "Приклад запиту із завантаженим завданням, доступним локально, та підключеним" " постачальником програм для аналізу машинного коду." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Дотримуйтесь інструкцій щодо введення, щоб перейти до його функції" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8220,14 +8228,14 @@ msgstr "" "Посилання дає агенту можливість провести розслідування, навіть незважаючи на" " те, що оригінальні імена функцій виконуваного файлу були видалені." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Ознайомтеся з програмою перевірки і двома її помічниками" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8239,7 +8247,7 @@ msgstr "" "підсумовує вибрані коди та порівнює результат із збереженим числом. Його " "кроки розміром {ph0} байт по {ph1} байт дають 26 масок." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8249,12 +8257,12 @@ msgstr "" "об'єкта скорочено для відображення; адреси стосуються імпортованого " "зображення REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Одна перевірка виявляє один символ" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8268,7 +8276,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." @@ -8276,7 +8284,7 @@ msgstr "" "При сьомій перевірці вибирається тільки одна позиція. {ph0}Відкрийте " "малюнок{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Порахуйте маску та її ціль із двійкового файлу" @@ -8285,7 +8293,7 @@ msgstr "Порахуйте маску та її ціль із двійковог #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8297,12 +8305,12 @@ msgstr "" "означає -21. Метою є ціле число в порядку убування. Разом ці байти " "повідомляють агенту, що {ph2}, так що цей символ дорівнює {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Від інструкцій до читабельного чеку" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8313,7 +8321,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8321,7 +8329,7 @@ msgstr "{ph0}01{ph1} Почавши" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8329,7 +8337,7 @@ msgstr "{ph0}02{ph1} Вибрати" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8337,7 +8345,7 @@ msgstr "{ph0}03{ph1} Додавши" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8345,18 +8353,18 @@ msgstr "{ph0}04{ph1} Просування" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} Порівнювати" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * вибрані оригінальні інструкції" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Читабельний підсумок C * one-check" @@ -8364,7 +8372,7 @@ msgstr "Читабельний підсумок C * one-check" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8372,7 +8380,7 @@ msgstr "{ph0}01 * почніть з нуля.{ph1} {ph2} містить пото #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8384,7 +8392,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8396,7 +8404,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8410,7 +8418,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8420,7 +8428,7 @@ msgstr "" "{ph0}05 * порівняти зі збереженим цільовим значенням.{ph1} Абонент отримує " "суму в {ph2}. Невідповідність стає {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8430,12 +8438,12 @@ msgstr "" "пристрою. C - це пояснювальна записка з описовими назвами та згладженим " "циклом із 36 клітинок." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Розв'яжіть 26 рівнянь" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8447,13 +8455,13 @@ msgstr "" "Перекриваються вибірки дають рівняння, які може вирішити невеликий скрипт " "Python." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Уривок з Python * solver" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8467,19 +8475,19 @@ msgstr "" "{ph0} з буквами, цифрами, символами підкреслення і фігурними дужками. Повне " "завантаження включає всі 26 масок і цільових об'єктів." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Завантажте повний вирішувач" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Перевірте відповідь за допомогою оригінальної програми" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8492,47 +8500,47 @@ msgstr "" "призводить до отримання першої суми 1440 замість 1441, і програма відхиляє " "її." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Уведення" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Спостережуваний результат" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Код виходу" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Прапор вирішувача" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Один персонаж змінено" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Відобразити відновлений прапор і захоплені вихідні дані" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * вихідний програмний результат" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Прапор копіювання" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8541,12 +8549,12 @@ msgstr "" "Відновлене значення також відповідає прапору в опублікованих організаторами " "метаданих задачі, який був перевірений після вирішення двійкової задачі." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Ідентифікація джерела, цілі та деталі аналізу" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8557,7 +8565,7 @@ msgstr "" "використовуючи REA 4.1.0 та Ghidra 12.1.4 на Linux x64. Двійковий файл являє" " собою урізаний x86-64 ELF, об'ємом 15 248 байт." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8580,7 +8588,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8590,12 +8598,12 @@ msgstr "" "{ph0}Порівняйте з джерелом, наданим організаторами{ph1} · {ph2}Метадані та " "прапор конкурсу{ph3} · {ph4}Примітки до доказів REA{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Спробуйте самі" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8605,13 +8613,13 @@ msgstr "" "наведеною вище інструкцією, щоб провести розслідування за допомогою свого " "агента, або запустіть доданий сценарій." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Термінал * вирішити і запустити" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8623,7 +8631,7 @@ msgstr "" " Для вирішення потрібен Python і {ph0}. Для запуску оригінального " "виконуваного файлу потрібен Linux x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Налаштуйте REA за допомогою агента кодування" @@ -8644,27 +8652,27 @@ msgstr "" "квадратів у DOWNDERCTF. Знайдіть функції перевірки, витягніть маски та " "порівняйте відновлений прапор з оригінальною програмою." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "Практичний приклад перевірки прапорів CTF" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Запит на копіювання прикладу CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "Рівняння маски CTF; горизонтальна прокрутка на менших екранах" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8675,42 +8683,42 @@ msgstr "" "Тільки ця комірка вносить свій внесок у суму. Її обов'язковий код-55, що " "означає, що символ дорівнює 7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Виконайте перевірку CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Скопіюйте збірку CTF" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Копіюваний чек CTF для читання" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Скопіюйте витяг із CTF-вирішувача" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Копіювати відновлений прапор" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Копіювання команд вирішувача CTF" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -8719,25 +8727,25 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Вітрина{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Тематичне дослідження * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "Відновлюємо DX-Ball {ph0}з його виконуваного файлу." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8747,14 +8755,14 @@ msgstr "" "1996 році. REA допомагає агенту перевіряти оригінал, по одній функції за " "раз." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows для i386 · s * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8766,14 +8774,14 @@ msgstr "" "викликають пристрої і дані для читання; проект реконструкції реалізує і " "тестує результат. {ph0}Відкрити малюнок{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "У цьому тематичному дослідженні" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8781,7 +8789,7 @@ msgstr "{ph0}Проект{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8789,7 +8797,7 @@ msgstr "{ph0}Звукова панорама{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8797,23 +8805,23 @@ msgstr "{ph0}Перевірка результату{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Продовжуйте роботу{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "підтримувані функції C" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "порівняння з вихідним кодом" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "функції з відповідними скомпільованими байтами" @@ -8824,7 +8832,7 @@ msgstr "функції з відповідними скомпільованим #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8834,12 +8842,12 @@ msgstr "" "Контрольна точка проекту: 7 жовтня 2026 року. {ph0}Журнал виконання{ph1} " "роботи · {ph2}Тестове покриття{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Проект досі" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8853,12 +8861,12 @@ msgstr "" " перевірки та бібліотека аналізу. Триває робота над грою, в яку можна грати," " фізикою м'яча і весла, управлінням посиленнями і інтеграцією Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Визначення положення звуку зліва / справа при розрахунку" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8877,17 +8885,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Копіювати" @@ -8898,7 +8906,7 @@ msgstr "Копіювати" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8908,7 +8916,7 @@ msgstr "" "{ph0}\"{ph1}{ph2}Використовуйте REA, щоб дізнатися, як DX-Ball обчислює " "розташування стереозвуку. Поясніть розрахунок і покажіть код.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8919,7 +8927,7 @@ msgstr "" "файлом. У наведеному нижче дослідженні Показані запити REA та докази, що " "лежать в основі відповіді." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8933,7 +8941,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8947,12 +8955,12 @@ msgstr "" "операції з плаваючою комою. Ця невідповідність дала агенту конкретну причину" " продовжувати розслідування." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "Перше представлення декомпілятора" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8962,18 +8970,18 @@ msgstr "" "інструкцій можна побачити вхідні дані і обчислення, які використовуються для" " цього виклику." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Відповіді на три запитання за допомогою REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Відновіть відсутні вхідні дані" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8984,14 +8992,14 @@ msgstr "" " елементами. Тут {ph0} забезпечує цілочисельний вхід, відсутній у поданні " "декомпілятора." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Слідкуйте за абонентом, щоб зрозуміти введені дані" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9002,12 +9010,12 @@ msgstr "" "tile_x масштабується {ph0}на 30; додавання 20 дає екранну координату цегли, " "{ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Порахуйте значення, що стоять за адресами пам'яті" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -9016,12 +9024,12 @@ msgstr "" "Повернені байти задають дві арифметичні константи та початковий масштаб " "панорамування. Тепер агент має значення, необхідні для вираження мовою Сі." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "Від штифтів REA до C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -9032,7 +9040,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -9040,7 +9048,7 @@ msgstr "{ph0}Вхід 01{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -9048,7 +9056,7 @@ msgstr "{ph0}02{ph1} Помноживши" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9056,7 +9064,7 @@ msgstr "{ph0}03{ph1} Віднявши" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9064,18 +9072,18 @@ msgstr "{ph0}Шкала 04{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Повернення" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Оригінальний витяг з x86 ·" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Реконструйований C" @@ -9085,7 +9093,7 @@ msgstr "Реконструйований C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9105,7 +9113,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9122,7 +9130,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9140,7 +9148,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9157,7 +9165,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9170,7 +9178,7 @@ msgstr "" "результат у {ph4}; оригінальні порівняння з x86 перевіряють повернене " "значення." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9181,23 +9189,23 @@ msgstr "" "арифметики та повернення. У наведений нижче повний список також включені " "проміжні сховища, настройка і очищення функцій." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Повна збірка та підтверджуючі докази" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "Результат REA · 0X406400–0X40643E" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Що надає Абонент" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9207,54 +9215,54 @@ msgstr "" "Функція brick-hit в {ph0} масштабує координату плитки на 30, додає 20, а " "потім переміщує її перед викликом:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Те, що читають дані, встановлює" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "Зчитується байт REA, декодується як подвоєння в порядку убування" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Адрес" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Цінність" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Використовується для" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Перше множення" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Віднімання" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} споконвічно" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Збережені ваги для піддонів" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9270,7 +9278,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9280,12 +9288,12 @@ msgstr "" "{ph0}Підтримуване джерело{ph1} · {ph2}Примітки щодо розслідування та " "посилання на докази{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Перевірка відновленої функції" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9295,12 +9303,12 @@ msgstr "" "збігаються з вихідними, а скомпільовані байти відповідають виконуваному " "файлу." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3 205 випадків порушення поведінки" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9311,12 +9319,12 @@ msgstr "" "повертає, із збереженим значенням C. Вони охоплюють усі цілі позиції від 0 " "до 640 у п'яти масштабах панорамування: 0, 0,5, 1, 20 та -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 збігаються байти" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9327,7 +9335,7 @@ msgstr "" "VC4.0. Повторне відтворення компілятором відповідає повній функції після " "застосування розглянутих змін і перевірки констант, на які дано посилання." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9342,18 +9350,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Ознайомтеся з подробицями відтворення компілятором{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Продовжуйте розслідування" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9364,7 +9372,7 @@ msgstr "" "розширенням та генерування бонусів: перевірте відповідні функції, відновіть " "їх стан та залежності, а потім порівняйте реалізацію з оригінальною." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9374,7 +9382,7 @@ msgstr "" "інструкцій з налаштування DX-Ball project і вкажіть відповідну вихідну мету." " Потім запустіть:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "При оформленні замовлення DX-Ball" @@ -9383,7 +9391,7 @@ msgstr "При оформленні замовлення DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9397,7 +9405,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9413,7 +9421,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9438,7 +9446,7 @@ msgstr "" "підтримуваних тестів на C, вихідних x86 і зіставлення скомпільованих байтів " "функцій." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" @@ -9446,7 +9454,7 @@ msgstr "" "DX-Ball sound - дослідження панорамування; горизонтальна прокрутка на менших" " екранах" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9462,70 +9470,70 @@ msgstr "" "від вихідного x86 в 3205 випадках і за допомогою компілятора VC4.0 " "відтворюється на відповідність 63 байтам." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Тематичне дослідження реконструкції DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Запит на копіювання прикладу" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Слідкуйте за розрахунком положення звуку зліва / справа" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Скопіюйте фрагмент оригінальної збірки" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Функція копіювання звуку-панорамування" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Скопіюйте повну збірку sound-pan" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Скопіювати команду аналізу DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Перейти до змісту" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Головний{ph1} сторінка / вітрини" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "Тематичні дослідження REA." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9534,17 +9542,17 @@ msgstr "" "Android, ігри, Electron і конкурс CTF з кодом, цифрами і перевіреними " "результатами." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * аналіз APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Як аутентифікатор генерує код входу" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9556,22 +9564,22 @@ msgstr "" "демонстраційний годинник, щоб зрозуміти, чому код змінюється кожні 30 " "секунд." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Ознайомтеся з тематичним дослідженням Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * аналіз програм з машинним кодом" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Вирішіть проблему перевірки прапора CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9582,22 +9590,22 @@ msgstr "" "перевірки, Перетворіть маски та суми в рівняння, а потім перевірте прапорець" " \"вирішено\" за допомогою оригінальної програми." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Ознайомтеся з тематичним дослідженням CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Нативна * Реконструкція" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball обчислює положення звуку зліва / справа" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9609,22 +9617,22 @@ msgstr "" "призводять до невеликої функції C, яка перевіряється на відповідність " "вихідній поведінці та всім 63 скомпільованим байтам." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Ознайомтеся з тематичним дослідженням DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * відстеження об'єктів" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Як Notion копіює текст та HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9636,22 +9644,22 @@ msgstr "" "потім подивіться, як маленький маркер HTML пов'язує дані розширеного блоку з" " копією." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Ознайомтеся з тематичним дослідженням Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * Реконструкція" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "Як TH04 цілиться в кільце з куль" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9662,17 +9670,17 @@ msgstr "" " його операції множення, ділення та координації з зрозумілим C++, а потім " "подивіться, як вони створюють кільце, спрямоване на гравця." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Ознайомтеся з тематичним дослідженням TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Покрокові керівництва" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9681,7 +9689,7 @@ msgstr "" "У посібниках описуються власні обчислення, експорт Electron і запит до " "браузера. Кожне з них починається з запиту і конкретної мети." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Ознайомтеся з посібниками" @@ -9701,12 +9709,12 @@ msgstr "" " Android authenticator, DX-Ball, Notion, TH04 і засоби перевірки прапора " "downunderctf." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -9715,25 +9723,25 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Вітрина{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Тематичне дослідження * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Як Notion копіює{ph0}текст і HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9742,12 +9750,12 @@ msgstr "" "Простежте виклик буфера обміну з API сторінки Notion, через попереднє " "завантаження і основний процес, в програму запису буфера обміну Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Робочий стіл Notion 7.6.1 * JavaScript * REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Міст всередині настільного пакету Notion" @@ -9759,7 +9767,7 @@ msgstr "Міст всередині настільного пакету Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9776,7 +9784,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9793,7 +9801,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9810,7 +9818,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9821,13 +9829,13 @@ msgstr "" "наданий текст і HTML-код.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Один канал з'єднує дві сторони: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9837,14 +9845,14 @@ msgstr "" "завантаження та в основному процесі. При вирішенні оболонок виявляються " "виклики Electron, що стоять за цими іменами." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "У цьому тематичному дослідженні" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9852,7 +9860,7 @@ msgstr "{ph0}Дотримуйтесь мосту з буфера обміну{ph #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9860,19 +9868,19 @@ msgstr "{ph0}Збереження структури блоку{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Додаткові приклади та джерела{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Де виконується операція копіювання?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9892,17 +9900,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Копіювати" @@ -9913,7 +9921,7 @@ msgstr "Копіювати" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9924,7 +9932,7 @@ msgstr "" "і HTML в системний буфер обміну. Показуйте код на кожному " "кроці.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9933,12 +9941,12 @@ msgstr "" "Приклад запиту з локальним пакетом додатків Notion, доступним вашому " "програмісту." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA знаходить, з чого почати читання" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9949,13 +9957,13 @@ msgstr "" "API, доступний для сторінки, і виклик, який відправляє запит IPC. Обидва " "результати представлені з діапазонами вихідних текстів у зменшеному пакеті:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA висновки → два місця для відкриття" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9970,7 +9978,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9984,12 +9992,12 @@ msgstr "" "інформацію для пошуку в основному пакеті. У чотирьох наведених нижче витягах" " показано маршрут, по якому він підключається." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Чотири короткі фрагменти коду" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9998,13 +10006,13 @@ msgstr "" "Спрощений порівняно з пакетом JavaScript, з читабельними іменами змінних. " "Незв'язані елементи опущені." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Почніть з API, доступного для цієї сторінки" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10014,13 +10022,13 @@ msgstr "" "Цей учасник надає назву каналу. Реалізація {ph0} повідомляє нам, як запит " "завершує обробку сторінки." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Усуньте оболонку попереднього завантаження" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10030,14 +10038,14 @@ msgstr "" "Функція повернення перенаправляє аргументи через IPC запиту та відповіді " "Electron. Тепер ми можемо шукати {ph0} на стороні основного процесу." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Перевірте, як зареєстрований одержувач" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10047,12 +10055,12 @@ msgstr "" "Основний процес використовує іншу оболонку. Його метод {ph0} реєструвати " "{ph1} для цього каналу." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Знайдіть запис і перевірте його відправника" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -10063,13 +10071,13 @@ msgstr "" "буфера обміну Electron. Канал і дві дозволені оболонки підключають відкритий" " метод до цього виклику." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Як скопійований блок зберігає свою структуру?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10080,27 +10088,27 @@ msgstr "" "дані блоку локально та вставляє ідентифікатор у скопійований HTML-код, щоб " "зв'язати їх." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "HTML-посилання на збережені дані блоків" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Прочитайте ідентифікатор HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Знайдіть той самий локальний ідентифікатор" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Відновити дані блоку Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10110,7 +10118,7 @@ msgstr "" "дані блоку, якщо ідентифікатори однакові; застарілий запис повертає лише " "текст та HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10119,24 +10127,24 @@ msgstr "" "При вставці Notion шукає HTML-ідентифікатор і порівнює його зі збереженою " "копією. Відповідні ідентифікатори відновлюють дані блоку." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Формат буфера обміну, записаний із веб-ресурсів, кешованих 13 липня 2026 " "року." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Додаткові приклади та джерела" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Інший приклад: таблиці уцінки" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10145,12 +10153,12 @@ msgstr "" "Notion перетворює Markdown в блокові дані. У цьому прикладі показано, як " "таблиця перетворюється на заголовок та рядки даних." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Таблиця за допомогою аналізатора уцінки Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10159,13 +10167,13 @@ msgstr "" "Записаний вихід із витягнутого аналізатора Markdown. Таблиця перетворюється " "в рядки і осередки." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Інший шлях: автономне підключення до SQLite" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10179,7 +10187,7 @@ msgstr "" "візуалізації, а інший - службовому процесу SQLite. Наступні пакети " "інструкцій та результати передаються через цей порт." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10189,7 +10197,7 @@ msgstr "" "базою даних і чому при відстеженні тільки початкового IPC-запиту не " "враховується подальший діалог." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Джерела та як читати уривки" @@ -10197,7 +10205,7 @@ msgstr "Джерела та як читати уривки" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10215,7 +10223,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10231,7 +10239,7 @@ msgstr "" "невеликі модулі управління; їх результати описують ці тести, а не захоплений" " сеанс інтерфейсу робочого столу." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10246,7 +10254,7 @@ msgstr "" "реалізацій-оболонок в пакеті." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10264,7 +10272,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10278,7 +10286,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10304,52 +10312,52 @@ msgstr "" " Electron, обгортки IPC та основного процесу, з короткими витягами коду та " "ознайомтеся з його багатим форматом буфера обміну." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Тематичне дослідження Notion Electron" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Скопіювати запит на аналіз Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Скопіювати фрагмент попереднього завантаження Notion" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Скопіювати фрагмент коду Notion для виклику оболонки" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Скопіювати фрагмент оболонки обробника Notion" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Скопіювати фрагмент приймача з буфера обміну Notion" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Відновлення розширених даних буфера обміну при вставці" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Нагору" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Перейти до змісту" @@ -10358,25 +10366,25 @@ msgstr "Перейти до змісту" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Головний{ph1} сторінка / {ph2}Вітрина{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Тематичне дослідження * Тохоу 4: історія Землі лотосів" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "Реконструкції TH04 з{ph0}візерунки кулі." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10386,17 +10394,17 @@ msgstr "" "для перевірки оригінальної функції DOS, а потім дотримуйтесь її інструкцій " "на читабельному C++." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * 16-розрядна версія DOS * C++ та збірка" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Переглянути реконструкцію TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Від оригінальних інструкцій до перевіреного джерела" @@ -10407,7 +10415,7 @@ msgstr "Від оригінальних інструкцій до перевір #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10424,7 +10432,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10442,7 +10450,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10458,7 +10466,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10470,7 +10478,7 @@ msgstr "" "записаних компілятором, перевірки охоплюють код генерації маркерів, що " "містить цей допоміжний елемент.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10479,14 +10487,14 @@ msgstr "" "REA повертає вихідний код і результати його аналізу. Проект TH04 забезпечує " "підтримувані перевірки вихідного коду та компілятора." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "У цьому тематичному дослідженні" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10494,7 +10502,7 @@ msgstr "{ph0}Кільце з кулями{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10502,7 +10510,7 @@ msgstr "{ph0}Що повертає REA{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10510,7 +10518,7 @@ msgstr "{ph0}Збірка на C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10518,18 +10526,18 @@ msgstr "{ph0}Перевірка джерела{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Повний проект{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Як кільце націлюється на гравця" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10548,16 +10556,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ваш кодуючий агент" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Копіювати" @@ -10568,7 +10576,7 @@ msgstr "Копіювати" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10579,7 +10587,7 @@ msgstr "" " куль і направляє його на гравця. Поясніть розрахунок і покажіть " "код.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10589,7 +10597,7 @@ msgstr "" "локально." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10603,7 +10611,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10613,12 +10621,12 @@ msgstr "" "Ілюстрація відновленого математичного розрахунку кута для рахунку 16, " "напрямку гравця 40 і повороту шаблону 0. {ph0}Відкрити малюнок{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Шаблон запуску у відновленому джерелі" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Напад Еллі на кільце · уривок з джерела" @@ -10627,7 +10635,7 @@ msgstr "Напад Еллі на кільце · уривок з джерела" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10637,13 +10645,13 @@ msgstr "" "У цих рядках вибирається шаблон перед налаштуванням складності та " "продуктивності. {ph0}Прочитайте джерело атаки{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "Що повертає REA" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10655,12 +10663,12 @@ msgstr "" "повертає свої інструкції, псевдокод та посилання. Три частини цього " "результату пояснюють закономірність." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Перевірте зображення DOS, перш ніж читати його код" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10669,7 +10677,7 @@ msgstr "" "Перевірка прив'язує завантажений код і записи про переміщення до наданого " "виконуваного файлу. Шлях, зазначений вище, скорочений для відображення." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Прочитайте напис на кільці \"множ і Делі\"" @@ -10677,7 +10685,7 @@ msgstr "Прочитайте напис на кільці \"множ і Делі #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10690,12 +10698,12 @@ msgstr "" "підтримуваних джерел, які вказані в полі {ph2}. Повна послідовність наведена" " нижче." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Знайдіть, де малюнок повертається в бік гравця" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10708,12 +10716,12 @@ msgstr "" "роблять ці адреси читабельними; REA дозволяє агенту перевіряти початкові " "операції, що стоять за ними." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Від асемблера до читабельного C++" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10726,7 +10734,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10734,7 +10742,7 @@ msgstr "{ph0}Індекс 01{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10742,7 +10750,7 @@ msgstr "{ph0}02{ph1} Простір" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10750,7 +10758,7 @@ msgstr "{ph0}03{ph1} Мета" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10758,18 +10766,18 @@ msgstr "{ph0}04{ph1} Обертати" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Магазин" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * оригінальні 16-розрядні інструкції" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Читабельний c++ * короткий опис aimed-ring" @@ -10777,7 +10785,7 @@ msgstr "Читабельний c++ * короткий опис aimed-ring" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10792,7 +10800,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10808,7 +10816,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10823,7 +10831,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10838,7 +10846,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10852,7 +10860,7 @@ msgstr "" "відбувається при перетворенні беззнакових байт. Навколишнє джерело також " "перетворює цей кут і швидкість у Швидкість обертання." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10864,7 +10872,7 @@ msgstr "" "перевірки компілятора застосовуються до підтримуваного вихідного тексту у " "зв'язаному проекті." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Ознайомтеся з збереженим кільцем і приціліться в джерело" @@ -10881,7 +10889,7 @@ msgstr "Ознайомтеся з збереженим кільцем і при #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10891,12 +10899,12 @@ msgstr "" "{ph0}Кільцевий макрос{ph1} · {ph2}Мета та джерело швидкості{ph3} · " "{ph4}Представлення кута{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Перевірка підтримуваного джерела" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10906,12 +10914,12 @@ msgstr "" "маркерів, включаючи цей помічник, за допомогою закріпленого набору " "інструментів Turbo C++ 4.0 J." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 відповідних байтів" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10920,12 +10928,12 @@ msgstr "" "Скомпільований код генерації маркерів відповідає 2139-байтовому розділу " "оригінального виконуваного файлу." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Дві чисті збірки" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10938,7 +10946,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." @@ -10946,59 +10954,59 @@ msgstr "" "Записано 3 жовтня 2026 року. {ph0}Ознайомтеся з перевірками " "компілятора{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Ідентифікація мети і обсяг аналізу" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Початкова мета" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0} , 156 258 байт, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Допоміжний запис" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} у завантаженому зображенні REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Зміщення вихідного файлу" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, що повертається параметром {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Перевірка записаного коду" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 жовтня 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -11009,7 +11017,7 @@ msgstr "" "відображення та перекриття переміщення." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11024,7 +11032,7 @@ msgstr "" "інструкції, наведені вище, знаходяться в цих повідомлених діапазонах." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11040,7 +11048,7 @@ msgstr "" "REA для тієї ж початкової мети. Надана гра ідентифікується в маніфесті " "сховища, при цьому незалежне Походження незайманого дампа все ще відкрите." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -11051,12 +11059,12 @@ msgstr "" "гри, хронометраж і поведінку апаратного забезпечення PC-98 перевіряються під" " час виконання в проекті реконструкції окремо." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "Повна реконструкція TH04" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -11069,7 +11077,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -11081,7 +11089,7 @@ msgstr "{ph0}Вивчіть репозиторій TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11097,7 +11105,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11113,7 +11121,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11139,22 +11147,22 @@ msgstr "" "Слідкуйте за збіркою та відновленим C++, щоб побачити, як розставлено кільце" " куль і як вони націлені на гравця." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "На цій сторінці" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "Тематичне дослідження щодо маркування TH04" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Скопіювати запит як приклад TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11162,7 +11170,7 @@ msgstr "" "TH04 фіксовані та цільові кульові кільця; горизонтальна прокрутка на менших " "екранах" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11176,27 +11184,27 @@ msgstr "" "обох випадках відстань між точками становить 16 кутових одиниць, або 22,5 " "градуса." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Скопіювати шаблон запуску TH04" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Дотримуйтесь розрахунку прицільного кільця TH04" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Скопіюйте фрагмент збірки TH04" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Копіювально-читається розрахунок прицільного кільця" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Нагору" @@ -11307,7 +11315,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Фіксована швидкість: {speed} обертання." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11317,7 +11325,7 @@ msgstr "" "контрольованій перевірці в оригінальній грі, якщо округлити їх до трьох " "знаків після коми." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11683,592 +11691,600 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Однакова відстань: 256 ÷ 16 = 16 кутових одиниць = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Приклади" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Блог" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Почати" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Посібники" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Вихідний код" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Ліцензія MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Приєднатися до спільноти" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Стежити в X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * вибране джерело сценарію" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Вихідний код" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Очікуваний результат форматування" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Інструкція" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Абонент" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Константа" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Функція C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Кнопка" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "API попереднього завантаження" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "МПК" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "Файл CSV" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Ваш клацання" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Захоплений запит" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Експорт скрипта" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA результат * підсумок.витяг з ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA витяг з інструкції * 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA запит абонента * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "" "Результати в байтах REA * інтерпретуються як подвоєння в порядку зменшення" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Відновлений уривок з C ·" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Подивіться, як працює REA ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Вітрина →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Вибрані налаштування з перевіреного скрипта" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Читається зведення про обробнику %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * вибрані оригінальні інструкції" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Ідентифікатори операторів * вихідний код Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Слідкуйте за @reatools на X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Агент → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → агент * вибрані результати" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → агент * методи та абоненти" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * вибраний Декомпільований Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Читабельне резюме * інтерпретація агента" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP, повний корпус" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Завантажити Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Завантажити Android analysis provider" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Агент → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → агент * вибрані результати" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → агент * вибрані інструкції" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Агент → REA * прочитано_байт" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → агент * сьомі записи" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Оригінальний виконуваний файл * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Скачайте оригінальну гру challenge" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Завантажити вирішувач" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "Результат REA * фрагмент псевдокоду" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Агент → REA * функція {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → агент * уривок з інструкції" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → агент * уривок з повідомлення про абонента" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Агент → REA * два {ph0}запиту на читання в байтах" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "Результати в байтах REA * декодуються як подвійні" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Почніть зі своєї власної мети" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Генерація коду" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Відновлене правило" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Регульований годинник" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Двійковий" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Перевіряючий код" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Рівняння" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Правильно!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Здійсненний" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "Висновки REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Відновлений C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Затвердження" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Упакований додаток" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Відкритий API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "Оболонки IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Буфер обміну" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Вихідний код DOS" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "Інструкції щодо REA" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Розрахунок кута нахилу" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Кульове кільце" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Відкритий API сторінки" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Виклик IPC засобу візуалізації" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Надіслано до системного буфера обміну" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Збережено локально за допомогою Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Введення даних для уцінки" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Висновок структурованого синтаксичного аналізатора · Витяг" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Проаналізуйте свій власний додаток" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Агент → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → агент * вибрані поля" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Агент → REA * функція {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → агент * уривок з інструкції" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Результат тієї ж функції · витяг з aim" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Відповідний Підтримуваний c++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Кільцевий макрос * гілка TH04, фрагмент" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Кут і швидкість * витяг з джерела" @@ -12300,7 +12316,7 @@ msgstr "Переклад оновлюється. Поки прочитайте #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12318,7 +12334,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12339,7 +12355,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12360,7 +12376,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12379,7 +12395,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12398,7 +12414,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12409,14 +12425,14 @@ msgstr "" "сайт для мене.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Реконструкція * {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12427,7 +12443,7 @@ msgstr "" "ознайомтеся з запропонованими змінами." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12436,7 +12452,7 @@ msgstr "Наведений приклад · {ph0} та npm * ваш кодую #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12455,7 +12471,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12471,7 +12487,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12490,7 +12506,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12501,7 +12517,7 @@ msgstr "" "форматування в {ph7} і записує файл.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12516,7 +12532,7 @@ msgstr "{ph0} * рядки 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12530,7 +12546,7 @@ msgstr "" "результат.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12542,7 +12558,7 @@ msgstr "" " {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12550,7 +12566,7 @@ msgstr "{ph0} * Засіб форматування CSV" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12560,7 +12576,7 @@ msgstr "" "входить {ph1}npm ." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12568,7 +12584,7 @@ msgstr "У вас немає {ph0} або ви не впевнені?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12581,7 +12597,7 @@ msgstr "" "встановіть {ph1} 24 LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12595,7 +12611,7 @@ msgstr "{ph0} * приклад витягу з джерела" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12606,9 +12622,9 @@ msgstr "" "файл {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12616,7 +12632,7 @@ msgstr "{ph0} * приклад джерела" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12630,7 +12646,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12643,7 +12659,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12656,7 +12672,7 @@ msgstr "Наприклад: {ph0}чому калькулятор дає 220 дл #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12667,7 +12683,7 @@ msgstr "" "{ph3} дають 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12676,7 +12692,7 @@ msgstr "REA · завантажено {ph0} * вибрані рядки" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12694,7 +12710,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12713,7 +12729,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12726,28 +12742,28 @@ msgstr "" "невеликий приклад, у якому можна змінювати час.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * Учасник API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * Помічник IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "main/{ph0} * помічник обробника" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12757,12 +12773,1406 @@ msgstr "головний/{ph0} * приймач буфера обміну" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Почати {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Перемкнути на світлу тему" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Перемкнути на темну тему" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Для дослідження тіл запитів і відповідей HTTP використовуйте {ph0}Fiddler " +"Everywhere: захоплення SAZ, MCP і загальнодоступні навички{ph1}. Експортуйте" +" SAZ ??? HAR 1.2 для отримання Evidence захоплення в REA без підключення до " +"мережі або підключіть MCP-сервер Everywhere, щоб досліджувати записаний " +"трафік разом з агентом." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Спеціалізація моделей{ph0}Есе" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Чи потрібна для зворотної розробки більша модель?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Що реконструкція Touhou допомагає зрозуміти про універсальні й " +"спеціалізовані моделі та навчання на зворотному зв’язку від компілятора." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Автор N0zoM1z0 · 13 жовтня 2026 р" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Перейти до змісту" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "" +"{ph0}Домашня сторінка{ph1} / {ph2}Блог{ph3} / Моделі та зворотне " +"проектування" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Есе" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Чи потрібна для зворотного проектування більша модель?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Автор N0zoM1z0 · 13 жовтня 2026 р" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Головне" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Можливості моделі впливають на те, які гіпотези може запропонувати " +"агент штучного інтелекту.{ph1} Пізніші сесії вирішували проблеми, які " +"попередня робота залишила невирішеними." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Знайомий компілятор пропонує конкретні шаблони для вивчення " +"спеціалізованої моделі.{ph1} Деякі точні збіги машинного коду залежать від " +"конкретних шаблонів вихідного коду, які можна багаторазово використовувати." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Включіть знання репозиторію в справедливе порівняння.{ph1} Менша модель" +" із хорошим пошуком знань може вже мати достатньо інформації для прогресу." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Навчіть модель вибирати наступний корисний експеримент і протестуйте її" +" засіб перевірки.{ph1} Зворотній зв’язок корисний лише в тій мірі, в якій " +"засіб перевірки перевіряє правильні речі." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Оцінка перевірених результатів реконструкції разом із часом і " +"вартістю.{ph1} Це те, що я хочу виміряти для повного робочого процесу AI-" +"agent." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "У цій статті" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Що змінили сильніші моделі{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Навіщо спеціалізуватися?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Де зберігати цей досвід?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Вивчення наступного корисного експерименту{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Зворотне проектування та навчання з посиленням{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Коли засіб перевірки помиляється{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Варте порівняння{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Що це за агент ШІ?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Що змінили сильніші моделі" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"З серпня 2026 року я досліджував, який обсяг зворотного проектування може " +"виконати агент, маючи доступ до програми та спосіб перевірки її роботи. " +"Більшість мого досвіду отримано від реконструкції ігор, особливо Touhou. " +"Оскільки я змінював моделі, репозиторії зберігали записи про те, що вдалося " +"відновити за кожну сесію." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Значна частина цієї роботи спрямована на точну реконструкцію: ми компілюємо " +"підтримуваний джерело в ланцюжку історичних інструментів із фіксованими " +"версіями та перевіряємо, чи він відтворює цільову функцію. Коли пізніша " +"модель досягає успіху там, де попередня робота зупинилася, зміни джерела " +"показують, що зробило цей прогрес можливим." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Тимчасові змінні потребували часу існування, що збігався" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Значна частина логіки функції атаки TH09 вже була реконструйована, але " +"компілятор усе ще зберігав тимчасові результати, відмінні від оригіналу. " +"Проблема, що залишилася, полягала в тому, як довго ці результати залишалися " +"живими та коли їхнє сховище можна було використовувати повторно." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"{ph0}GPT-6-Sol запис сеансу{ph1} повідомив про цю невідповідність після " +"тестування кількох звичайних механізмів вихідного коду. Коли " +"{ph2}GPT-6.1-Sol знову дослідив проблему{ph3}, він запропонував корисну " +"гіпотезу щодо тривалості життя цих тимчасових змінних." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"Функція створила тимчасові результати та скопіювала їх у позиції анімації. У" +" C++ тимчасовий результат залишається активним до завершення виразу, який " +"його використовує. Групування реальних операцій в один вираз зберігало ці " +"результати разом, тому компілятор більше не міг повторно використовувати те " +"саме сховище для всіх них." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Один результат все ще ділився пам’яттю зі значенням, яке використовується " +"пізніше для перевірок на конфлікти. Надання цьому значенню власного часу " +"життя вирішило решту накладання. Після кількох цілеспрямованих експериментів" +" {ph0}чиста повторна компіляція з джерела підтвердила, що повна функція " +"відповідає{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Мені цікаво, як відкриття та випробування підтримували одне одного. Гіпотеза" +" про тривалість життя тимчасових об’єктів дала агенту ШІ новий напрямок. " +"Відгуки компілятора допомогли уточнити цю гіпотезу у вихідному коді, який " +"відповідав." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Інший графік потоку керування" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Друга функція TH09 показує, чому цей новий напрямок може мати значення. Тут " +"перешкодою було те, що кілька філій поділилися своєю остаточною роботою. " +"Попередня робота {ph0}GPT-6.1-Sol{ph1} мала відповідні частини функції, але " +"гілки все одно з’єднувалися інакше, ніж у оригіналі." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra змінив навколишній графік потоку керування{ph1}. Основні " +"шляхи тепер вели до спільного остаточного оновлення та повернення. У цій " +"вихідній структурі компілятор об’єднав гілки так само, як і в оригіналі. " +"Повна функція відповідала, і {ph2}окрема перевірка відновлення підтвердила " +"це{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Зміна подання відкрила більш продуктивний простір для пошуку.{ph1} " +"Обидва випадки дають мені підстави серйозно поставитися до загальної " +"можливості моделі: агент може довго пробувати місцеві варіації, перш ніж " +"знайти кращий спосіб вираження навколишньої роботи." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"У той же час пізніші сеанси починалися з попередніх джерел і записаних " +"збоїв. Ця накопичена робота була частиною їхньої переваги. Історія дозволяє " +"нам ознайомитися з відкриттями та їх перевірками; контрольоване порівняння " +"допомогло б відокремити ефект моделі від досвіду, який вона успадкувала." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Ось що робить питання цікавим для мене. Певний прогрес став завдяки пошуку " +"нового представництва. Значна частина роботи, що залишилася, включала " +"тестування різних механізмів вихідного коду на знайомому компіляторі. " +"Наскільки для цього потрібна широка здатність міркувати? Скільки може " +"навчитися модель, постійно працюючи з цим компілятором і кодом?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Чому спеціалізована модель ШІ може працювати добре?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou дає нам конкретну причину очікувати, що цей досвід допоможе. Значна " +"частина ігрового коду походить від того самого автора, ZUN, тому повторювані" +" звички є розумним вихідним припущенням. Репозиторії підтверджують це " +"корисними прикладами: пов’язані цикли та допоміжні механізми надають " +"гіпотези для різних ігор." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Ці вихідні шаблони стають більш конкретними, коли ми включаємо компілятор. " +"За певної версії та набору параметрів невеликі зміни у джерелі можуть " +"призвести до повторюваних відмінностей у машинному коді. Деякі з цих " +"відмінностей напрочуд незрозумілі." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"У TH095, наприклад, {ph0}навіть ім’я локальної змінної могло вплинути на те," +" де VC7.1 її зберігати{ph1}. Переміщення його оголошення не вирішило макета " +"сховища. Однак більш рання фонова функція виявила шаблон іменування, який " +"вплинув на вибір компілятора. Це запропонувало більш перспективну гіпотезу " +"для {ph2}реконструкції {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Повторне використання цього шаблону для змінної розміру файлу створило " +"необхідний макет без додавання пам’яті. Тоді повна функція збігалася." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Це дуже конкретна деталь, яку модель ШІ загального призначення може не " +"знати, коли вперше стикається з проблемою. Спеціалізована модель для цього " +"компілятора може побачити багато таких випадків і дізнатися, які варіації " +"вихідного коду варто перевірити в першу чергу." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Можливість особливо чітка в остаточних задачах зіставлення, де ми вже " +"розуміємо поведінку. Тоді ми запитуємо, яку звичайну структуру вихідного " +"коду цей компілятор перетворює на спостережувані інструкції. Спеціалізація " +"може допомогти моделі запропонувати ці форми ефективніше, тоді як ціль все " +"ще визначає, які гіпотези виживуть." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Корисні шаблони повинні зберігати свій контекст. TH08 використовує попередню" +" версію Visual C++, ніж TH095 і TH09. TH04 використовує компілятор, " +"відмінний від епохи DOS. Його {ph0}реконструкція коду гравця{ph1} " +"потребувала різних гіпотез щодо шаблонів вихідного коду та того, як " +"скомпільований код зв’язувався у виконуваний файл. Наявність того самого " +"автора дає нам початкове очікування, але кожна ціль говорить нам, чи вона " +"застосовна. Спеціалізована модель повинна розрізняти ці контексти." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Де зберігати цей досвід?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Перш ніж вирішувати навчати цим шаблонам за допомогою моделювання, я б " +"подивився на знання, які ми вже зберігаємо в репозиторії. У " +"{ph0}попередньому есе{ph1} я писав про те, що це стало робочою пам’яттю " +"проекту. Ця пам’ять містить уроки компілятора, а також джерело та невдалі " +"експерименти, які зробили їх корисними." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Отримавши цей запис, агент може почати з відомого результату та перевірити, " +"як ми його досягли. Він також може уникнути альтернатив, які вже зазнали " +"невдачі в тому ж контексті. Початкова точка покращується без зміни навчених " +"параметрів моделі." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Під час реконструкції функції TH09 для створення ворогів {ph0}GPT-6-Luna-max" +" сеанс{ph1} взяв гіпотезу з відповідного вихідного коду TH08. Цей попередній" +" код пропонував, як організувати цикл і обробляти збої в ньому. Власні " +"свідчення TH09 надали деталі гри. Перебудови з джерела підтвердили, що вся " +"функція відповідає." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}«Модель не знала про цю примху компілятора» та «модель не могла її " +"використати» — це різні проблеми.{ph1} Отримання може вирішити першу, але " +"для того, щоб перетворити цей факт на корисну кандидатуру, все ще потрібно " +"попрацювати. І якщо вихідний код кандидата зазнає невдачі, модель повинна " +"вирішити, що означає результат для її наступної спроби. Знання відповідного " +"шаблону – це лише початок цього процесу." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"З цієї причини я б включив у будь-яке порівняння меншу модель ШІ загального " +"призначення з хорошим пошуком. Надання такої ж бібліотеки досвіду допомогло " +"б нам визначити, що додає навчання: краще формування кандидатів, кращі " +"рішення після зворотного зв’язку чи те й інше." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Вивчення наступного корисного експерименту" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Я б найбільше хотів вивчити ці рішення після зворотного зв’язку. При " +"агентній реконструкції модель пропонує пояснення та перевіряє його на " +"програму. Навіть якщо вихідний код кандидата не вдається, результат може " +"звузити можливості, що залишилися, і запропонувати більш корисний наступний " +"експеримент." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Знову розглянемо приклад із тимчасовими результатами. Його остаточне джерело" +" показує схему, яка спрацювала, але шлях до цього джерела містить більше " +"інформації. Кожен із наступних експериментів допоміг визначити, що ще " +"потрібно змінити." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Експериментуйте" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Чого нас навчив його результат" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Спробуйте інший спосіб скопіювати результати" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Код копіювання змінюється, але функція все ще відрізняється." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Використовуйте повернуті значення безпосередньо" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "" +"Копіювання відбувається за оригінальним шаблоном, але тимчасове зберігання " +"все ще відрізняється." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Зберігайте всі тимчасові змінні дійсними одночасно" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Вони отримують окреме сховище, але одне все одно перекриває значення, яке " +"буде використано пізніше для перевірок на конфлікти." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Зберігайте значення перевірки зіткнень окремо" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "Чиста перекомпіляція з джерела підтверджує повний збіг." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Вибрані експерименти з наведеної вище реконструкції функції атаки, " +"згруповані за тим, чому вони нас навчили." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Навчальний запис, який зберігає цю послідовність, може навчити більше, ніж " +"одне лише кінцеве джерело. Він пов’язує кожну запропоновану зміну з " +"результатом спостереження та наступним рішенням. Збереження неефективних " +"варіацій також має значення: вони повідомляють пізнішому агенту, які " +"гіпотези вже були перевірені в цьому контексті." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Я хотів би, щоб модель навчилася використовувати зворотній " +"зв’язок.{ph1} Нейтральний результат є причиною переглянути варіант; змінена " +"невідповідність може вказувати на іншу причину. Коли локальні редагування " +"перестають бути інформативними, агент повинен мати можливість переглянути " +"вихідне представлення або знову перевірити докази." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Щоб навчитися робити такий вибір, потрібна автономія. Іноді корисним " +"наступним кроком є ​​перевірка іншої функції, що викликає цю функцію, а не " +"компіляція іншого редагування. Жорстка послідовність необхідних переписів " +"усуне цей вибір разом із частиною поведінки, яку ми хочемо, щоб модель " +"навчила." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "Чому зворотне проектування цікаве для навчання з підкріпленням" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Реконструкція з визначеними межами дає практичне середовище для вивчення цих" +" рішень. Коли версії цілі й компілятора зафіксовані, багато експериментів із" +" вихідним кодом дають швидкий, відтворюваний зворотний зв’язок. Агент може " +"скомпілювати кандидата, перевірити відмінності та вибрати наступний крок." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Навчання з підкріпленням може тренувати цей процес прийняття рішень за " +"допомогою зворотного зв’язку, який він отримує. Кандидат, прийнятий за " +"певною перевіркою, дає нам конкретний результат, а послідовність спроб " +"дозволяє спостерігати, скільки роботи знадобилося для його досягнення." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"У цьому напрямку вже є дослідження. {ph0}LLM4Decompile{ph1} вивчає моделі, " +"що спеціалізуються на декомпіляції. {ph2}AutoDecompiler{ph3} тренує " +"багатоповоротне вдосконалення за допомогою компілятора та відгуків про " +"виконання. Їх дослідження зосереджені на функціональному відновленні. Для " +"цієї роботи я б використав їх як відправну точку для пов’язаного завдання " +"пошуку джерела, яке відповідає історичним результатам компілятора." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Однак, щоб досягти такого чітко визначеного завдання, нам може спочатку " +"знадобитися встановити, якими ресурсами володіє функція, або розробити новий" +" спосіб спостереження за поведінкою програми під час виконання. У TH08, " +"наприклад, {ph0}різниця зіткнень призвела до того, як оригінальна програма " +"обробляла обчислення з плаваючою комою{ph1}. Перш ніж агент міг перевірити " +"корисну поправку, він повинен був визначити, що вимірювати." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Це говорить про іншу роль широкофункціональної моделі: допомогти зробити " +"проблему перевіреною в першу чергу. Щойно така перевірка з’явиться, ми " +"зможемо дослідити, наскільки далеко може зайти вивчена політика пошуку з " +"нею." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Коли засіб перевірки помиляється" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Коли перевірка використовується для навчання, її охоплення стає частиною " +"навчального середовища. Такий еталон або засіб перевірки я називаю оракулом." +" Навіть відтворювану відповідь потрібно розуміти в межах того, що вона " +"справді перевіряє." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 показав, як багато можна приховати за межами цього покриття. Деякі " +"реконструйовані функції пройшли точне порівняння з неправильними плаваючими " +"константами. Компаратор скоригував переміщені адреси перед перевіркою " +"інструкцій, але він перевірив значення за цими адресами лише тоді, коли вони" +" були явно записані для перевірки. Інші літеральні посилання можуть пройти " +"без перевірки їхніх значень." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Щоб усунути цю прогалину, {ph0}ширший аудит{ph1} виявив неправильні " +"константи у функціях, які вже пройшли перевірку. В одному обчисленні " +"реконструйований вихідний код додав {ph2}, тоді як оригінальний додав {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Модель, нагороджена старою перевіркою перевірки, може навчитися " +"виробляти неправильну реконструкцію.{ph1} Ми не навчали модель RL за " +"допомогою цього засобу перевірки. Помилка, яку ми помітили, була в самій " +"перевірці. Але якби ми використовували це як винагороду, та сама сліпа пляма" +" стала б частиною навчального середовища." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Функціональний тест може мати подібну сліпу пляму. {ph0}Дослідження з " +"використанням диференціального фаззингу на декомпіляторах LLM{ph1} виявили " +"поведінкові відмінності поза наданими тестами. Тому ми повинні розуміти " +"проходження тесту з точки зору випадків, які він виконує. Подібним чином " +"збіг інструкцій слід розуміти з точки зору байтів і даних, які він " +"перевіряє." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Перш ніж використовувати будь-який вид перевірки підтвердження як " +"винагороду, я б перевірив його з навмисно неправильними результатами. Я " +"також хотів би зберегти остаточне прийняття окремо від вихідного коду, який " +"агент ШІ може редагувати. Модель повинна пройти перевірку шляхом коректної " +"реконструкції програми. Інакше просте копіювання байтового масиву з " +"цільового об’єкта може обдурити наївну систему підрахунку балів без " +"відновлення корисного вихідного коду." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Поліпшення моделі й поліпшення її засобу перевірки — частини однієї " +"дослідницької проблеми.{ph1} Що краще модель оптимізує наданий зворотний " +"зв’язок, то важливіше розуміти сам цей зв’язок." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Варте порівняння" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"За наявності цих перевірок я б почав порівняння з фіксованої сім’ї завдань " +"VC7.1. По-перше, я б визначив базові лінії для сильної моделі ШІ загального " +"призначення та меншої. Додавання знань про репозиторій до меншої моделі " +"покаже, які зміни в пошуку. Звідти контрольована спеціалізація та версія з " +"навчанням RL дозволять нам перевірити, що додає навчання." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Щоб зробити ці порівняння інформативними, кожна модель отримуватиме однакові" +" цільові дані та інструменти. Для порівнянь, пов’язаних із навчанням, я б " +"також залишив базову модель і наявні знання фіксованими. Повторні " +"випробування допомогли б відрізнити надійну стратегію пошуку від " +"альтернативного рішення, яке вдалось випадково." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Потім я б розділив дві початкові умови: реконструкція функції з її " +"інструкцій і закриття кількох останніх відмінностей у підтримуваному " +"джерелі. Спеціалізована модель штучного інтелекту може бути чудовою для " +"другого завдання, тоді як модель загального призначення виконує велику " +"частину роботи, необхідної для її досягнення. Вимірювання їх окремо виявило " +"б такий розподіл роботи." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Для обох завдань потрібні тестові приклади, яких немає ані в навчальних " +"даних, ані в матеріалах для пошуку. Пов’язані ігри Touhou мають спільний код" +" рушія. Якщо відкласти лише одну гру, майже однакові функції все одно можуть" +" потрапити до навчання. Я б натомість відкладав цілі групи спорідненого " +"вихідного коду й виключав їхні перевірені відповіді як із навчальних даних, " +"так і з бібліотеки пошуку." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Для цих прикладів результатом будуть повні, незалежно перевірені збіги. " +"Рівні бюджети для пропозицій кандидатів або спроб компіляції допоможуть " +"порівняти якість пошуку. Вимірювання загального часу та вартості, включаючи " +"компіляцію, покаже, чи забезпечує така якість ефективний робочий процес. " +"Витрати на навчання слід вимірювати окремо." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Обидва вимірювання мають значення. Дешева пропозиція може призвести до " +"дорогого робочого процесу, якщо це спричинить більше компіляцій, які не " +"надають корисної інформації. І навпаки, повільніша модель може бути " +"економнішою, якщо швидше знайде корисний експеримент. Порівняння повинно " +"включати ці витрати." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Підрахунок прийнятих результатів також зберігає проміжний прогрес у " +"перспективі. Один TH09 {ph0}кандидат для повторного збереження{ph1} виглядав" +" багатообіцяючим, оскільки скомпільована функція мала очікуваний розмір, але" +" повне порівняння все одно виявило значні відмінності. Зміни в тому, як " +"компілятор впорядковує інструкції, також можуть створити враження, що " +"кандидат ближчий до цілі, не вирішуючи основної проблеми. Така діагностика " +"може керувати наступним експериментом, але я б перевірив будь-яку винагороду" +" за «наближення» до повної перевірки прийняття." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Мені було б цікаво побачити закономірності цих результатів. Якщо " +"спеціалізована модель штучного інтелекту добре справляється зі знайомим " +"сімейством компіляторів, чи збережеться ця перевага після зміни " +"інструментального ланцюжка? І коли обидві моделі штучного інтелекту мають " +"хороший пошук, скільки ще додає навчання? Відповіді допоможуть нам вирішити," +" де кожен тип моделі є найбільш корисним." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Що це за агент ШІ?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Якщо виявиться, що моделі допомагають на різних етапах, корисною " +"домовленістю може бути широкий агент із доступом до спеціалізованої моделі " +"ШІ. Коли завдання стає звичним пошуком компілятора, воно може запитати " +"спеціалізовану модель AI для кандидатів. Якщо результати перестають мати " +"сенс, ширший агент може повернутися до цільових доказів або дослідити саме " +"вимірювання." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"У такій домовленості спеціалізація стає інструментом, який агент може " +"вибрати під час розслідування. Агент зберігає свободу змінювати напрямок, що" +" уможливило попередні прориви." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Це природно випливає з промислових змін, які я описав у попередньому есе. " +"Можливість проводити багато інших експериментів змінює спосіб організації " +"роботи. Це також дає нам привід запитати, які рішення потребують широкого " +"оцінювання, а які покращуються через повторний досвід роботи з певним " +"ремеслом." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Наразі найсильніша універсальна модель заслужила місце в моєму робочому " +"процесі, розв’язавши проблеми, які раніше залишалися нерозв’язаними. Ці " +"успіхи спонукають мене дослідити процес: яка частина залежала від широти її " +"можливостей, а яку могла б виконати модель, навчена саме такої " +"реконструкції?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Репозиторії дають нам спосіб перевірити запитання.{ph1} Я хотів би " +"використати цей запис для порівняння та побачити, що ми дізнаємося." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Докази та атрибуція моделі" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Приклади описують історичні порівняння на рівні функцій, записані у " +"зв’язаних комітах. Перевірки виконання всієї гри є окремими етапами. Вихідні" +" та відповідні записи було переглянуто 13 жовтня 2026 року." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"Мітка TH09 {ph0} означає GPT-6-Astra. Модель, пов’язана з {ph1}, змінювалася" +" з часом, тому лише ця мітка не може ідентифікувати модель, яка " +"використовується в певному циклі. Явні назви моделей в інших цитованих " +"комітах забезпечують записане присвоєння. Ці історії не містять узгоджених " +"вимірювань витрат або зусиль для кожного запуску." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 терміни життя тимчасових об’єктів:{ph1} {ph2}попередній перегляд " +"контексту{ph3} та {ph4}повна реконструкція, підтверджена чистою " +"перекомпіляцією з джерела{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front зворотний виклик:{ph1} {ph2}діагностичні області, які не " +"збігаються{ph3}, {ph4}Astra новий графік потоку керування{ph5} та його " +"{ph6}перевірка прийнятої повторної компіляції{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Знання компілятора:{ph1} {ph2}TH095 повторне використання поведінки " +"сегмента ідентифікатора{ph3}, {ph4}TH04 вихідний код гравця та порядок " +"зв’язування{ph5} та повна реконструкція {ph6}Luna функції створення ворогів " +"TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Перевірки та діагностика:{ph1} {ph2}TH08 постійний аудит із плаваючою " +"комою{ph3}, {ph4}TH08 числове дослідження{ph5} та {ph6}TH09 реконструкція зі" +" збереженням повтору{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Пропоновані порівняння спеціалізованих моделей і навчання RL є майбутніми " +"експериментами. Історії проекту мотивують їх. Жодна навчена спеціалізована " +"модель не оцінювалася для цього есе." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Чи потрібна для зворотного проектування більша модель? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Чого навчила мене реконструкція Touhou щодо загальних моделей, спеціальних " +"моделей і навчання пропонувати кращі гіпотези на основі відгуків " +"компілятора." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "На цій сторінці" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Есе про моделі та зворотне проектування" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Вибрані досліди реконструкції" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Нагору" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}Докладні записи доказів{ph1} містять результати порівнянь і контекст " +"експериментів." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "Автор: N0zoM1z0 · 13 жовтня 2026 р. · Чернетка для обговорення" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Посібник зі встановлення" diff --git a/website/locales/vi/messages.po b/website/locales/vi/messages.po index 313aca285..dac24ee02 100644 --- a/website/locales/vi/messages.po +++ b/website/locales/vi/messages.po @@ -8,42 +8,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}Nhà{ph1} / Blog" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "Blog." -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "Suy nghĩ về kỹ thuật đảo ngược." #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "Tái thiết trò chơi{ph0}Bài luận" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "Cuộc cách mạng công nghiệp trong kỹ thuật đảo ngược" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " @@ -52,34 +52,35 @@ msgstr "" "NHỮNG gì HƯỚNG DẪN SỬ DỤNG LẠI VÀ tái TẠO TH08, TH095 và TH04 đã dạy tôi về " "các agent, xác minh và kiến thức mà các hợp chất trong các dự án." -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "Đọc bài viết" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Bởi N0zoM1z0 * 10 tháng mười 2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -100,6 +101,8 @@ msgstr "" "REA và AI." #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -135,112 +138,117 @@ msgstr "" "REA-Tìm hiểu cách thức hoạt động của phần mềm. Kỹ thuật đảo ngược với agent " "mã hóa của bạn." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "Trang chủ REA" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "Điều hướng chính" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "REA TRÊN GitHub" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "Tham gia Discord của REA" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "Theo DÕI REA Trên X" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -249,35 +257,35 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}Nhà{ph1} / {ph2}Blog{ph3} / Tái thiết Touhou" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "Tiểu luận * Tái Thiết Touhou" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "Cuộc cách mạng công nghiệp trong kỹ thuật đảo ngược." -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "Bởi N0zoM1z0 * 10 tháng mười 2026" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "Điểm chính" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -290,7 +298,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -304,7 +312,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -317,7 +325,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -330,7 +338,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -341,65 +349,65 @@ msgstr "" " RE.{ph1} Các phương pháp vẫn đang hình thành. Còn rất nhiều thứ để khám " "phá." -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "Làm thế nào kinh nghiệm hợp chất" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}Hướng của con người{ph1} * Tiêu chí mục tiêu và chấp nhận" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "Quyền tự chủ" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "Trợ lý AI" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "Chọn một thử nghiệm.{ph0}Đề xuất một giả thuyết." -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "Kiểm chứng" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "Chuẩn kiểm chứng" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "Kiểm tra chống lại một{ph0}tham chiếu cụ thể." -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "Kho mã" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "Bộ nhớ làm việc" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -408,7 +416,7 @@ msgstr "Mã, bằng chứng,{ph0}kiểm tra và bài học." #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -417,26 +425,26 @@ msgstr "Không phù hợp{ph0}{ph1}Sửa đổi giả thuyết{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "Một tốt hơn{ph0}{ph1}điểm bắt đầu{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "Tái sử dụng" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}Vượt qua{ph1} * Giữ kết quả và bằng chứng của nó" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " @@ -445,14 +453,14 @@ msgstr "" "Mỗi dự án để lại tiếp theo với một điểm khởi đầu tốt hơn. Điều đó bao gồm " "sửa chữa các kiểm tra khi chúng tôi phát hiện ra một khoảng cách." -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "Trong bài viết này" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -460,7 +468,7 @@ msgstr "{ph0}Mai 2026{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -468,7 +476,7 @@ msgstr "{ph0} TH08 : sự tiếp tục{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -476,7 +484,7 @@ msgstr "{ph0}Hai cách tiếp cận{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -484,7 +492,7 @@ msgstr "{ph0} TH095 : hợp chất{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -492,7 +500,7 @@ msgstr "{ph0} TH04: trên các kiến trúc{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -500,7 +508,7 @@ msgstr "{ph0}Từ chính xác đến có thể đọc được{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -508,18 +516,18 @@ msgstr "{ph0}Sự thay đổi công nghiệp{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}Điều gì trở nên khả thi{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "Điều gì đã thay đổi vào tháng 8 năm 2026" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -534,7 +542,7 @@ msgstr "" "là dành nhiều thời gian hơn cho chức năng tiếp theo. Nó cũng có nghĩa là giữ" " một bức tranh ngày càng lớn trong đầu tôi." -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -548,7 +556,7 @@ msgstr "" "có thể hữu ích ở nơi khác, nhưng mỗi trường cần thiết lập những gì nó có thể" " kiểm tra đối với một tham chiếu đáng tin cậy." -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -561,7 +569,7 @@ msgstr "" " và các công cụ phát triển thông thường. Touhou tái thiết đã cho tôi một dự " "án đáng kể trong đó để tìm hiểu." -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -578,7 +586,7 @@ msgstr "" "tạo ra sự khác biệt: tôi có thể dành nhiều sự chú ý hơn cho hướng của dự án " "và về việc kiểm tra của nó có đáng tin cậy hay không." -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -589,7 +597,7 @@ msgstr "" " gì sẽ tồn tại ngoài dự án hiện tại. Liệu trò chơi tiếp theo có được hưởng " "lợi từ mọi thứ chúng ta vừa học được không?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08: xây dựng trên công việc của con người" @@ -598,7 +606,7 @@ msgstr "TH08: xây dựng trên công việc của con người" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -612,7 +620,7 @@ msgstr "" " đáng kể. Nó đi kèm với kiến thức về việc xây dựng và lịch sử đóng góp mà " "tôi đã lưu giữ trong phần tiếp theo." -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -623,7 +631,7 @@ msgstr "" "tiếp tục độc lập của tôi bắt đầu vào ngày 13 tháng tám. Đến ngày 19 tháng 8," " sổ cái đã ghi lại nguồn cho tất cả 1.107 chức năng trò chơi được xác định." -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -634,7 +642,7 @@ msgstr "" "8, khoảng mười một ngày sau khi bắt đầu tiếp tục. Một phiên Bản Web theo " "sau. BẢN PHÁT HÀNH Linux 64-bit gốc đã đến vào ngày 30 tháng 8." -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -650,7 +658,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -669,12 +677,12 @@ msgstr "" " một lời giải thích và kiểm tra nó; một sự không phù hợp mang lại cho nó một" " cái gì đó cụ thể để điều tra." -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "Một kết hợp chính xác với hằng số sai" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -686,7 +694,7 @@ msgstr "" #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -698,7 +706,7 @@ msgstr "" "trở lại mục tự động thu thập. Nguồn tái tạo kiểm tra sức mạnh của người chơi" " chống lại {ph0}. Bản gốc được sử dụng {ph1}, ngưỡng công suất tối đa." -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -713,13 +721,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}Tuy nhiên, chức năng đã vượt qua so sánh chính xác.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -734,7 +742,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -750,7 +758,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -765,7 +773,7 @@ msgstr "" "thấy mười hai tài liệu tham khảo không chính xác khác trên năm chức năng " "được chấp nhận." -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -778,7 +786,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -788,7 +796,7 @@ msgstr "" "{ph0}Tài liệu tham khảo xác minh (oracle) cũng cần được xây dựng lại.{ph1} " "Sửa chữa nó là một phần của việc sửa chữa trò chơi." -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -806,7 +814,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -822,7 +830,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -832,7 +840,7 @@ msgstr "" "{ph0}Một lô thành công đã cho chúng tôi cả mã được khôi phục và môi trường " "tốt hơn cho lô tiếp theo.{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "Hai ý tưởng tái thiết khác nhau" @@ -841,7 +849,7 @@ msgstr "Hai ý tưởng tái thiết khác nhau" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -853,7 +861,7 @@ msgstr "" "loại công việc này rõ ràng. Thông báo thông báo rằng việc phát triển thêm sẽ" " diễn ra riêng tư cho đến khi hoàn thành. Một đoạn văn đọc:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" @@ -863,7 +871,7 @@ msgstr "" " tác phẩm của chúng tôi vẽ nên một hình ảnh xấu cho những nỗ lực dịch ngược " "trong tương lai…" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -880,7 +888,7 @@ msgstr "" "muốn thảo luận là về việc tái thiết nên tiến hành như thế nào và đóng góp " "nên được đánh giá như thế nào." -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -893,7 +901,7 @@ msgstr "" "rất nhiều vào chuyên môn của người đó. Niềm tin vào người đóng góp quan " "trọng vì rất nhiều lý do đã xảy ra trong khi họ làm việc." -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -904,7 +912,7 @@ msgstr "" "công cụ. Điều thay đổi đối với tôi là một agent có thể sử dụng kiến thức đó " "để tự mình theo đuổi cuộc điều tra tiếp theo." -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -919,7 +927,7 @@ msgstr "" "có thể kiểm tra lý do tại sao chúng tôi chọn một triển khai, ngay cả khi một" " agent đã làm hầu hết công việc." -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -932,7 +940,7 @@ msgstr "" "đó đặt ra câu hỏi thực sự về tín dụng. Nó cũng thay đổi những gì các nhà bảo" " trì cần biết trước khi chấp nhận đóng góp." -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -947,7 +955,7 @@ msgstr "" "ra khi nào đầu ra của nó sai. Các cộng đồng khác nhau có thể chọn mức độ " "thay đổi mà họ muốn thực hiện." -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -972,7 +980,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -985,14 +993,14 @@ msgstr "" "trích rút gọn. TH08 ' s {ph4}tín dụng và xuất xứ{ph5} ghi lại ranh giới " "tiếp tục." -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095: kinh nghiệm bắt đầu ghép" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1007,7 +1015,7 @@ msgstr "" "chơi. Nhưng chúng tôi đã biết nhiều hơn về cách bắt đầu tái thiết và cách " "giữ cho nó di chuyển." -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -1021,7 +1029,7 @@ msgstr "" "i386 được đánh dấu có thể chơi được vào ngày 10 tháng 9, khoảng mười hai " "ngày sau khi khởi tạo." -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -1032,7 +1040,7 @@ msgstr "" "thể được hưởng lợi từ công việc được thực hiện trên một trò chơi khác. Kinh " "nghiệm đã có mặt trong các công cụ và trong cách dự án được tổ chức." -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -1047,7 +1055,7 @@ msgstr "" "việc cùng nhau. Bài học đó đã giúp định hình cách chúng tôi tiếp cận BẢN " "dựng toàn bộ CHƯƠNG trình CỦA TH095." -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -1060,7 +1068,7 @@ msgstr "" "khi tôi đã chuyển sang. Các agent tiếp theo có thể sử dụng kết quả mà không " "cần lặp lại điều tra dẫn đến nó." -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -1075,7 +1083,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1087,7 +1095,7 @@ msgstr "" "tiếp theo.{ph1} Chúng ta có thể dành nhiều nỗ lực của dự án tiếp theo cho " "những gì thực sự mới về mục tiêu của nó." -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -1100,7 +1108,7 @@ msgstr "" "phải xây dựng lại toàn bộ lịch sử của dự án để tìm hiểu lý do tại sao nguồn " "trông giống như cách nó làm." -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04: quy trình làm việc tồn tại trong một kiến trúc khác" @@ -1109,7 +1117,7 @@ msgstr "TH04: quy trình làm việc tồn tại trong một kiến trúc khác" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1125,7 +1133,7 @@ msgstr "" "CHƠI Windows. Hiện có {ph2}ReC98 làm việc{ph3} đã cho chúng tôi kiến thức có" " giá trị và tài liệu nguồn ở đây quá." -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -1138,7 +1146,7 @@ msgstr "" "chúng và kiểm tra lưu. Công việc hiện tại là một cổng 64 bit gốc. Thiết lập " "phiên bản dos hoạt động trước tiên cung cấp cho cổng đó một tham chiếu." -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1151,7 +1159,7 @@ msgstr "" "mình. Nhưng tác nhân vẫn có thể làm theo một câu hỏi cho đến một kết quả và " "để kết quả đó hướng dẫn thí nghiệm tiếp theo." -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1166,7 +1174,7 @@ msgstr "" "bằng chứng và kiểm tra có sẵn, một agent có thể làm việc thông qua các câu " "hỏi nhiều như nó đã làm trên một tiêu đề Windows." -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1178,7 +1186,7 @@ msgstr "" "mới. Kiến trúc đã xác định vấn đề; quy trình làm việc vẫn cho chúng ta một " "cách để giải quyết nó." -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1195,7 +1203,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1206,12 +1214,12 @@ msgstr "" "kiểm tra thủ công{ph1} · {ph2}Cổng 64-bit{ph3}. Cảng vẫn đang được phát " "triển." -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "Từ mã chính xác đến mã có thể đọc được" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " @@ -1219,7 +1227,7 @@ msgid "" msgstr "" "Khi một công trình tái thiết hoạt động, tôi muốn người khác có thể hiểu nó." -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1234,7 +1242,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1251,7 +1259,7 @@ msgstr "" "với bằng chứng. Chúng tôi giữ lý luận với nguồn để người tiếp theo có thể " "thấy cách giải thích đó đến từ đâu." -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1266,14 +1274,14 @@ msgstr "" "nên sở hữu trạng thái đó. Để di chuyển hành vi một cách an toàn, chúng ta " "cần khôi phục mối quan hệ đằng sau quyền truy cập bộ nhớ cũ." -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "Thứ tự tôi sử dụng bây giờ là:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1289,7 +1297,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1306,7 +1314,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1322,7 +1330,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1337,7 +1345,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1354,7 +1362,7 @@ msgstr "" "trình được xây dựng lại vẫn xây dựng và hoạt động chính xác dọc theo các con" " đường chúng ta tập thể dục." -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1368,7 +1376,7 @@ msgstr "" " sẵn cung cấp cho các agent một thất bại cụ thể để điều tra trước khi thực " "hiện một refactor hơn nữa." -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1386,7 +1394,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1405,7 +1413,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1416,12 +1424,12 @@ msgstr "" "nghĩa làm cho kiến thức phục hồi có thể sử dụng được.{ph1} Một cổng sau đó " "có thể xây dựng trên cả hai." -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "Điều gì làm cho điều này một sự thay đổi công nghiệp" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1434,7 +1442,7 @@ msgstr "" "việc của họ đã trở thành một trong những điều hữu ích nhất mà tôi có thể " "làm. Một công cụ tốt hơn có thể giúp với mọi chức năng sau này cần nó." -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1447,7 +1455,7 @@ msgstr "" " đó bất ngờ. Nếu phải đợi tôi quy định từng bước, phần lớn công việc vẫn gắn" " liền với sự chú ý của tôi." -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1460,7 +1468,7 @@ msgstr "" "thất bại sẽ giúp nó hiểu rõ sai lầm đủ để thử lại. Tôi vẫn phải quyết định " "xem bằng chứng tích lũy có hỗ trợ một cột mốc dự án hay không." -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1475,7 +1483,7 @@ msgstr "" "riêng nó. Tác nhân có thể sử dụng chúng để kiểm tra nguồn mà nó đề xuất và " "xem lời giải thích của nó giữ ở đâu." -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1493,7 +1501,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1514,7 +1522,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1532,7 +1540,7 @@ msgstr "" "quả mà nó bị ảnh hưởng. Dự án tiếp theo sau đó có thể kế thừa một công cụ " "mạnh mẽ hơn." -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1548,7 +1556,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1561,7 +1569,7 @@ msgstr "" "họ về phía trước. Làm việc trên một trò chơi có thể cải thiện các điều kiện " "bắt đầu cho một trò chơi khác." -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1573,12 +1581,12 @@ msgstr "" "dụng. Cải thiện những công cụ thay đổi bao nhiêu người tiếp theo—hoặc các " "agent tiếp theo—có thể được thực hiện." -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "Các dự án bây giờ chúng ta có thể xem xét" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1589,7 +1597,7 @@ msgstr "" " là hấp dẫn để đảo ngược kỹ sư và vẫn đòi hỏi nhiều sự chú ý của riêng tôi " "hơn tôi thực tế có thể cung cấp cho nó. Nhiều dự án sẽ ở lại ý tưởng." -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1606,7 +1614,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1617,7 +1625,7 @@ msgstr "" "và kiến thức tích lũy nào sẽ cho phép một agent làm việc về điều này một " "cách đáng tin cậy?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1628,12 +1636,12 @@ msgstr "" " Mỗi người có thể cải thiện cách chúng ta tiếp cận tiếp theo. Tôi muốn tiếp " "tục khám phá xem điều đó có thể đưa chúng ta đi bao xa." -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "Các cột mốc và nguồn dự án" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1667,7 +1675,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1701,7 +1709,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1719,7 +1727,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1743,7 +1751,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1765,7 +1773,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1781,7 +1789,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1802,7 +1810,7 @@ msgstr "" #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1816,7 +1824,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1836,27 +1844,27 @@ msgstr "" "N0zoM1z0 phản ánh về kỹ thuật đảo ngược thủ công, Tái Thiết Touhou với các " "tác nhân AI và cách các hợp chất kiến thức trên TH08, TH095 và PC-98 TH04 ." -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "Kinh nghiệm thực hiện giữa các dự án" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "Bài luận tái thiết Touhou" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -1865,18 +1873,18 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}Nhà{ph1}{ph2}/{ph3}Phòng thí nghiệm tốc độ khủng long" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "Kiểm tra → xây dựng lại → thay đổi" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "Xây dựng lại quy tắc tốc độ của khủng long." @@ -1885,7 +1893,7 @@ msgstr "Xây dựng lại quy tắc tốc độ của khủng long." #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1898,15 +1906,15 @@ msgstr "" "sử dụng quy tắc của nó để xây dựng trò chơi nhỏ này với {ph2}tốc độ điều " "chỉnh.{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "Trên trang này" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1914,7 +1922,7 @@ msgstr "{ph0}Chơi và thay đổi tốc độ{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1922,7 +1930,7 @@ msgstr "{ph0}Đọc quy tắc đã khôi phục{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1930,18 +1938,18 @@ msgstr "{ph0}Kiểm tra việc tái thiết{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}Hãy thử phân tích{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "Chơi và thay đổi tốc độ" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1952,49 +1960,49 @@ msgstr "" "thử một trò chơi chậm hơn hoặc nhanh hơn; nó chuyển sang một tốc độ cố định." " Chọn quy tắc đã khôi phục để bắt đầu từ 6 và tăng tốc dần trở lại." -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "Chơi bản dựng lại" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "Chơi" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "Nhảy ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "Chơi lại" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "Tốc độ" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "Sử dụng quy tắc tăng tốc đã khôi phục" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Quy tắc ban đầu: bắt đầu từ 6, sau đó tăng lên 13." -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Di chuyển thanh trượt để thiết lập tốc độ của riêng bạn. Không gian Hoặc " "Nhảy xóa một cây xương rồng." -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -2003,7 +2011,7 @@ msgstr "" "Cho PHÉP JavaScript để chơi tái thiết. Mã và giải thích ở trên vẫn có thể " "đọc được." -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "Đọc kịch BẢN REA trả về" @@ -2011,7 +2019,7 @@ msgstr "Đọc kịch BẢN REA trả về" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2026,7 +2034,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2036,18 +2044,18 @@ msgstr "" "Các cài đặt là {ph0}, {ph1} và {ph2}. Trò chơi chạy nhánh này trên bản cập " "nhật mà không có va chạm." -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "Sử dụng quy tắc tương tự trong trò chơi mới" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "Sao chép" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -2064,18 +2072,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}Tải xuống quy tắc tốc độ{ph1} · {ph2}Đọc mã trò chơi{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "Kiểm tra việc tái thiết" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -2086,27 +2094,27 @@ msgstr "" " và lập lịch tự động bị vô hiệu hóa. So sánh những tốc độ ghi lại với một " "phát lại của quy tắc phục hồi." -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "Cập nhật" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "Trò chơi gốc" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "Quy tắc được xây dựng lại" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "Chạy kiểm tra tốc độ" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " @@ -2115,14 +2123,14 @@ msgstr "" "Giá trị làm tròn đến ba số thập phân. Chi nhánh kiểm tra trước khi thêm, vì " "vậy gia số cuối cùng có thể mất tốc độ chỉ trên 13." -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "Hãy tự mình thử phân tích" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -2131,7 +2139,7 @@ msgstr "{ph0}Thiết LẬP REA {ph1} với agent mã hóa của bạn." #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2140,7 +2148,7 @@ msgstr "" "Theo dõi {ph0}các bước kết nối trình duyệt{ph1}, sử dụng {ph2} như url " "trang." -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -2157,7 +2165,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2169,7 +2177,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2183,7 +2191,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2198,7 +2206,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -2224,12 +2232,12 @@ msgstr "" "Đọc quy tắc tốc độ của trò chơi khủng long VỚI REA , xây dựng lại nó, sau đó" " thay đổi tốc độ và chơi." -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "Khủng long tốc độ tái thiết" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -2238,52 +2246,52 @@ msgstr "" "Khủng long mini-game. Sử dụng Nút Nhảy hoặc Nhấn Không gian trong khi trò " "chơi được tập trung." -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "Sao chép quy tắc tốc độ được xây dựng lại" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "Sao chép dấu nhắc phân tích khủng long" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}Nhà{ph1} / HỎI ĐÁP" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA CÂU HỎI THƯỜNG GẶP." -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "Thiết lập, cập nhật, phân tích và khắc phục sự cố." -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "Chủ đề" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -2291,7 +2299,7 @@ msgstr "{ph0}Thiết lập và cập nhật{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -2299,7 +2307,7 @@ msgstr "{ph0}Phân tích{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2307,31 +2315,31 @@ msgstr "{ph0}Khắc phục sự cố{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}Dữ liệu và chia sẻ{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "Thiết lập và cập nhật" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "Cài đặt REA thế nào?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "Thiết bị đầu cuối · thiết lập agent" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "Sao chép" @@ -2339,7 +2347,7 @@ msgstr "Sao chép" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2353,12 +2361,12 @@ msgstr "" "{ph0}Hướng dẫn thiết lập{ph1} trình bày các yêu cầu và bước phân tích đầu " "tiên." -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "NHỮNG agent mã hóa NÀO có thể sử DỤNG REA ?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2373,18 +2381,18 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}Kết nối agent mã hóa của bạn{ph1}." -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "Cập nhật REA thế nào?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " @@ -2393,13 +2401,13 @@ msgstr "" "REA phát hành thường xuyên, bao gồm sửa lỗi. Nếu bạn đã cài ĐẶT CLI với npm " ":" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "Thiết bị đầu cuối * CÀI ĐẶT CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2409,14 +2417,14 @@ msgstr "" "Thực hiện theo lệnh làm mới thiết lập được in bởi bản cập nhật. Nếu bạn " "thiết lập agent của bạn thông qua {ph0}, chạy đi:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "Thiết bị đầu cuối · thiết lập agent làm mới" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2428,14 +2436,14 @@ msgstr "" " cụ thể, nên cần chạy lại lệnh thiết lập để agent dùng bản mới. Với lệnh CLI" " chạy một lần, thêm lệnh cần dùng sau {ph0}." -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "Đang cài đặt kỹ năng từ skills.sh đủ chưa?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2447,24 +2455,24 @@ msgstr "" "REA{ph1} để kết nối MÁY chủ MCP và cài đặt kỹ năng phù hợp, sau đó khởi động" " lại agent của bạn để nó có thể gọi các công cụ." -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "Phân tích" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "Tôi có thể phân tích gì VỚI REA ?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "Bắt đầu với loại phần mềm bạn có:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2476,7 +2484,7 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2488,7 +2496,7 @@ msgstr "" #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2497,7 +2505,7 @@ msgstr "" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2509,12 +2517,12 @@ msgstr "" "phần sụn và tài nguyên đóng gói. {ph0}Xem các nghiên cứu điển hình{ph1} đối " "với các cuộc điều tra làm việc." -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "TÔI có cần Hopper , Ghidra hoặc IDA không ?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2526,7 +2534,7 @@ msgstr "" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2539,12 +2547,12 @@ msgstr "" " nào có thể được sử dụng. {ph0}Thiết lập phân tích các chương trình mã " "máy{ph1}." -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "Tôi có thể sử DỤNG REA mà không cần agent mã hóa không?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " @@ -2553,14 +2561,14 @@ msgstr "" "Vâng. CLI sử dụng cùng một quy trình phân tích. ĐỐI với ỨNG DỤNG JavaScript " "hoặc Electron cục BỘ:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "Thiết bị đầu cuối · phân tích ứng dụng tĩnh" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2571,13 +2579,13 @@ msgstr "" "{ph0}Sử DỤNG CLI {ph1} đối với các tùy chọn cài đặt." # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA trả về mã gì?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2592,7 +2600,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2604,12 +2612,12 @@ msgstr "" " kiểm tra việc thực hiện. Các {ph0} DX-Ball tính TOÁN{ph1} và {ph2}CTF cờ " "checker{ph3} cho thấy quá trình đó hoạt động như thế nào." -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "Tôi nên hỏi trợ lý điều gì?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2626,7 +2634,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2634,7 +2642,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2644,18 +2652,18 @@ msgstr "" "Thay thế đường dẫn bằng mục tiêu của bạn. Các {ph0}hướng dẫn{ph1} cung cấp " "lời nhắc cho các ví dụ gốc, Electron và trình duyệt." -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "Khắc phục sự cố" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "Tại sao agent của tôi không thể thấy CÁC CÔNG cụ REA?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2665,7 +2673,7 @@ msgstr "" "Khởi động lại hoặc kết nối lại agent của bạn sau khi thiết lập. Kiểm tra " "ĐĂNG ký REA của NÓ với {ph0}; CHO Codex :" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "Thiết bị đầu cuối * kiểm tra một khách hàng" @@ -2673,7 +2681,7 @@ msgstr "Thiết bị đầu cuối * kiểm tra một khách hàng" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2684,14 +2692,14 @@ msgstr "" "Nếu báo cáo hiển thị đăng ký bị thiếu hoặc cũ, hãy chạy thiết lập cho khách " "hàng đó:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "Thiết bị đầu cuối · sửa chữa thiết lập của một khách hàng" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2703,14 +2711,14 @@ msgstr "" "mạnh nhưng các công cụ vẫn vắng mặt, hãy kiểm tra LỖI KẾT nối MCP của khách " "hàng. {ph0}Thêm chẩn đoán thiết lập{ph1}." -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "Tôi có cần khởi ĐỘNG Hopper trước không?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2722,14 +2730,14 @@ msgstr "" " chạy đầu tiên của chế độ demo hoặc kích hoạt giấy phép trước khi phân tích " "không giám sát. {ph0}Xem thiết lập nhà cung cấp gốc{ph1}." -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "Tôi nên làm gì khi gặp lỗi?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2741,7 +2749,7 @@ msgstr "" #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2753,17 +2761,17 @@ msgstr "" "điều hành, loại mục tiêu, các bước để tái tạo và đầu ra lỗi. Bao gồm tên nhà" " cung cấp khi sự cố liên quan đến việc phân tích các chương trình mã máy." -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "Dữ liệu và chia sẻ" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "REA có tải lên ứng dụng của tôi không?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " @@ -2773,7 +2781,7 @@ msgstr "" "quả và chính sách dữ liệu của nhà cung cấp mô hình áp dụng cho các kết quả " "đó." -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "Làm thế nào tôi có thể chia sẻ một ví dụ hoặc đóng góp?" @@ -2782,7 +2790,7 @@ msgstr "Làm thế nào tôi có thể chia sẻ một ví dụ hoặc đóng g #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2798,7 +2806,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2822,77 +2830,77 @@ msgstr "" "Câu trả lời cho CÁC CÂU HỎI REA phổ biến: cài đặt, cập nhật, công cụ phân " "tích, agent mã hóa, khắc phục sự cố và chia sẻ ví dụ." -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "CÂU hỏi thường gặp VỀ REA" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "Sao CHÉP lệnh THIẾT LẬP REA" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "Sao CHÉP lệnh cập NHẬT REA" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "Sao chép lệnh làm mới thiết lập tác nhân" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "Sao CHÉP lệnh PHÂN tích REA CLI" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "Sao chép lời nhắc phân tích ví dụ" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "Sao chép lệnh chẩn đoán khách hàng" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "Sao chép lệnh thiết lập phạm vi" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}Nhà{ph1} / Cuộc điều tra đầu tiên của bạn" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "Tìm ra nơi{ph0}xuất khẩu ghi chú đi." -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" @@ -2901,14 +2909,14 @@ msgstr "" "SỬ DỤNG REA để kiểm tra một ứng dụng nhỏ, hãy làm theo Nút Xuất ghi Chú Của " "NÓ và tự kiểm tra một chi tiết." -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "Trong bài tập này" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2916,7 +2924,7 @@ msgstr "{ph0}1. Thiết lập{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2924,7 +2932,7 @@ msgstr "{ph0}2. Hỏi về xuất khẩu{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2932,7 +2940,7 @@ msgstr "{ph0}3. Làm theo câu trả lời{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2940,13 +2948,13 @@ msgstr "{ph0}4. Kiểm tra dự đoán{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. Hỏi một câu hỏi khác{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. Kết nối agent CỦA BẠN VỚI REA" @@ -2959,29 +2967,29 @@ msgstr "1. Kết nối agent CỦA BẠN VỚI REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "Sao chép" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "Hoặc chạy lệnh này trong thiết bị đầu cuối của bạn:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " @@ -2990,14 +2998,14 @@ msgstr "" "Xem lại kế hoạch, phê duyệt thiết lập, sau đó khởi động lại agent của bạn. " "Đã kết nối? Tiếp tục dưới đây." -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. Hỏi CSV được viết ở đâu" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3009,7 +3017,7 @@ msgstr "" "Agent của bạn có thể kiểm tra mã của nó mà không cần cài đặt hoặc khởi CHẠY " "Electron ." -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -3021,14 +3029,14 @@ msgstr "" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Tải xuống VÍ DỤ ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3038,12 +3046,12 @@ msgstr "" "Nếu agent của bạn không thể tải xuống tệp, hãy tự giải nén kho lưu trữ này. " "Cung cấp cho nó con đường đến {ph0} thư mục và cùng một câu hỏi xuất." -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. Làm theo câu trả lời trở lại mã" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "Tìm kiếm một lời giải thích ngắn với các tham chiếu tệp và dòng:" @@ -3052,7 +3060,7 @@ msgstr "Tìm kiếm một lời giải thích ngắn với các tham chiếu t #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3064,12 +3072,12 @@ msgstr "" "CSV và viết {ph1} trong thư mục Tải xuống của người dùng. Các cột là {ph2} " "và {ph3}." -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "Từ nút đến trình ghi tệp" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" @@ -3078,7 +3086,7 @@ msgstr "" "PHÂN tích TĨNH CỦA REA ghép nối thông báo với trình xử lý của nó. Điểm đến " "được đọc từ mã." -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -3090,18 +3098,18 @@ msgstr "" #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}Xem dấu vết mã đầy đủ và ghi LẠI KẾT quả REA{ph1}." -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. Kiểm tra dự đoán" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " @@ -3110,19 +3118,19 @@ msgstr "" "Dấu phẩy phân TÁCH CÁC CỘT CSV. Điều gì xảy ra khi một tiêu đề ghi chú chứa " "dấu phẩy hoặc dấu ngoặc kép?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "Tự chạy kiểm tra" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "Mở một thiết bị đầu cuối trong giải nén {ph0} thư mục:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -3132,17 +3140,17 @@ msgstr "" " Zsh. Agent của bạn có thể chạy CÙNG MỘT JavaScript trong vỏ nền tảng của " "bạn." -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. Hỏi một câu hỏi khác" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "Hãy thử theo dõi trong cùng một cuộc trò chuyện:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " @@ -3151,7 +3159,7 @@ msgstr "" "Điều gì xảy ra nếu tập tin không thể được viết? Thực hiện theo các lỗi trở " "lại trang." -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -3164,7 +3172,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3178,7 +3186,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3192,7 +3200,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -3216,65 +3224,65 @@ msgstr "" "Hãy thử REA trên Một Ứng dụng Ghi chú nhỏ. Thiết lập agent của bạn, hỏi ghi " "chú đã xuất đi đâu và kiểm tra TRÌNH định dạng CSV với tiêu đề mẫu." -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "CUỘC điều tra REA đầu tiên của bạn" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "Sao CHÉP lời nhắc cài ĐẶT REA" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "Sao chép lệnh thiết lập" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "Sao Chép Ghi chú điều tra nhanh chóng" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "Sao CHÉP CSV kiểm tra dấu nhắc" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "Sao chép lệnh kiểm tra định dạng" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}Nhà{ph1} / Bắt đầu" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "Thiết LẬP REA ." -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." @@ -3282,49 +3290,49 @@ msgstr "" "Kết nối REA với agent mã hóa của bạn hoặc kiểm tra một ứng dụng cục bộ từ " "thiết bị đầu cuối của bạn." -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "Mở một thiết bị đầu cuối và kiểm tra:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "Thiết bị đầu cuối" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "Sao chép" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0} Windows (PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3337,7 +3345,7 @@ msgstr "" #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3347,17 +3355,17 @@ msgstr "" "Nếu PowerShell sau đó nói {ph0}\"chạy tập lệnh bị vô hiệu hóa trên hệ thống " "này\"{ph1} khi bạn chạy {ph2}, chạy cái này một lần và thử lại:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "NẾU bạn sử DỤNG Homebrew :" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "Nếu không:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "Đóng Thiết bị đầu cuối, mở lại, sau đó:" @@ -3365,7 +3373,7 @@ msgstr "Đóng Thiết bị đầu cuối, mở lại, sau đó:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3377,7 +3385,7 @@ msgstr "" #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3389,7 +3397,7 @@ msgstr "" #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3399,14 +3407,14 @@ msgstr "" "Thích một trình cài đặt thông thường? Tải xuống phiên bản LTS từ " "{ph0}nodejs.org{ph1}." -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "Tùy chọn thiết lập" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3414,7 +3422,7 @@ msgstr "{ph0}Kết nối agent mã hóa của bạn{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3422,7 +3430,7 @@ msgstr "{ph0}Sử DỤNG CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3430,18 +3438,18 @@ msgstr "{ph0}Thiết lập phân tích các chương trình mã máy{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}Nhận trợ giúp{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "Kết nối agent mã hóa của bạn" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3453,12 +3461,12 @@ msgstr "" "Grok Build và CÁC máy KHÁCH MCP được hỗ trợ khác. Trình kết nối của Grok Bot" " được thêm vào từ cuộc trò chuyện của Nó." -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "Mới đối với agent mã hóa?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3470,7 +3478,7 @@ msgstr "" " cầu trước khi thực hiện thay đổi. REA cung cấp cho nó các công cụ kỹ thuật" " ngược." -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3481,7 +3489,7 @@ msgstr "" #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3494,7 +3502,7 @@ msgstr "" #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3507,7 +3515,7 @@ msgstr "" #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3517,7 +3525,7 @@ msgstr "" "{ph0}{ph1} OpenCode {ph2}{ph3}, mã nguồn mở. Kết nối nhà cung cấp mô hình " "bạn chọn." -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3534,18 +3542,18 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "Hoặc tự chạy thiết lập" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "Làm cách nào để mở một thiết bị đầu cuối?" @@ -3554,7 +3562,7 @@ msgstr "Làm cách nào để mở một thiết bị đầu cuối?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3570,7 +3578,7 @@ msgstr "" #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3584,7 +3592,7 @@ msgstr "" #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3599,7 +3607,7 @@ msgstr "" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3609,7 +3617,7 @@ msgstr "" "Dán một lệnh với {ph0} {ph1} (macOS : {ph2} {ph3}; THIẾT BỊ ĐẦU CUỐI Linux: " "{ph4} {ph5} {ph6}), sau đó nhấn Enter." -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3620,12 +3628,12 @@ msgstr "" " và kỹ năng điều tra phù hợp, giữ một bản sao lưu cấu hình hiện có. Nó hỏi " "trước khi áp dụng các thay đổi." -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "Khởi động lại máy khách của bạn khi thiết lập kết thúc." -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "Làm cách nào để khởi động lại khách hàng của tôi?" @@ -3634,7 +3642,7 @@ msgstr "Làm cách nào để khởi động lại khách hàng của tôi?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3650,7 +3658,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3660,7 +3668,7 @@ msgstr "" "{ph0}Agent thiết bị đầu cuối{ph1} (Claude Code, Codex, Gemini CLI): thoát " "khỏi phiên và bắt đầu lại." -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3670,7 +3678,7 @@ msgstr "" " với ỨNG dụng JavaScript hoặc Electron, bạn có thể bắt đầu với:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3680,12 +3688,12 @@ msgstr "" "Nhìn kìa {ph0} và tìm cách nó xuất dữ liệu. Hiển thị các điểm vào, cuộc gọi " "và phụ thuộc liên quan, với các vị trí nguồn cho những phát hiện của bạn." -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "Thay thế đường dẫn bằng mục tiêu cục bộ của bạn." -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "Làm cách nào để có được đường dẫn đầy đủ của một thư mục?" @@ -3694,7 +3702,7 @@ msgstr "Làm cách nào để có được đường dẫn đầy đủ của m #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3709,7 +3717,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3721,7 +3729,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3731,19 +3739,19 @@ msgstr "" "{ph0}Bất kỳ hệ thống:{ph1} kéo thư mục vào cửa sổ đầu cuối và đường dẫn của " "nó xuất hiện." -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "" "Trong một thiết bị đầu cuối, đặt dấu ngoặc kép xung quanh một đường dẫn có " "chứa khoảng trắng." -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "Sử DỤNG CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " @@ -3752,14 +3760,14 @@ msgstr "" "Phân tích THƯ mục ỨNG DỤNG JavaScript hoặc Electron hoặc KHO LƯU TRỮ ASAR mà" " không cần chạy ứng dụng:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "Phân tích ứng dụng tĩnh" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3769,13 +3777,13 @@ msgstr "" "Thay thế đường dẫn bằng thư mục ứng dụng được trích xuất của bạn hoặc {ph0} " "tập tin. TRÊN Windows, một đường dẫn như {ph1} hoạt động ở đây." -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "Tôi tìm thấy một ứng dụng ở đâu .tập tin asar?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3786,7 +3794,7 @@ msgstr "Electron ứng dụng thường giữ nó trong một {ph0} thư mục:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3798,7 +3806,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3811,21 +3819,21 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0} Linux :{ph1} thường xuyên {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "" "Một số ứng dụng cài đặt ở nơi khác. Tìm kiếm thư mục của ứng dụng cho {ph0}." -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3837,31 +3845,31 @@ msgstr "" "kết quả." #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "Nếu bạn muốn một vĩnh viễn {ph0} lệnh trong shell của bạn:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "Cài ĐẶT CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}Tiếp tục VỚI hướng dẫn ứng DỤNG JavaScript{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "Thiết lập phân tích các chương trình mã máy" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " @@ -3871,12 +3879,12 @@ msgstr "" "hình MỘT bên dưới, sau đó cung cấp CHO REA tệp thực thi hoặc thư viện của " "bạn." -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "Chọn một công cụ: Ghidra, Hopper hoặc IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3888,17 +3896,17 @@ msgstr "" "ngược gốc cho kiến trúc máy chủ của bạn. Đặt đường dẫn trước khi chạy thiết " "lập:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "Kết nối CÀI ĐẶT Ghidra của bạn" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra kết nối * macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3910,12 +3918,12 @@ msgstr "" "TRÊN Linux arm64, bạn có thể cần xây DỰNG RIÊNG TRÌNH dịch ngược GỐC CỦA " "Ghidra." -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "Kết NỐI Ghidra TRÊN Windows" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3926,12 +3934,12 @@ msgstr "" " pe gốc trên các ổ đĩa ntfs cục bộ cố định. Sử DỤNG Ghidra 12.1 hiện có.x " "cài đặt VÀ 64-bit JDK 21 hoặc mới hơn:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra kết nối * Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." @@ -3939,7 +3947,7 @@ msgstr "" "Thay thế hai đường dẫn bằng cài đặt của bạn, sau đó xem lại kế hoạch thiết " "lập." -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" @@ -3948,7 +3956,7 @@ msgstr "" "Kết nối Hopper TRÊN macOS hoặc Linux . Chạy lệnh thiết lập ở trên; nó phát " "hiện cài đặt hiện có hoặc cung cấp kế hoạch cài đặt để bạn phê duyệt." -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " @@ -3957,7 +3965,7 @@ msgstr "" "TRÊN macOS, hoàn THÀNH Hopper ' s lựa chọn chạy đầu tiên của chế độ demo " "hoặc kích hoạt giấy phép trước khi phân tích không giám sát." -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3968,7 +3976,7 @@ msgstr "" " cho GUI đính kèm hoặc cơ sở dữ liệu không đầu. PHÂN tích không đầu Linux " "và macOS vẫn chưa được xác minh." -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "Kết nối ĐĂNG ký IDA MCP HIỆN CÓ" @@ -3978,7 +3986,7 @@ msgstr "Kết nối ĐĂNG ký IDA MCP HIỆN CÓ" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3990,13 +3998,13 @@ msgstr "" "một tệp JSON. Một hiện có {ph3} đối tượng với một {ph4} nhập cảnh cũng được " "chấp nhận. Trỏ REA vào tệp đó trước khi thiết lập:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA kết nối * Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4013,7 +4021,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4025,29 +4033,29 @@ msgstr "" "Đối với một agent, bao gồm {ph1} trong môi trường ĐĂNG ký REA và chọn IDA " "khi mở nhị phân." -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "Đối với THIẾT LẬP Ghidra hiện có, hãy kiểm tra một chức năng với:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "Phân tích chức năng" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "Thay thế {ph0} với tên chức năng hoặc địa chỉ bạn muốn kiểm tra." -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "Cách phân tích các phiên chương trình mã máy hoạt động" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -4060,7 +4068,7 @@ msgstr "" #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4070,18 +4078,18 @@ msgstr "" "{ph0}Thực hiện theo phân tích ví dụ về chương trình mã máy{ph1} để xem kết " "quả hàm dẫn đến một phép tính được phục hồi như thế nào." -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "Nhận trợ giúp" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "Nếu agent của bạn không THẤY REA" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4091,27 +4099,27 @@ msgstr "" "Khởi động lại hoặc kết nối lại máy khách sau khi thiết lập. Kiểm tra KẾT nối" " REA của NÓ với {ph0}; CHO Codex :" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "Kiểm tra một khách hàng" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "Nếu một nhà cung cấp cần chú ý" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "Kiểm tra nhà cung cấp bạn đang sử dụng. CHO Ghidra :" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "Kiểm tra một nhà cung cấp" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "Báo cáo đưa ra kiểm tra thất bại và một bước tiếp theo được đề xuất." @@ -4120,7 +4128,7 @@ msgstr "Báo cáo đưa ra kiểm tra thất bại và một bước tiếp theo #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4133,7 +4141,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4147,7 +4155,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4160,7 +4168,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -4185,112 +4193,112 @@ msgstr "" "Electron cục bộ từ thiết bị đầu cuối. Thiết lập, câu hỏi đầu tiên và hướng " "dẫn nhà cung cấp bản địa." -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "Sao CHÉP kiểm tra PHIÊN BẢN Node.js" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "Sao CHÉP lệnh cài ĐẶT Node.js CHO Windows" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "Sao Chép Lệnh Chính sách Thực Thi PowerShell" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "Sao CHÉP lệnh cài ĐẶT Homebrew Node.js" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "Sao chép lệnh cài đặt fnm CHO macOS" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "Sao CHÉP Node.js 24 lệnh CHO macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "Sao chép lệnh cài đặt fnm CHO Linux" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "Sao CHÉP Node.js 24 lệnh CHO Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA bắt đầu hướng dẫn" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "Sao CHÉP lời nhắc cài ĐẶT REA" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "Sao chép lệnh thiết lập tác nhân" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "Sao CHÉP lệnh PHÂN tích JavaScript" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "Sao CHÉP lệnh cài ĐẶT CLI" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "Sao chép lệnh kết nối Ghidra cho macOS và Linux" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "Sao CHÉP Ghidra kết nối CHO Windows PowerShell" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "Sao CHÉP IDA kết nối CHO Windows PowerShell" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "Sao chép lệnh phân tích chức năng gốc" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "Sao chép lệnh chẩn đoán khách hàng" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "Sao chép lệnh chẩn đoán nhà cung cấp" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -4299,20 +4307,20 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}Nhà{ph1} / {ph2}Hướng dẫn{ph3} / Quan sát trình duyệt" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "Xem những gì xảy ra{ph0}khi bạn nhấp vào." -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " @@ -4321,14 +4329,14 @@ msgstr "" "Sử dụng một ứng dụng trình duyệt nhỏ để kết nối một hành động, yêu cầu mạng " "của nó và JavaScript xây dựng tải xuống." -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "Trong hướng dẫn này" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -4336,7 +4344,7 @@ msgstr "{ph0}Ví dụ{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -4344,7 +4352,7 @@ msgstr "{ph0}Mở trình duyệt{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4352,7 +4360,7 @@ msgstr "{ph0}Hỏi agent của bạn{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -4360,13 +4368,13 @@ msgstr "{ph0}Chụp TỪ CLI {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}Đọc yêu cầu và tập lệnh{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "Điều gì xảy ra khi bạn nhấp Vào Xuất?" @@ -4376,7 +4384,7 @@ msgstr "Điều gì xảy ra khi bạn nhấp Vào Xuất?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4388,7 +4396,7 @@ msgstr "" "Nhấp vào nó tải {ph4}, định dạng hai ghi chú DƯỚI DẠNG CSV và bắt đầu tải " "xuống." -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "Từ nhấp VÀO TẢI XUỐNG CSV" @@ -4399,7 +4407,7 @@ msgstr "Từ nhấp VÀO TẢI XUỐNG CSV" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4415,7 +4423,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4433,7 +4441,7 @@ msgstr "" #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4443,17 +4451,17 @@ msgstr "" "{ph0}03 * agent của Bạn{ph1}{ph2}Đọc mã xuất{ph3}{ph4}Kết nối yêu cầu quan " "sát được với {ph5} trong {ph6}.{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "Bắt đầu chụp trước khi nhấp Vào xuất ghi chú." -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "MỞ Chrome với gỡ lỗi từ xa" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " @@ -4462,21 +4470,21 @@ msgstr "" "Mở Ví Dụ Ghi chú được lưu trữ với cấu hình trình duyệt riêng biệt và cổng gỡ" " lỗi cục bộ. TRÊN Linux :" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "Khởi động trình duyệt ví dụ" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "Sao chép" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " @@ -4486,7 +4494,7 @@ msgstr "" "hoặc Windows . BẠN có thể thay THẾ url trang bằng một trang khác mà bạn muốn" " kiểm tra." -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" @@ -4495,7 +4503,7 @@ msgstr "" "REA kết nối với trình duyệt hiện có này. Bạn giữ quyền kiểm soát trang, thực" " hiện hành động và đóng trình duyệt khi hoàn tất." -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "Yêu cầu agent của bạn xem một hành động" @@ -4508,7 +4516,7 @@ msgstr "Yêu cầu agent của bạn xem một hành động" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4520,7 +4528,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4532,7 +4540,7 @@ msgstr "" "nào?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4542,7 +4550,7 @@ msgstr "" "Ví dụ nhắc nhở. Cung cấp cho agent của bạn điểm cuối gỡ lỗi, {ph0}, VÀ url " "trang. Hãy để nó bắt đầu chụp trước khi bạn nhấp vào." -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4553,23 +4561,23 @@ msgstr "" "đọc bằng chứng kết quả. Sau đó, nó có thể kiểm tra tập lệnh đằng sau xuất " "khẩu." -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "Hoặc chụp từ thiết bị đầu cuối" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "Tìm ID mục tiêu của trang:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "Tìm trang" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4579,14 +4587,14 @@ msgstr "" "Chọn mục tiêu với Url Ví dụ Ghi chú. Thay thế {ph0} BÊN dưới VỚI ID của NÓ, " "sau đó chạy:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "Chụp mười giây tiếp theo" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4596,7 +4604,7 @@ msgstr "" "Để lệnh kết nối trong vài giây, sau đó nhấp vào {ph0}Xuất ghi chú{ph1} trong" " trình duyệt đó. Kết quả đến sau khi cửa sổ quan sát kết thúc." -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4606,49 +4614,49 @@ msgstr "" "Kết quả đã chụp bao gồm trang đã chọn, hoạt động mạng trong cửa sổ đó và " "hình dạng của phản hồi JSON. Yêu cầu trước đó là bên ngoài chụp này." -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "Đọc yêu cầu và xuất tập lệnh" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "Được ghi BẰNG REA 4.1.0 trên Ví Dụ Ghi chú cục Bộ" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "Thực tế bị bắt" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "Giá trị" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "Yêu cầu" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "Phản hồi" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "Yêu cầu người khởi xướng" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} * kịch bản" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "Cấu trúc phản hồi" @@ -4656,19 +4664,19 @@ msgstr "Cấu trúc phản hồi" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} với {ph1} và {ph2} lĩnh vực" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "Đọc các tập lệnh đã tải" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4679,7 +4687,7 @@ msgstr "" "Đọc nguồn tập lệnh đã chụp để xem dữ liệu được sử dụng như thế nào:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4692,7 +4700,7 @@ msgstr "" "cầu {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4704,7 +4712,7 @@ msgstr "" #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4729,65 +4737,65 @@ msgstr "" "Quan sát Một Ghi chú xuất KHẨU VỚI REA : chọn một trang trình duyệt, chụp " "một nhấp chuột, kiểm tra các yêu cầu và làm theo các kịch bản xuất khẩu." -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "Quan sát trình duyệt" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "Sao chép bắt đầu trình duyệt ví dụ" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "Sao chép ví dụ dấu nhắc" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "Sao chép tìm trang" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "Sao chép chụp mười giây tiếp theo" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "Sao chép đọc các tập lệnh đã tải" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}Nhà{ph1} / Hướng dẫn" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA hướng dẫn." -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " @@ -4796,37 +4804,37 @@ msgstr "" "Phân tích chức năng gốc, xuất Electron hoặc yêu cầu trình duyệt. Mỗi hướng " "dẫn bao gồm một lời nhắc, mã và kết quả." -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "Điều tra đầu tiên" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "Thiết LẬP REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "Kết nối agent mã hóa của bạn hoặc SỬ dụng REA từ thiết bị đầu cuối." -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "Bắt đầu VỚI REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "Chương trình mã máy" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "Khôi phục tính toán vị trí âm thanh trái/phải" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," @@ -4835,22 +4843,22 @@ msgstr "" "Bắt đầu với MỘT TRÒ CHƠI Windows thực thi. Kiểm tra hướng dẫn, theo dõi hàm " "gọi, đọc hằng Số và kiểm Tra C đã khôi Phục." -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "Phân tích hướng dẫn chương trình mã máy" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "Thực HIỆN theo một CSV xuất KHẨU" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " @@ -4860,14 +4868,14 @@ msgstr "" "trước và quy trình chính. SỬ DỤNG REA để kết nối api, KÊNH IPC và trình ghi " "tệp." -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript & Electron hướng dẫn" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." @@ -4875,17 +4883,17 @@ msgstr "" "Đối với một ứng dụng đóng gói lớn hơn, hãy làm theo {ph0} Cầu clipboard CỦA " "Notion{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "Hành vi trình duyệt" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "Quan sát một cú nhấp chuột" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " @@ -4894,7 +4902,7 @@ msgstr "" "Mở Một Ví Dụ Ghi chú làm việc, chụp yêu cầu xuất và tìm mã biến phản hồi của" " nó thành tải xuống." -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "Hướng dẫn quan sát trình duyệt" @@ -4913,12 +4921,12 @@ msgstr "" "Tìm HIỂU REA thông qua các ví dụ làm việc ngắn: tính toán gốc, xuất Electron" " CSV và yêu cầu trình duyệt." -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -4927,20 +4935,20 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}Nhà{ph1} / {ph2}Hướng dẫn{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "Theo dõi Electron {ph0} CSV xuất khẩu." -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " @@ -4949,14 +4957,14 @@ msgstr "" "Thực hiện theo một nút bấm từ api trang, THÔNG qua Electron IPC, ĐẾN TRÌNH " "ghi tệp CSV." -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "Trong hướng dẫn này" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4964,7 +4972,7 @@ msgstr "{ph0}Ví dụ{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4972,7 +4980,7 @@ msgstr "{ph0}Hỏi agent của bạn{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4980,7 +4988,7 @@ msgstr "{ph0}Theo dõi mã xuất{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4988,20 +4996,20 @@ msgstr "{ph0}Hãy thử ví dụ{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}Kiểm TRA NHÀ văn CSV{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"Xuất ghi chú\" đi đâu?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5013,7 +5021,7 @@ msgstr "" "chú{ph1} gọi MỘT API trong trang, đi vào quy trình chính và VIẾT CSV . Hành " "vi được trải rộng trên một số tệp." -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "XUẤT CSV qua CÁC quy TRÌNH Electron" @@ -5027,7 +5035,7 @@ msgstr "XUẤT CSV qua CÁC quy TRÌNH Electron" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5044,7 +5052,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5061,7 +5069,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5074,13 +5082,13 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} định dạng các ghi chú → {ph1} viết {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -5091,14 +5099,14 @@ msgstr "" "API được hiển thị. Đường dẫn được suy ra từ mã; chụp thời gian chạy có thể " "kiểm tra những gì thực thi." -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "Hỏi VỀ xuất CSV" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5116,14 +5124,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "Sao chép" @@ -5134,7 +5142,7 @@ msgstr "Sao chép" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5145,7 +5153,7 @@ msgstr "" "trong ứng dụng này. CSV được tạo ở đâu?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5154,7 +5162,7 @@ msgid "" msgstr "" "Ví dụ nhắc nhở. Bao gồm đường dẫn tuyệt đối đến thư mục ứng dụng hoặc {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -5165,17 +5173,17 @@ msgstr "" "giới quy trình. Agent của bạn sử dụng bản đồ đó để thu hẹp cuộc điều tra về " "tính năng xuất." -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "Theo dõi mã xuất" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "Trang gọi MỘT API nhỏ" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -5186,7 +5194,7 @@ msgstr "" #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5198,7 +5206,7 @@ msgstr "" #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5208,7 +5216,7 @@ msgstr "" "Đọc trình xử lý trả lời câu hỏi ban đầu: {ph0} định dạng các ghi chú và quá " "trình chính viết {ph1} vào Thư mục Tải xuống của người dùng." -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " @@ -5217,7 +5225,7 @@ msgstr "" "Được GHI LẠI bởi REA 4.1.0 trên ví dụ có thể tải xuống bên dưới. Vị trí " "nguồn đi kèm VỚI CÁC PHÁT hiện API, kênh và trình xử lý." -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "Tự phân tích ví dụ" @@ -5225,25 +5233,25 @@ msgstr "Tự phân tích ví dụ" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}Tải xuống VÍ DỤ ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "Duyệt qua sáu tệp nguồn" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "Phân tích ứng dụng tĩnh" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5253,7 +5261,7 @@ msgstr "" "Thay thế đường dẫn bằng thư mục bạn đã giải nén. Bạn sẽ tìm thấy một KÊNH " "IPC và một trình xử lý phù hợp trong {ph0}. Vị trí nguồn đang ở {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -5264,13 +5272,13 @@ msgstr "" "đường DẪN ASAR của nó. Một tác nhân có thể theo một chuỗi ký tự, TÊN API " "hoặc KÊNH IPC VỚI CÁC CÔNG cụ truy tìm tính năng CỦA REA." -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "Kiểm TRA NHÀ văn CSV" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5280,7 +5288,7 @@ msgstr "" "Theo dõi {ph0} để xử lý của nó. Đầu vào nào đạt đến trình ghi CSV và điều gì" " sẽ xảy ra nếu việc ghi tệp không thành công?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -5295,7 +5303,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5309,7 +5317,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5323,7 +5331,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -5349,32 +5357,32 @@ msgstr "" "TRÌNH xử lý IPC với REA . Bao gồm các tệp ví dụ có thể tải xuống và kết quả " "phân tích đã được xác minh." -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "Sao chép ví dụ dấu nhắc" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "Sao chép phân tích ứng dụng tĩnh" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -5383,7 +5391,7 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" @@ -5391,13 +5399,13 @@ msgstr "" "{ph0}Nhà{ph1} / {ph2}Hướng dẫn{ph3} / Phân tích các chương trình mã máy" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "Khôi PHỤC DX-Ball ' s{ph0}tính toán vị trí âm thanh trái/phải." -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " @@ -5406,14 +5414,14 @@ msgstr "" "Kiểm Tra các hướng dẫn ban Đầu, xác Định đầu vào và hằng số, sau Đó kiểm Tra" " C đã khôi Phục." -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "Trong hướng dẫn này" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -5421,7 +5429,7 @@ msgstr "{ph0}Ví dụ{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -5429,7 +5437,7 @@ msgstr "{ph0}Hỏi agent của bạn{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -5437,7 +5445,7 @@ msgstr "{ph0}Đọc KẾT QUẢ REA{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -5445,18 +5453,18 @@ msgstr "{ph0}Phục hồi và kiểm tra{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}Sử dụng nhị phân của riêng bạn{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "Tính toán trái / phải định vị âm thanh stereo" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -5467,7 +5475,7 @@ msgstr "" #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5479,7 +5487,7 @@ msgstr "" "{ph1}. REA cũng trả về các hướng dẫn và hàm gọi của nó, cung cấp cho tác " "nhân một cách để điều tra số học bị thiếu." -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "Mới đối với các điều khoản này?" @@ -5488,7 +5496,7 @@ msgstr "Mới đối với các điều khoản này?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5500,7 +5508,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5513,7 +5521,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5526,7 +5534,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5538,7 +5546,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5548,7 +5556,7 @@ msgstr "" "{ph0}Hằng số:{ph1} số cố định được lưu trữ trong chương trình, đọc như byte " "thô và giải mã." -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "Ba bằng chứng, một phép tính" @@ -5559,7 +5567,7 @@ msgstr "Ba bằng chứng, một phép tính" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5576,7 +5584,7 @@ msgstr "" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5594,7 +5602,7 @@ msgstr "" #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5604,7 +5612,7 @@ msgstr "" "{ph0}03 * Byte Dữ liệu{ph1}{ph2}Các hằng số số{ph3}{ph4}Tham chiếu byte giải" " mã để {ph5}, {ph6} và một giá trị quy mô.{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " @@ -5613,7 +5621,7 @@ msgstr "" "REA cung cấp các hướng dẫn, mối quan hệ cuộc gọi chức năng và byte. Các " "agent giải thích chúng cùng nhau." -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "Hỏi về hành vi" @@ -5622,7 +5630,7 @@ msgstr "Hỏi về hành vi" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5632,19 +5640,19 @@ msgstr "" "Sau {ph0}kết NỐI REA với agent của bạn{ph1} và {ph2}thiết lập phân tích công" " cụ chương trình mã máy{ph3}, cung cấp thực thi cục bộ và một câu hỏi:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "Tôi nên sử dụng công cụ phân tích nào?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA cần một trong số này để đọc các chương trình gốc:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5658,7 +5666,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5670,7 +5678,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5680,7 +5688,7 @@ msgstr "" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5695,14 +5703,14 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "Sao chép" @@ -5713,7 +5721,7 @@ msgstr "Sao chép" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5723,7 +5731,7 @@ msgstr "" "{ph0}›{ph1}{ph2}SỬ dụng REA để tìm CÁCH DX-Ball tính toán định vị âm thanh " "nổi. Giải thích tính toán và hiển thị mã.{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5735,7 +5743,7 @@ msgstr "" "bản sao của riêng bạn hoặc hỏi cùng một loại câu hỏi về một chương trình " "Windows nhỏ khác mà bạn có." -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "Làm cách nào để có được đường dẫn đầy đủ của tệp?" @@ -5744,7 +5752,7 @@ msgstr "Làm cách nào để có được đường dẫn đầy đủ của t #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5759,7 +5767,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5771,7 +5779,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5781,17 +5789,17 @@ msgstr "" "{ph0}Bất kỳ hệ thống:{ph1} kéo tệp vào cửa sổ đầu cuối và đường dẫn của nó " "xuất hiện." -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "Đọc KẾT QUẢ REA" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "Đọc đầu vào" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " @@ -5800,13 +5808,13 @@ msgstr "" "Các hướng dẫn tải một đối số nguyên và chuyển đổi nó cho số học dấu phẩy " "động. Đây là đầu vào vắng mặt từ chế độ xem mã giả đầu tiên." -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "Theo dõi hàm gọi" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5816,12 +5824,12 @@ msgstr "" "REA xác định hàm gọi gạch-hit. Các hướng dẫn trước đó của nó nhân tọa độ " "gạch với 30; thêm {ph0} (20) cho vị trí màn hình của gạch." -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "Đọc các hằng số được tham chiếu" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " @@ -5830,12 +5838,12 @@ msgstr "" "Số học tham chiếu các địa chỉ này. Đọc các byte cung cấp các giá trị thực " "tế; thứ tự hướng dẫn cho tác nhân biết cách chúng được sử dụng." -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "Viết và kiểm tra chức năng đã khôi phục" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5846,7 +5854,7 @@ msgstr "" " khi chuyển đổi số nguyên. Tính toán đặt trung tâm của màn hình ở trung tâm " "của trường âm thanh nổi." -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5859,20 +5867,20 @@ msgstr "" #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}Xem điều tra đầy đủ và so sánh assembly-To-c{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "Hãy thử nó với nhị phân của riêng bạn" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5886,7 +5894,7 @@ msgstr "" " để điều tra. Các câu hỏi bắt đầu hữu ích bao gồm \" tệp này được phân tích " "cú pháp Như thế nào?\"hoặc\" chức năng nào xử lý hành động menu này?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " @@ -5895,13 +5903,13 @@ msgstr "" "Nếu bạn đã biết tên hoặc địa chỉ chức năng, bạn có thể truy vấn nó từ thiết " "bị đầu cuối. Để CÀI ĐẶT Ghidra được định cấu HÌNH:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "Phân tích chức năng" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5915,7 +5923,7 @@ msgstr "" "phiên của NÓ. Các truy vấn MCP của agent của bạn sử dụng lại nhị phân đã " "nhập trong khi phiên đó đang mở." -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5939,50 +5947,50 @@ msgstr "" "Khôi phục tính toán gốc VỚI REA : kiểm Tra hướng Dẫn, theo dõi hàm gọi, đọc " "hằng số và kiểm Tra Tái Tạo C." -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "Phân tích các chương trình mã máy" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "Sao chép ví dụ dấu nhắc" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "Sao chép phân tích chức năng" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "Thiết LẬP REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5990,7 +5998,7 @@ msgstr "{ph0}Thiết LẬP REA {ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5998,7 +6006,7 @@ msgstr "{ph0}RE LÀ GÌ?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -6006,7 +6014,7 @@ msgstr "{ph0}REA giúp gì?{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -6014,7 +6022,7 @@ msgstr "{ph0}Chơi Dinosaur miễn phí{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -6022,7 +6030,7 @@ msgstr "{ph0}Máy tính{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -6030,7 +6038,7 @@ msgstr "{ph0}Thử REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -6038,7 +6046,7 @@ msgstr "{ph0}Tìm hiểu sâu hơn{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -6046,25 +6054,25 @@ msgstr "{ph0}Trợ giúp & phản hồi{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}Cộng đồng{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "Kỹ thuật đảo ngược, với agent mã hóa của bạn" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "Tìm hiểu cách{ph0}phần mềm hoạt động." -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -6075,7 +6083,7 @@ msgstr "" #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -6083,13 +6091,13 @@ msgstr "ĐÃ BIẾT LẠI? {ph0}Chuyển đến hướng dẫn phân tích →{p #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "Bạn muốn đi sâu hơn? {ph0}Đọc Blog →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "Dán lời nhắc này vào trợ lý lập trình AI của bạn:" @@ -6102,38 +6110,38 @@ msgstr "Dán lời nhắc này vào trợ lý lập trình AI của bạn:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "Sao chép" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "Hoặc chạy lệnh này trong terminal:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "Xem và chấp thuận kế hoạch cài đặt, rồi khởi động lại trợ lý." -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "Kỹ thuật đảo ngược là gì?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6148,7 +6156,7 @@ msgstr "" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6160,7 +6168,7 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -6168,7 +6176,7 @@ msgstr "Trước khi dùng REA · Bạn {ph0}tự điều tra{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -6176,7 +6184,7 @@ msgstr "{ph0}01{ph1} Giải mã chi nhánh" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -6184,7 +6192,7 @@ msgstr "{ph0}02{ph1} Theo dõi cuộc gọi" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -6194,20 +6202,20 @@ msgstr "{ph0}03{ph1} Khôi phục quy tắc" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}Ban đầu x64 * lựa chọn hướng dẫn{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 * chi Nhánh Nào?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6217,29 +6225,29 @@ msgstr "" "“{ph0}0x5b? 0x5c?{ph1} Hai bước nhảy đến cùng một nơi. Những nhà khai thác " "này là gì?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "Tra Cứu id lệnh, sau đó gắn nhãn nhánh." -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "Chia ÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "Nhân ×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · Các hàm được gọi làm gì?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6249,24 +6257,24 @@ msgstr "" "\"100 là rõ ràng. Các cuộc gọi chỉ là địa chỉ. {ph0}Cái nào phân chia? Giá " "trị nào đi vào?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "Kiểm tra các chức năng trợ giúp và theo dõi các giá trị được lưu trữ." -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "Chia" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 * quy tắc Là gì?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6276,19 +6284,19 @@ msgstr "" "\"Con đường này nhân với đầu vào khác. Vậy {ph0}10% có nghĩa là 10% của " "200{ph1} sau +.”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "Đặt tên cho các toán hạng và kiểm tra cả hai đường dẫn toán tử." -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "Lý luận chuyên gia minh họa" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6300,20 +6308,20 @@ msgstr "" #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "Với REA · Bạn hỏi {ph0}trợ lý AI{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "Chỉ một lời nhắc." #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -6327,49 +6335,49 @@ msgstr "Hỏi trợ lý {ph0}bằng ngôn ngữ thông thường.{ph1}" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ví dụ nhắc · Máy tính" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "Câu trả lời ví dụ · dựa trên những phát hiện" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "Sau +, nút % mất {ph0}một tỷ lệ phần trăm của số đầu tiên.{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA cung cấp" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "Hướng dẫn của trình xử lý, mã dịch ngược và các cuộc gọi." -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "Trợ lý giải thích" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "Chi nhánh nào áp dụng, những gì nó tính toán và cách xây dựng lại nó." #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6381,7 +6389,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6391,37 +6399,37 @@ msgstr "" "{ph0}Hãy thử hai ví dụ.{ph1} Thay đổi tốc độ của trò chơi, sau đó quay lại " "Máy tính và xây dựng lại nút % của trò chơi." -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "Ví dụ 01 * Chrome ' s trò chơi khủng long" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "Vì sao khủng long chạy nhanh dần?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "Mục tiêu" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "Xây dựng lại trò chơi với {ph0}tốc độ điều chỉnh.{ph1}" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "Tại sao kỹ sư đảo ngược nó?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6432,49 +6440,49 @@ msgstr "" "chạy{ph1}: nó bắt đầu nhanh như thế nào, nó tăng bao nhiêu và khi nào nó " "dừng lại." -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "Chơi bản dựng lại" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "Chơi" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "Nhảy ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "Chơi lại" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "Tốc độ" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "Sử dụng quy tắc tăng tốc đã khôi phục" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "Quy tắc ban đầu: bắt đầu từ 6, sau đó tăng lên 13." -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "" "Di chuyển thanh trượt để thiết lập tốc độ của riêng bạn. Không gian Hoặc " "Nhảy xóa một cây xương rồng." -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" @@ -6483,14 +6491,14 @@ msgstr "" "Cho PHÉP JavaScript để chơi tái thiết. Mã và giải thích ở trên vẫn có thể " "đọc được." -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA trả về" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6508,7 +6516,7 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -6521,7 +6529,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6535,7 +6543,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -6549,7 +6557,7 @@ msgstr "" #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6559,12 +6567,12 @@ msgstr "" "{ph0}Bắt đầu từ 6.{ph1} Thêm {ph2}0.001{ph3} mỗi bản cập nhật mà không có va" " chạm, trong khi tốc độ thấp hơn {ph4}13{ph5}." -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "Mở phòng thí nghiệm tốc độ →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "Mỗi phần làm gì" @@ -6575,7 +6583,7 @@ msgstr "Mỗi phần làm gì" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6591,7 +6599,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6608,7 +6616,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6618,13 +6626,13 @@ msgstr "" "{ph0}03 * Bạn{ph1}{ph2}Thay đổi tốc độ và chơi{ph3}{ph4}Hãy thử tăng tốc ban" " đầu, sau đó chọn tốc độ của riêng bạn.{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "Xem kịch bản, kiểm tra và cách thử phân tích" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6634,7 +6642,7 @@ msgstr "" "REA đã kiểm tra PHIÊN bản TRÌNH duyệt HTTP thông qua kết nối gỡ lỗi cục bộ " "và trả về đã tải {ph0}, bao gồm cả nguồn và tiêu hóa của nó." -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -6648,7 +6656,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6664,7 +6672,7 @@ msgstr "" #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6682,7 +6690,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6690,19 +6698,19 @@ msgid "" msgstr "" "{ph0}Kiểm tra mã tốc độ{ph1} · {ph2} Tác GIẢ Chromium * giấy phép BSD{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "Ví dụ 02 * Windows Máy Tính" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "Dựng lại nút % của Máy tính." #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6711,7 +6719,7 @@ msgstr "Xây dựng một máy tính nhỏ xử lý {ph0}cả + và × chính x #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6721,29 +6729,29 @@ msgstr "" "Nút tương tự sử dụng {ph0}các quy tắc khác nhau sau + và ×.{ph1} Chúng tôi " "kiểm tra ứng dụng đã cài đặt để tìm số phần trăm được áp dụng." -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "Hãy thử tính toán" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "Đặt lại" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "10% của 200 = 20. Sau đó, 200 + 20 = 220." -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "Minh họa tương tác của quy tắc phần trăm được kiểm tra." #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6755,7 +6763,7 @@ msgstr "" #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6769,7 +6777,7 @@ msgstr "Đối với ví dụ này, {ph0} và {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6784,7 +6792,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6796,7 +6804,7 @@ msgstr "" "phục các quy tắc sau + và ×, sau đó xây dựng một máy tính nhỏ sử dụng cả " "hai.{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "Với +" @@ -6804,13 +6812,13 @@ msgstr "Với +" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}Lấy 10% số đầu tiên.{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "Với ×" @@ -6818,13 +6826,13 @@ msgstr "Với ×" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}Biến 10% thành 0,1.{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "Từ ứng dụng đã cài đặt đến nút % hoạt động" @@ -6836,7 +6844,7 @@ msgstr "Từ ứng dụng đã cài đặt đến nút % hoạt động" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6853,7 +6861,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6865,12 +6873,12 @@ msgstr "" "quy tắc{ph3}{ph4}Kiểm tra chéo nhánh với Nguồn Của Microsoft, sau đó thử + " "và × ở trên.{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "Xem mã thực và câu trả lời đã được kiểm tra như thế nào" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6891,7 +6899,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6901,17 +6909,17 @@ msgstr "" "{ph0}Thực hiện tỷ lệ phần trăm{ph1} · {ph2}Trường hợp thử nghiệm của " "Microsoft{ph3} · {ph4}Hướng dẫn thiết lập gốc{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "Cuộc điều tra đầu tiên của bạn" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "Hãy thử REA trên một ứng dụng nhỏ." -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " @@ -6920,12 +6928,12 @@ msgstr "" "Tải Xuống Ví Dụ Ghi Chú của chúng tôi, theo dõi XUẤT CSV của NÓ và kiểm tra " "một đầu vào đã thay đổi." -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "Hãy thử ví dụ hướng dẫn" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "Muốn tìm hiểu sâu hơn?" @@ -6934,7 +6942,7 @@ msgstr "Muốn tìm hiểu sâu hơn?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6954,13 +6962,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Ví dụ nhắc * Trang Web" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "Vâng, cái này." @@ -6973,7 +6981,7 @@ msgstr "Vâng, cái này." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6987,7 +6995,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7001,23 +7009,23 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}Xem nghiên cứu điển hình DX-Ball →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "Đối với các bước thiết lập và phân tích, hãy chọn mục tiêu của bạn:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "Chương trình mã máy" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" @@ -7026,17 +7034,17 @@ msgstr "" "Kiểm tra các hàm, chuỗi, tham chiếu và mối quan hệ gọi hàm trong tệp thực " "thi và thư viện." -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "Phân tích hướng dẫn chương trình mã máy" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript & Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " @@ -7045,17 +7053,17 @@ msgstr "" "Các mô-đun bản đồ, tuyến ĐƯỜNG, IPC và các phụ thuộc gốc từ thư mục ứng dụng" " hoặc KHO LƯU trữ ASAR." -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "Quy trình làm việc ứng dụng" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "Hoạt động trình duyệt và thời gian chạy" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " @@ -7064,12 +7072,12 @@ msgstr "" "Nắm bắt các trình duyệt được lựa chọn hoặc quá trình hoạt động, sau đó so " "sánh các kết quả trên chạy." -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "Hướng dẫn quan sát trình duyệt" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "Bạn có câu hỏi?" @@ -7080,7 +7088,7 @@ msgstr "Bạn có câu hỏi?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -7090,12 +7098,12 @@ msgstr "" "{ph0}Đọc CÂU hỏi THƯỜNG gặp{ph1}, {ph2}trò chuyện VỚI CHÚNG TÔI TRÊN Discord" " {ph3}, hoặc {ph4}mở sự cố GitHub{ph5} đối với lỗi và yêu cầu tính năng." -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "Tham gia cộng đồng" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -7118,27 +7126,27 @@ msgstr "" "Ứng dụng kỹ sư đảo ngược, nhị phân và hành vi trình duyệt với tác nhân mã " "hóa của bạn. Làm theo hướng dẫn rõ ràng và thử các ví dụ tương tác VỚI REA ." -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "Sao CHÉP lời nhắc cài ĐẶT REA" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "Sao chép lệnh thiết lập" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "Thực hiện theo phân tích máy tính thủ công" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "Sao chép câu hỏi tỷ lệ phần Trăm máy Tính" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " @@ -7147,37 +7155,37 @@ msgstr "" "Khủng long mini-game. Sử dụng Nút Nhảy hoặc Nhấn Không gian trong khi trò " "chơi được tập trung." -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "Sao chép dấu nhắc phân tích khủng long" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "Chọn tính toán" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "Sao chép lời nhắc phân tích máy tính" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "Sao chép lời nhắc dự án trang web" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "Sao chép lời nhắc tái thiết trò chơi" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -7186,25 +7194,25 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}Nhà{ph1} / {ph2}Giới thiệu{ph3} / Android" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "Nghiên cứu trường hợp * Aegis Authenticator" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "Làm thế nào để một authenticator{ph0}tạo mã đăng nhập?" -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " @@ -7214,17 +7222,17 @@ msgstr "" " Trong ANDROID APK , sau đó xây dựng lại nó bằng đồng hồ bạn có thể điều " "khiển." -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 * Android * PHÁT HÀNH CHÍNH THỨC APK * 6.9 MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "Xem Aegis TRÊN GitHub" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "TỪ APK đến mã bạn có thể sao chép" @@ -7235,7 +7243,7 @@ msgstr "TỪ APK đến mã bạn có thể sao chép" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7253,7 +7261,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7271,7 +7279,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7283,14 +7291,14 @@ msgstr "" "mã.{ph3}{ph4}Một bản demo trình duyệt mới tái tạo quy tắc và kiểm tra nó đối" " với các trường hợp tham chiếu công khai.{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "Trong trường hợp này nghiên cứu" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -7298,7 +7306,7 @@ msgstr "{ph0}Hỏi agent của bạn{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -7306,7 +7314,7 @@ msgstr "{ph0}Hãy thử trình tạo mã{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -7314,7 +7322,7 @@ msgstr "{ph0}Tìm mã VỚI REA {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -7322,7 +7330,7 @@ msgstr "{ph0}Đọc tính toán{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -7330,20 +7338,20 @@ msgstr "{ph0}Kiểm tra việc tái thiết{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}Tự kiểm tra APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "Hỏi agent của bạn" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7361,21 +7369,21 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "Sao chép" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7386,14 +7394,14 @@ msgstr "" " định cấu hình. {ph0}Nhận APK và thiết lập phân tích nhúng vào trang web " "hoặc blog của bạn ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "Hãy thử trình tạo mã" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7404,33 +7412,33 @@ msgstr "" "Các nhóm ứng dụng thời gian vào {ph0}Khối 30 giây.{ph1} Nó kết hợp số khối " "với khóa tài khoản để tạo mã. Cùng một khóa và khối tạo ra cùng một mã." -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "Di chuyển đồng hồ qua 60 giây" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "Thời gian" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "giây" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "Đồng hồ ví dụ có thể điều chỉnh của chúng tôi" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "Khối 30 giây" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "Khối" @@ -7439,35 +7447,35 @@ msgstr "Khối" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59 giây{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "Mã được tạo" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "Khóa tài khoản + khối → sáu chữ số" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "Thời gian ví dụ, tính bằng giây" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59 giây" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60 giây" @@ -7476,7 +7484,7 @@ msgstr "60 giây" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7488,7 +7496,7 @@ msgstr "" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7498,25 +7506,25 @@ msgstr "" "Chìa khóa là cố định, công khai {ph0}Dữ liệu thử NGHIỆM rfc 6238{ph1}. Bản " "demo thực hiện tính toán được khôi phục từ APK ." -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " "clock." msgstr "Sơ đồ hiển thị kết quả ở 59 giây. Bật JavaScript để thay đổi đồng hồ." -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "Tìm mã VỚI REA" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "Thu HẸP APK đến ba lớp" #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7527,14 +7535,14 @@ msgstr "" "trình và tài khoản nhập khẩu. TOTP có nghĩa là mật khẩu một lần dựa trên " "thời gian." -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "Kết nối máy phát điện với màn hình của ứng dụng" #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7545,7 +7553,7 @@ msgstr "" "Kiểm tra {ph0} sau đó hiển thị cuộc gọi hiển thị {ph1}." #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7555,14 +7563,14 @@ msgstr "" "Yêu cầu hiển thị một đường dẫn đầu vào rút gọn. Tên lớp kết quả bỏ qua điểm " "chung {ph0} tiền tố." -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "Đọc tính toán" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7576,7 +7584,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -7584,7 +7592,7 @@ msgstr "{ph0}01{ph1} Khối thời gian" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -7592,7 +7600,7 @@ msgstr "{ph0}02{ph1} Phím + khối" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -7600,7 +7608,7 @@ msgstr "{ph0}03{ph1} Sáu chữ số" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7612,7 +7620,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7625,7 +7633,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7639,7 +7647,7 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7650,7 +7658,7 @@ msgstr "" "Bảng điều khiển bên phải là một bản tóm tắt giải thích. {ph0} MÃ Aegis LÀ " "GPL-3.0.{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "Bên trong máy phát điện" @@ -7659,7 +7667,7 @@ msgstr "Bên trong máy phát điện" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7669,7 +7677,7 @@ msgstr "" "APK phát hành đặt {ph0} trong {ph1}. REA thực hiện cuộc gọi từ {ph2} và trả" " về cơ thể này; nguồn gốc gọi người trợ giúp {ph3}." -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -7685,20 +7693,20 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}So sánh với nguồn phát hành phù hợp{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "Kiểm tra việc tái thiết" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7711,29 +7719,29 @@ msgstr "" " trên {ph0}133 trường hợp thử nghiệm{ph1}, bao gồm ranh giới khối thời gian " "và mã bắt đầu bằng không." -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "Thời gian ví dụ" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "Mã sáu chữ số" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30 giây" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109 giây" #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7743,17 +7751,17 @@ msgstr "" "Trình tạo cũng khớp với sáu trường hợp tham chiếu SHA-1 đã xuất bản trong " "{ph0}RFC 6238{ph1}. Kiểm tra việc triển khai trình duyệt chống lại chúng:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "Chạy kiểm tra tham chiếu" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "Đọc tính toán của bản demo" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" @@ -7762,7 +7770,7 @@ msgstr "" "Các trường hợp tham chiếu sử dụng tám chữ số. Kiểm tra cũng xác minh kết quả" " sáu chữ số của họ." -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " @@ -7771,14 +7779,14 @@ msgstr "" "Xác minh chạy các phương thức Java được trích xuất và bản demo mới. Android " "APK đã được kiểm tra tĩnh." -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "Tự kiểm tra APK" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7790,7 +7798,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7800,18 +7808,18 @@ msgstr "" "Phân tích Android cần MỘT jdk 17 đầy đủ hoặc mới hơn. Chọn nó với {ph0} hoặc" " {ph1}. Trường hợp này sử DỤNG JDK 21." -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "Điểm REA tại tệp nhà cung cấp và kiểm TRA APK :" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS / Linux" #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7824,7 +7832,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7834,7 +7842,7 @@ msgstr "" "Một câu hỏi tiếp theo: {ph0}điều gì xảy ra khi một tài khoản sử dụng tám chữ" " số hoặc một khoảng thời gian khác nhau?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "Nguồn" @@ -7850,7 +7858,7 @@ msgstr "Nguồn" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7864,14 +7872,14 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "" "{ph0}Rfc 6238 trường hợp tham khảo{ph1} · {ph2}Dữ liệu thử nghiệm Demo{ph3}" -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7896,37 +7904,37 @@ msgstr "" "Kiểm tra Aegis ANDROID APK VỚI REA , khôi phục tính toán mã đăng nhập gồm " "sáu chữ số của NÓ và thử tái tạo với đồng hồ có thể điều chỉnh." -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK trường hợp nghiên cứu" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "Sao CHÉP DẤU nhắc VÍ DỤ Aegis" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "Thực hiện theo tính toán mã đăng nhập" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "Sao CHÉP lệnh kiểm TRA APK" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -7935,26 +7943,26 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}Nhà{ph1} / {ph2}Giới thiệu{ph3} / CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "Nghiên cứu điển hình * DownUnderCTF 2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "Tìm cờ trong{ph0}MỘT NHỊ phân CTF." #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7964,17 +7972,17 @@ msgstr "" "SỬ DỤNG REA để kiểm tra một trình kiểm tra cờ nhỏ, biến các quy tắc của nó " "thành các phương trình và tìm một đầu vào làm cho chương trình gốc in {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "mặt nạ hình vuông cờ checker * Dễ dàng * Linux x86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "Xem thử thách ban đầu" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "Từ nhị phân đến câu trả lời đã kiểm tra" @@ -7985,7 +7993,7 @@ msgstr "Từ nhị phân đến câu trả lời đã kiểm tra" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8002,7 +8010,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8020,7 +8028,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8032,7 +8040,7 @@ msgstr "" "bản Python giải quyết các phương trình. REA chụp chương trình ban đầu chấp " "nhận kết quả.{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." @@ -8040,14 +8048,14 @@ msgstr "" "Thử thách là của joseph, được xuất bản trong Kho lưu trữ chính thức Của " "DownUnderCTF." -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "Trong trường hợp này nghiên cứu" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -8055,7 +8063,7 @@ msgstr "{ph0}Tìm mã kiểm tra{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -8063,7 +8071,7 @@ msgstr "{ph0}Đọc một mặt nạ{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -8071,7 +8079,7 @@ msgstr "{ph0}Lắp ráp để mã có thể đọc được{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -8079,7 +8087,7 @@ msgstr "{ph0}Giải các phương trình{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -8087,20 +8095,20 @@ msgstr "{ph0}Kiểm tra câu trả lời{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}Hãy thử nó cho mình{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "Tìm mã kiểm tra" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8118,17 +8126,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "Sao chép" @@ -8139,7 +8147,7 @@ msgstr "Sao chép" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8151,7 +8159,7 @@ msgstr "" "thích cách kiểm tra hoạt động, sau đó xác minh câu trả lời với chương trình " "gốc.{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " @@ -8160,12 +8168,12 @@ msgstr "" "Một lời nhắc ví dụ, với thử thách đã tải xuống có sẵn tại địa phương và phân" " tích nhà cung cấp chương trình mã máy được kết nối." -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "Thực hiện theo lời nhắc đầu vào cho chức năng của nó" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " @@ -8174,14 +8182,14 @@ msgstr "" "Tham chiếu cung cấp cho tác nhân một nơi để điều tra, mặc dù tên hàm ban đầu" " của tệp thực thi đã bị xóa." -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "Đọc trình kiểm tra và hai người trợ giúp của nó" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8193,7 +8201,7 @@ msgstr "" "hợp các mã đã chọn và so sánh kết quả với một số được lưu trữ. Của nó {ph0}-" " byte bước qua {ph1} byte cho 26 mặt nạ." -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " @@ -8203,12 +8211,12 @@ msgstr "" "cục bộ được rút ngắn để hiển thị; địa chỉ tham khảo HÌNH ẢNH ĐÃ nhập CỦA " "REA." -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "Một kiểm tra cho thấy một nhân vật" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -8221,13 +8229,13 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "Kiểm tra thứ bảy chỉ chọn một vị trí. {ph0}Hình mở{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "Đọc mặt nạ và mục tiêu của nó từ nhị phân" @@ -8236,7 +8244,7 @@ msgstr "Đọc mặt nạ và mục tiêu của nó từ nhị phân" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8249,12 +8257,12 @@ msgstr "" "với nhau, các byte này cho agent biết rằng {ph2}, vì vậy nhân vật đó là " "{ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "Từ hướng dẫn đến kiểm tra có thể đọc được" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -8265,7 +8273,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -8273,7 +8281,7 @@ msgstr "{ph0}01{ph1} Bắt đầu" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -8281,7 +8289,7 @@ msgstr "{ph0}02{ph1} Chọn" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -8289,7 +8297,7 @@ msgstr "{ph0}03{ph1} Thêm" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -8297,18 +8305,18 @@ msgstr "{ph0}04{ph1} Tiến lên" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} So sánh" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA * hướng dẫn ban đầu được chọn" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "Có Thể đọc Được C * tóm tắt một lần kiểm tra" @@ -8316,7 +8324,7 @@ msgstr "Có Thể đọc Được C * tóm tắt một lần kiểm tra" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -8324,7 +8332,7 @@ msgstr "{ph0}01 * Bắt đầu từ số không · {ph1} {ph2} giữ số tiền #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8336,7 +8344,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8348,7 +8356,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8362,7 +8370,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8372,7 +8380,7 @@ msgstr "" "{ph0}05 * So sánh với mục tiêu được lưu trữ.{ph1} Người gọi nhận được số " "tiền trong {ph2}. Một sự không phù hợp nhảy đến {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " @@ -8381,12 +8389,12 @@ msgstr "" "Các hướng dẫn đến từ người trợ giúp tổng hợp và hàm gọi của nó. C Là một bản" " tóm tắt giải thích với tên mô tả và một vòng lặp 36 ô phẳng." -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "Giải 26 phương trình" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -8397,13 +8405,13 @@ msgstr "" "và yêu cầu tổng cộng 1441. Các lựa chọn chồng chéo cung cấp các phương trình" " mà một tập Lệnh Python nhỏ có thể giải quyết cùng nhau." -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python * giải đoạn trích" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8417,19 +8425,19 @@ msgstr "" "cái, chữ số, dấu gạch dưới và dấu ngoặc nhọn. Quá trình tải xuống hoàn chỉnh" " bao gồm tất cả 26 mặt nạ và mục tiêu." -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "Tải xuống trình giải hoàn chỉnh" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "Kiểm tra câu trả lời với chương trình gốc" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8441,47 +8449,47 @@ msgstr "" " Thay đổi một ký tự đã chọn từ {ph0} để {ph1} tạo tổng đầu tiên 1440 thay vì" " 1441 và chương trình từ chối nó." -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "Đầu vào" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "Đầu ra quan sát" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "Mã thoát" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "Cờ của người giải" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "Một nhân vật đã thay đổi" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "Hiển thị cờ đã khôi phục và đầu ra đã chụp" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA * đầu ra chương trình gốc" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "Sao chép cờ" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " @@ -8490,12 +8498,12 @@ msgstr "" "Giá trị được khôi phục cũng khớp với cờ trong siêu dữ liệu thử thách đã xuất" " bản của ban tổ chức, được kiểm tra sau khi giải nhị phân." -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "Nguồn, danh tính mục tiêu và chi tiết phân tích" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -8506,7 +8514,7 @@ msgstr "" "REA 4.1.0 với Ghidra 12.1.4 TRÊN Linux x64. Nhị phân là MỘT ELF x86-64 bị " "tước, 15.248 byte." -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -8529,7 +8537,7 @@ msgstr "" #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8539,12 +8547,12 @@ msgstr "" "{ph0}So sánh với nguồn của ban tổ chức{ph1} · {ph2}Thách thức siêu dữ liệu " "và cờ{ph3} · {ph4} REA ghi chú bằng chứng{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "Hãy thử nó cho mình" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " @@ -8553,13 +8561,13 @@ msgstr "" "Tải xuống thử thách ban đầu và người giải quyết vào một thư mục. Sử dụng lời" " nhắc ở trên để điều tra với agent của bạn hoặc chạy tập lệnh đi kèm." -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "Thiết bị đầu cuối * giải quyết và chạy" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -8571,7 +8579,7 @@ msgstr "" "quyết Nhu cầu Python và {ph0}. Chạy các nhu CẦU thực thi BAN ĐẦU Linux " "x86-64." -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "Thiết LẬP REA với agent mã hóa của bạn" @@ -8592,27 +8600,27 @@ msgstr "" "các chức năng kiểm tra, trích xuất mặt nạ và so sánh cờ đã khôi phục với " "chương trình gốc." -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTF cờ - kiểm tra trường hợp nghiên cứu" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "Sao CHÉP dấu nhắc VÍ DỤ CTF" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "PHƯƠNG trình mặt NẠ CTF; cuộn theo chiều ngang trên màn hình nhỏ hơn" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -8623,42 +8631,42 @@ msgstr "" "đó đóng góp vào tổng. Mã ký tự bắt buộc của nó là 55, có nghĩa là ký tự là " "7." -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "Thực hiện theo kiểm TRA CTF" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "Sao chép ctf hội" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "Sao chép KIỂM tra CTF có thể đọc được" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "Sao CHÉP CTF giải đoạn trích" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "Sao chép cờ phục hồi" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "Sao CHÉP LỆNH CTF solver" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -8667,25 +8675,25 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}Nhà{ph1} / {ph2}Giới thiệu{ph3} / DX-Ball" -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "Nghiên cứu trường hợp * DX-Ball 1.07" #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "XÂY DỰNG LẠI DX-Ball {ph0}từ thực thi của nó." -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" @@ -8694,14 +8702,14 @@ msgstr "" "Mục tiêu là một phiên bản C có thể bảo trì của TRÒ chơi Windows NĂM 1996. " "REA giúp các agent kiểm tra bản gốc, một chức năng tại một thời điểm." -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 * C * REA" #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8713,14 +8721,14 @@ msgstr "" "gọi và dữ liệu đọc; dự án tái thiết thực hiện và kiểm tra kết quả. {ph0}Hình" " mở{ph1}" -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "Trong trường hợp này nghiên cứu" #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -8728,7 +8736,7 @@ msgstr "{ph0}Dự án{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -8736,7 +8744,7 @@ msgstr "{ph0}Âm thanh pan{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -8744,23 +8752,23 @@ msgstr "{ph0}Kiểm tra kết quả{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}Tiếp tục công việc{ph1}" -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "duy Trì Chức Năng C" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "so sánh với mã gốc" -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "các hàm với các byte được biên dịch phù hợp" @@ -8771,7 +8779,7 @@ msgstr "các hàm với các byte được biên dịch phù hợp" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8781,12 +8789,12 @@ msgstr "" "Trạm kiểm soát dự án: 7 tháng 10 năm 2026. {ph0}Sổ cái tiến độ{ph1} · " "{ph2}Bảo hiểm kiểm tra{ph3}" -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "Dự án cho đến nay" -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -8801,12 +8809,12 @@ msgstr "" "chơi được tiếp tục với vật lý bóng và mái chèo, xử lý tăng sức mạnh và TÍCH " "hợp Windows." -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "Tìm tính toán vị trí âm thanh trái/phải" -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8825,17 +8833,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "Sao chép" @@ -8846,7 +8854,7 @@ msgstr "Sao chép" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8856,7 +8864,7 @@ msgstr "" "{ph0}›{ph1}{ph2}SỬ dụng REA để tìm CÁCH DX-Ball tính toán định vị âm thanh " "nổi. Giải thích tính toán và hiển thị mã.{ph3}{ph4}{ph5}" -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8867,7 +8875,7 @@ msgstr "" "sẵn. Cuộc điều tra dưới đây cho THẤY CÁC truy vấn REA và bằng chứng đằng sau" " câu trả lời." -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8881,7 +8889,7 @@ msgstr "" #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8895,12 +8903,12 @@ msgstr "" " động dấu phẩy động. Sự khác biệt đó đã cho agent một lý do cụ thể để tiếp " "tục điều tra." -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "Chế độ xem dịch ngược đầu tiên" -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8909,18 +8917,18 @@ msgstr "" "Đầu ra hiển thị một cuộc gọi chuyển đổi. Đọc các hướng dẫn dưới đây cho thấy" " đầu vào và tính toán cho ăn cuộc gọi đó." -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "Ba câu HỎI được trả lời THÔNG QUA REA" -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "Khôi phục đầu vào bị thiếu" #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8930,14 +8938,14 @@ msgstr "" "Kết quả chức năng bao gồm các hướng dẫn cùng với mã giả và hàm gọi. Đây, " "{ph0} hiển thị đầu vào số nguyên bị thiếu từ chế độ xem trình dịch ngược." -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "Theo dõi hàm gọi để hiểu đầu vào" #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8947,12 +8955,12 @@ msgstr "" "REA đã xác định hàm gọi này trong kết quả đầu tiên. Quy mô hướng dẫn trước " "của nó {ph0} bằng 30; thêm 20 cho tọa độ màn hình của gạch, {ph1}." -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "Đọc các giá trị đằng sau địa chỉ bộ nhớ" -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " @@ -8961,12 +8969,12 @@ msgstr "" "Các byte được trả về thiết lập hai hằng số học và thang đo pan ban đầu. Tác " "nhân bây giờ có các giá trị cần thiết cho biểu Thức C." -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "TỪ NHỮNG phát Hiện CỦA REA Đến C" -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8977,7 +8985,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8985,7 +8993,7 @@ msgstr "{ph0}01{ph1} Đầu vào" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8993,7 +9001,7 @@ msgstr "{ph0}02{ph1} Nhân" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -9001,7 +9009,7 @@ msgstr "{ph0}03{ph1} Trừ" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -9009,18 +9017,18 @@ msgstr "{ph0}04{ph1} Quy mô" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} Quay trở lại" -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "Bản gốc x86 * trích đoạn" -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "Tái Tạo C" @@ -9030,7 +9038,7 @@ msgstr "Tái Tạo C" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9049,7 +9057,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9065,7 +9073,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9082,7 +9090,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9099,7 +9107,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9111,7 +9119,7 @@ msgstr "" "định TRONG REA 's callee kết quả. C đúc kết quả để {ph4}; so sánh " "original-x86 kiểm tra giá trị trả về." -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -9122,23 +9130,23 @@ msgstr "" "đầy đủ dưới đây cũng bao gồm các cửa hàng can thiệp và thiết lập chức năng " "và dọn dẹp." -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "Lắp ráp đầy đủ và bằng chứng hỗ trợ" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA kết quả · 0x406400-0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "Những gì hàm gọi cung cấp" #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9148,54 +9156,54 @@ msgstr "" "Chức năng gạch-hit tại {ph0} cân tọa độ gạch của nó thêm 30, thêm 20, sau đó" " đẩy nó trước cuộc gọi:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "Những gì dữ liệu đọc thiết lập" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA byte đọc, giải mã như đôi endian ít" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "Địa chỉ" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "Giá trị" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "Được sử dụng cho" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "Phép nhân đầu tiên" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "Phép trừ" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} ban đầu" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "Quy mô chảo được lưu trữ" -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -9211,7 +9219,7 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9221,12 +9229,12 @@ msgstr "" "{ph0}Nguồn duy trì{ph1} · {ph2}Ghi chú điều tra và tài liệu tham khảo bằng " "chứng{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "Kiểm tra chức năng phục hồi" -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -9235,12 +9243,12 @@ msgstr "" "Hàm được khôi phục vượt qua hai lần kiểm tra: các giá trị trả về của nó khớp" " với bản gốc và các byte được biên dịch của nó khớp với tệp thực thi." -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3.205 trường hợp hành vi" -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -9251,12 +9259,12 @@ msgstr "" " c. Chúng bao phủ mọi vị trí nguyên từ 0 đến 640 ở năm thang pan: 0, 0,5, 1," " 20 và -1." -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 byte phù hợp" -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -9267,7 +9275,7 @@ msgstr "" "dịch khớp với chức năng hoàn chỉnh sau khi áp dụng các lần di dời đã xem xét" " và kiểm tra các hằng số được tham chiếu." -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -9282,18 +9290,18 @@ msgstr "" #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}Đọc chi tiết phát lại trình biên dịch{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "Tiếp tục điều tra" -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -9304,7 +9312,7 @@ msgstr "" " tiền thưởng: kiểm tra các chức năng có liên quan, khôi phục trạng thái và " "phụ thuộc của chúng, sau đó so sánh việc triển khai với bản gốc." -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " @@ -9313,7 +9321,7 @@ msgstr "" "Để tự kiểm tra chức năng sound-pan, hãy làm theo HƯỚNG dẫn thiết lập CỦA DỰ " "án DX-Ball và cung cấp mục tiêu ban đầu phù hợp. Sau đó chạy:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "TRONG thanh TOÁN DX-Ball" @@ -9322,7 +9330,7 @@ msgstr "TRONG thanh TOÁN DX-Ball" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9336,7 +9344,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9352,7 +9360,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -9377,14 +9385,14 @@ msgstr "" "duy trì Các bài kiểm tra C, original-x86 và các byte hàm được biên dịch phù " "hợp." -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "" "DX-Ball sound-pan điều tra; di chuyển theo chiều ngang trên màn hình nhỏ hơn" -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -9399,70 +9407,70 @@ msgstr "" "tra độc lập so với x86 ban đầu trong 3.205 trường hợp và bằng cách phát lại " "trình biên dịch vc4.0 khớp với 63 byte." -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "Nghiên cứu trường HỢP tái THIẾT DX-Ball" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "Sao chép ví dụ dấu nhắc" -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "Thực hiện theo các tính toán của trái/phải vị trí âm thanh" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "Sao chép đoạn trích lắp ráp ban đầu" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "Sao chép chức năng sound-pan" -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "Sao chép hoàn chỉnh âm thanh-pan lắp ráp" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "Sao CHÉP lệnh PHÂN tích DX-Ball" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}Nhà{ph1} / Trưng bày" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA nghiên cứu trường hợp." -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" @@ -9471,17 +9479,17 @@ msgstr "" "Android, trò chơi, Electron và MỘT THÁCH thức CTF, với mã, số liệu và kết " "quả kiểm tra." -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android * PHÂN tích APK" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "Cách trình xác thực tạo mã đăng nhập" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -9492,22 +9500,22 @@ msgstr "" "phương thức tạo BẰNG REA , sau đó di chuyển đồng hồ demo để xem lý do tại " "sao mã thay đổi sau mỗi 30 giây." -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "Đọc nghiên Cứu điển Hình Android" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF * Phân tích các chương trình mã máy" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "Giải QUYẾT MỘT TRÌNH kiểm tra cờ CTF" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -9518,22 +9526,22 @@ msgstr "" "của nó, biến mặt nạ và tổng thành phương trình, sau đó xác minh cờ đã giải " "với chương trình gốc." -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "Đọc nghiên CỨU trường hợp CTF" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "Bản Địa · Tái Thiết" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball ' s tính toán vị trí âm thanh trái/phải" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -9544,22 +9552,22 @@ msgstr "" " REA ' s hướng dẫn, tham chiếu hàm gọi và hằng số dẫn đến một hàm c nhỏ, " "được kiểm tra đối với hành vi ban đầu và tất cả 63 byte được biên dịch." -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "Đọc nghiên CỨU điển HÌNH DX-Ball" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron * Tính năng truy tìm" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Notion sao chép văn bản và HTML như thế nào" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -9571,22 +9579,22 @@ msgstr "" " xem cách một điểm đánh dấu HTML nhỏ giữ dữ liệu khối phong phú được kết nối" " với một bản sao." -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "Đọc nghiên CỨU điển HÌNH Notion" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS * Tái thiết" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "TH04 nhắm vào một viên đạn như thế nào" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -9597,17 +9605,17 @@ msgstr "" "nhân, chia và phối hợp của nó với C++ có thể đọc được, sau đó xem cách chúng" " tạo ra một vòng nhắm vào người chơi." -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "Đọc nghiên CỨU điển HÌNH TH04" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "Hướng dẫn từng bước" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " @@ -9616,7 +9624,7 @@ msgstr "" "Các hướng dẫn đi qua tính toán gốc, xuất Electron và yêu cầu trình duyệt. " "Mỗi bắt đầu với một dấu nhắc và một mục tiêu cụ thể." -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "Đọc hướng dẫn" @@ -9635,12 +9643,12 @@ msgstr "" "Theo DÕI CÁC cuộc điều tra REA thông qua mã, số liệu và bản demo: Trình xác " "thực Android, DX-Ball , Notion , TH04 và Trình kiểm tra cờ DownUnderCTF." -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -9649,25 +9657,25 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}Nhà{ph1} / {ph2}Giới thiệu{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "Nghiên cứu trường hợp * Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "Notion sao CHÉP như THẾ NÀO{ph0}văn bản VÀ HTML." -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " @@ -9676,12 +9684,12 @@ msgstr "" "Theo dõi cuộc gọi clipboard TỪ API trang CỦA Notion, thông qua quá trình tải" " trước và quy trình chính, ĐẾN TRÌNH ghi clipboard CỦA Electron." -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion Máy tính để bàn 7.6.1 * JavaScript * REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Cây cầu BÊN TRONG GÓI máy TÍNH ĐỂ BÀN CỦA Notion" @@ -9693,7 +9701,7 @@ msgstr "Cây cầu BÊN TRONG GÓI máy TÍNH ĐỂ BÀN CỦA Notion" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9710,7 +9718,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9727,7 +9735,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9744,7 +9752,7 @@ msgstr "" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9755,13 +9763,13 @@ msgstr "" "bản và HTML được cung cấp.{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "Một kênh nối hai bên: {ph0}" -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " @@ -9771,14 +9779,14 @@ msgstr "" "quyết các trình bao bọc cho thấy CÁC cuộc gọi Electron đằng sau những tên " "đó." -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "Trong trường hợp này nghiên cứu" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -9786,7 +9794,7 @@ msgstr "{ph0}Theo cầu clipboard{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -9794,19 +9802,19 @@ msgstr "{ph0}Giữ cấu trúc của một khối{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}Thêm ví dụ và nguồn{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "Thao tác sao chép đi đâu?" #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9826,17 +9834,17 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "Sao chép" @@ -9847,7 +9855,7 @@ msgstr "Sao chép" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9857,7 +9865,7 @@ msgstr "" "{ph0}›{ph1}{ph2}SỬ DỤNG REA để theo dõi CÁCH Notion sao chép văn bản và HTML" " vào bảng tạm hệ thống. Hiển thị mã ở mỗi bước.{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " @@ -9866,12 +9874,12 @@ msgstr "" "Một lời nhắc ví dụ VỚI GÓI ứng dụng CỤC BỘ CỦA Notion có sẵn cho agent mã " "hóa của bạn." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA tìm nơi bắt đầu đọc" -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9882,13 +9890,13 @@ msgstr "" "gửi yêu cầu IPC. Cả hai phát hiện đều đi kèm với phạm vi nguồn trong gói thu" " nhỏ:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA phát hiện → hai nơi để mở" #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9902,7 +9910,7 @@ msgstr "" #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9916,12 +9924,12 @@ msgstr "" "cấp cho tác nhân một cái gì đó chính xác để tìm kiếm trong gói chính. Bốn " "đoạn trích dưới đây cho thấy tuyến đường mà nó kết nối." -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "Bốn đoạn mã ngắn" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " @@ -9930,13 +9938,13 @@ msgstr "" "Đơn giản hóa TỪ JavaScript đóng gói , với tên biến có thể đọc được. Các " "thành viên không liên quan bị bỏ qua." -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "Bắt đầu TẠI API tiếp xúc với trang" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9946,13 +9954,13 @@ msgstr "" "Thành viên này cung cấp tên kênh. Việc thực hiện {ph0} cho chúng tôi biết " "cách yêu cầu rời khỏi quy trình của trang." -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "Giải quyết trình bao bọc tải trước" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9962,14 +9970,14 @@ msgstr "" "Hàm trả về chuyển tiếp các đối số thông qua IPC YÊU cầu và phản hồi CỦA " "Electron. Bây giờ chúng ta có thể tìm kiếm {ph0} về phía chính-quá trình." -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "Kiểm tra cách người nhận được đăng ký" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9979,12 +9987,12 @@ msgstr "" "Quá trình chính sử dụng một trình bao bọc khác. Của nó {ph0} phương pháp " "đăng ký một {ph1} người nhận cho kênh đó." -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "Tìm ghi và kiểm tra người gửi của nó" -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9995,13 +10003,13 @@ msgstr "" " cung cấp cho API clipboard CỦA Electron. Kênh và hai trình bao bọc được " "giải quyết kết nối phương thức tiếp xúc với cuộc gọi này." -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "Làm thế nào để một khối được sao chép giữ cấu trúc của nó?" #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10011,27 +10019,27 @@ msgstr "" "Notion ' s web editor gửi văn bản VÀ HTML thông qua {ph0}. Nó giữ dữ liệu " "khối cục bộ và ĐẶT ID vào HTML đã sao chép để kết nối chúng." -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "LIÊN KẾT HTML để lưu dữ liệu khối" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "Đọc ID HTML" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "Tìm CÙNG MỘT ID cục BỘ" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "Khôi phục DỮ LIỆU KHỐI Notion" -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " @@ -10040,7 +10048,7 @@ msgstr "" "Văn BẢN minh họa VÀ ID. Kiểm tra mô-đun được ghi sẽ khôi phục dữ liệu khối " "khi id khớp; một mục cũ chỉ trả về văn bản và HTML." -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." @@ -10049,24 +10057,24 @@ msgstr "" "Khi dán, Notion tìm ID HTML và kiểm tra NÓ với bản sao đã lưu. Id phù hợp " "khôi phục dữ liệu khối." -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "" "Định dạng Clipboard được ghi lại từ tài sản web được lưu trong bộ nhớ cache " "vào ngày 13 tháng 7 năm 2026." -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "Thêm ví dụ và nguồn" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "Một ví dụ khác: Bảng Markdown" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " @@ -10075,12 +10083,12 @@ msgstr "" "Notion phân Tích Markdown thành dữ liệu khối. Ví dụ này cho thấy cách một " "bảng trở thành tiêu đề và các hàng dữ liệu." -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "Một bảng thông QUA TRÌNH phân tích Cú pháp Markdown CỦA Notion" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " @@ -10089,13 +10097,13 @@ msgstr "" "Ghi lại đầu ra từ Một Trình phân tích Cú pháp Markdown trích xuất. Bảng trở " "thành hàng và ô." -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "Một đường dẫn khác: kết nối sqlite ngoại tuyến" #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10108,7 +10116,7 @@ msgstr "" "kênh tin nhắn và cung cấp một cổng cho trình kết xuất và cổng kia cho quy " "trình tiện ích SQLite. Các lô tuyên bố tiếp theo và kết quả đi qua cổng đó." -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " @@ -10117,7 +10125,7 @@ msgstr "" "Sau đó, handoff giải thích nơi công việc cơ sở dữ liệu chạy và tại sao chỉ " "truy tìm yêu cầu IPC ban đầu bỏ lỡ cuộc trò chuyện sau này." -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "Nguồn và cách đọc các đoạn trích" @@ -10125,7 +10133,7 @@ msgstr "Nguồn và cách đọc các đoạn trích" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10143,7 +10151,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10159,7 +10167,7 @@ msgstr "" "thi các mô-đun được trích xuất và các dây nịt nhỏ; đầu ra của chúng mô tả " "các đầu dò đó thay vì một phiên GIAO diện người dùng máy tính để bàn bị bắt." -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -10173,7 +10181,7 @@ msgstr "" " các triển khai trình bao bọc của chúng trong gói." #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10191,7 +10199,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10205,7 +10213,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -10231,52 +10239,52 @@ msgstr "" "wrappers và quy trình chính, với đoạn trích mã ngắn và xem xét định dạng " "clipboard phong phú của NÓ." -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron trường hợp nghiên cứu" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "Sao CHÉP DẤU NHẮC PHÂN TÍCH Notion" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "Sao CHÉP Notion tải trước đoạn trích" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "Sao CHÉP Notion gọi wrapper đoạn trích" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "Sao CHÉP Notion handler wrapper đoạn trích" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "Sao CHÉP Notion clipboard receiver đoạn trích" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "Khôi phục dữ liệu clipboard phong phú trên dán" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "Về đầu trang" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "Bỏ qua nội dung" @@ -10285,25 +10293,25 @@ msgstr "Bỏ qua nội dung" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}Nhà{ph1} / {ph2}Giới thiệu{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "Nghiên cứu điển hình * Touhou 4: Lotus Land Story" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "XÂY DỰNG LẠI TH04 ' s{ph0}mẫu đạn." -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " @@ -10313,17 +10321,17 @@ msgstr "" "chức năng dos ban đầu, sau đó làm theo hướng dẫn của NÓ vào C++có thể đọc " "được." -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98 * 16-bit DOS * c++ và lắp ráp" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "Xem TÁI THIẾT TH04" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "Từ hướng dẫn ban đầu để kiểm tra nguồn" @@ -10334,7 +10342,7 @@ msgstr "Từ hướng dẫn ban đầu để kiểm tra nguồn" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10350,7 +10358,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10368,7 +10376,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10384,7 +10392,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10395,7 +10403,7 @@ msgstr "" "{ph0}04 * Kiểm tra nguồn{ph1}{ph2}2,139 byte phù hợp{ph3}{ph4}Kiểm tra trình" " biên dịch đã ghi bao gồm mã tạo đạn có chứa trình trợ giúp này.{ph5}" -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " @@ -10404,14 +10412,14 @@ msgstr "" "REA trả về mã gốc và bằng chứng phân tích của nó. DỰ án TH04 cung cấp các " "kiểm tra nguồn và trình biên dịch được duy trì." -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "Trong trường hợp này nghiên cứu" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -10419,7 +10427,7 @@ msgstr "{ph0}Vòng đạn{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -10427,7 +10435,7 @@ msgstr "{ph0}REA trả về gì{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -10435,7 +10443,7 @@ msgstr "{ph0}Lắp Ráp Để C C{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -10443,18 +10451,18 @@ msgstr "{ph0}Kiểm tra nguồn{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}Dự án đầy đủ{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "Làm thế nào một chiếc nhẫn nhắm vào người chơi" -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -10473,16 +10481,16 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Agent mã hóa của bạn" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "Sao chép" @@ -10493,7 +10501,7 @@ msgstr "Sao chép" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10503,7 +10511,7 @@ msgstr "" "{ph0}›{ph1}{ph2}SỬ DỤNG REA để tìm CÁCH TH04 tạo ra một vòng đạn và nhắm vào" " người chơi. Giải thích tính toán và hiển thị mã.{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -10513,7 +10521,7 @@ msgstr "" "địa phương." #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10527,7 +10535,7 @@ msgstr "" #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10537,12 +10545,12 @@ msgstr "" "Một minh họa của toán học góc phục hồi cho đếm 16, hướng máy nghe nhạc 40 và" " mẫu xoay 0. {ph0}Hình mở{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "Mẫu bắn trong nguồn được phục hồi" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Elly ' s ring attack * đoạn trích nguồn" @@ -10551,7 +10559,7 @@ msgstr "Elly ' s ring attack * đoạn trích nguồn" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10561,13 +10569,13 @@ msgstr "" "Những dòng này chọn mẫu trước khi điều chỉnh độ khó và hiệu suất. {ph0}Đọc " "nguồn của cuộc tấn công{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "REA trả về gì" #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10579,12 +10587,12 @@ msgstr "" "REA trả về hướng dẫn, mã giả và tài liệu tham khảo. Ba phần của kết quả đó " "giải thích mô hình." -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "Kiểm tra hình ẢNH DOS trước khi đọc mã của nó" -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " @@ -10593,7 +10601,7 @@ msgstr "" "Việc kiểm tra liên kết mã đã tải và các bản ghi di dời đến tệp thực thi được" " cung cấp. Đường dẫn trên được rút ngắn để hiển thị." -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "Đọc nhân và chia của chiếc nhẫn" @@ -10601,7 +10609,7 @@ msgstr "Đọc nhân và chia của chiếc nhẫn" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10613,12 +10621,12 @@ msgstr "" "số đếm đọc từ {ph1}. Tên nguồn duy trì trường đó {ph2}. Trình tự hoàn chỉnh " "xuất hiện bên dưới." -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "Tìm nơi mẫu quay về phía người chơi" -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -10631,12 +10639,12 @@ msgstr "" " cho các địa chỉ đó có thể đọc được; REA cho phép tác nhân kiểm tra các hoạt" " động ban đầu đằng sau chúng." -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "Từ lắp Ráp Đến có Thể đọc Được c C" -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -10649,7 +10657,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -10657,7 +10665,7 @@ msgstr "{ph0}01{ph1} Chỉ số" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -10665,7 +10673,7 @@ msgstr "{ph0}02{ph1} Không gian" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -10673,7 +10681,7 @@ msgstr "{ph0}03{ph1} Mục tiêu" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -10681,18 +10689,18 @@ msgstr "{ph0}04{ph1} Xoay" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} Cửa hàng" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA * hướng dẫn 16-bit gốc" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "Có thể đọc Được C++ * tóm tắt vòng nhắm" @@ -10700,7 +10708,7 @@ msgstr "Có thể đọc Được C++ * tóm tắt vòng nhắm" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10714,7 +10722,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10729,7 +10737,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10744,7 +10752,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10759,7 +10767,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10772,7 +10780,7 @@ msgstr "" "trường góc đẻ trứng. Các giá trị bọc sau 255, giống như cast byte không dấu." " Nguồn xung quanh cũng chuyển đổi góc và tốc độ này thành vận tốc." -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -10783,7 +10791,7 @@ msgstr "" " C++ ở trên là một bản tóm tắt có thể đọc được. Kiểm tra trình biên dịch bên" " dưới áp dụng cho nguồn được duy trì trong dự án được liên kết." -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "Đọc vòng duy trì và mục tiêu nguồn" @@ -10800,7 +10808,7 @@ msgstr "Đọc vòng duy trì và mục tiêu nguồn" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10810,12 +10818,12 @@ msgstr "" "{ph0}Vòng macro{ph1} · {ph2}Mục tiêu và vận tốc nguồn{ph3} · {ph4}Biểu diễn " "góc{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "Kiểm tra nguồn duy trì" -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " @@ -10824,12 +10832,12 @@ msgstr "" "CÁC kiểm tra được ghi LẠI CỦA DỰ án TH04 biên dịch mã tạo đạn, bao gồm cả " "trình trợ giúp này, với chuỗi công cụ Turbo C 4 4.0 J được ghim." -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139 byte phù hợp" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " @@ -10837,12 +10845,12 @@ msgid "" msgstr "" "Mã tạo đạn được biên dịch khớp với phần 2.139 byte của tệp thực thi ban đầu." -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "Hai tòa nhà sạch sẽ" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -10855,66 +10863,66 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "" "Thu âm vào ngày 3 tháng 10 năm 2026. {ph0}Đọc kiểm tra trình biên dịch{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "Phạm vi phân tích và nhận dạng mục tiêu" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "Mục tiêu ban đầu" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0}, 156,258 byte, DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "Mục trợ giúp" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} TRONG HÌNH ẢNH ĐƯỢC tải CỦA REA" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "Tập tin ban đầu bù đắp" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0}, trả lại bởi {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "Kiểm tra mã được ghi lại" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA 4.1.0 * 7 tháng mười 2026" -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10925,7 +10933,7 @@ msgstr "" "chéo." #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10940,7 +10948,7 @@ msgstr "" "phạm vi được báo cáo đó." #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10956,7 +10964,7 @@ msgstr "" "tính của trò chơi được cung cấp được ghim bởi biểu hiện kho lưu trữ của nó, " "với nguồn gốc tự đổ nguyên sơ độc lập vẫn còn mở." -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10967,12 +10975,12 @@ msgstr "" "vi PHẦN CỨNG PC-98 có kiểm tra thời gian chạy riêng biệt trong dự án tái " "thiết." -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "VIỆC TÁI THIẾT TH04 đầy đủ" -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10985,7 +10993,7 @@ msgstr "" #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10997,7 +11005,7 @@ msgstr "{ph0}Khám PHÁ KHO LƯU TRỮ TH04{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11013,7 +11021,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11029,7 +11037,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -11054,22 +11062,22 @@ msgstr "" "KIỂM tra MÃ DOS 16 bit gốc CỦA TH04 VỚI REA . Thực hiện theo lắp Ráp Và phục" " Hồi C++ để xem cách một vòng đạn được đặt cách nhau và nhắm vào người chơi." -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "Trên trang này" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04 bullet-nghiên cứu trường hợp mẫu" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "Sao CHÉP DẤU nhắc VÍ DỤ TH04" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" @@ -11077,7 +11085,7 @@ msgstr "" "TH04 cố định và nhằm mục đích đạn nhẫn; di chuyển theo chiều ngang trên màn " "hình nhỏ hơn" -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -11090,27 +11098,27 @@ msgstr "" " tiên được đánh dấu về phía người chơi. Cả hai đều giữ khoảng cách 16 đơn vị" " góc hoặc 22,5 độ." -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "Sao CHÉP TH04 bắn mẫu" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "Thực HIỆN THEO CÁC TH04 nhằm mục đích tính vòng" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "Sao CHÉP TH04 lắp ráp đoạn trích" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "Sao chép có thể đọc được nhằm mục đích-tính toán vòng" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "Về đầu trang" @@ -11220,7 +11228,7 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "Tốc độ cố định: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" @@ -11229,7 +11237,7 @@ msgstr "" "Phát lại quy tắc phục hồi. Tất cả bốn giá trị phù hợp với kiểm tra trò chơi " "gốc được kiểm soát khi được làm tròn thành ba số thập phân." -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -11593,591 +11601,599 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "Khoảng cách tương tự: 256 ÷ 16 = 16 đơn vị góc = 22,5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "Ví dụ thực tế" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "Blog" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "Bắt đầu" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "Hướng dẫn" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "Mã nguồn" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "Giấy phép MIT" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "Tham gia cộng đồng" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "Theo dõi trên X" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA * nguồn tập lệnh đã chọn" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "Mã nguồn" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "Đầu ra định dạng dự kiến" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "Hướng dẫn" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "Người gọi" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "Hằng số" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "Chức năng C" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "Nút" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "TẢI TRƯỚC API" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV tập tin" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "Nhấp chuột của bạn" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "Yêu cầu bị bắt" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "Xuất tập lệnh" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "KẾT quả REA · tóm tắt.trích đoạn ipc" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "TRÍCH ĐOẠN HƯỚNG dẫn REA · 0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA hàm gọi trích đoạn * 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "KẾT quả byte REA * được hiểu là đôi endian nhỏ" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "Phục Hồi C · trích Đoạn" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "Xem REA hoạt động thế nào ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "Giới thiệu →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "Cài đặt đã chọn từ tập lệnh được kiểm tra" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "Tóm tắt có thể đọc được của trình xử lý %" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA * hướng dẫn ban đầu được chọn" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "Id nhà điều Hành * Nguồn Của Microsoft" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "Theo dõi @ reatools Trên X" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA → agent · kết quả đã chọn" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA → agent · phương pháp và hàm gọi" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA * Đã chọn Java dịch ngược" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "Tóm tắt có thể đọc được · giải thích của agent" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA * generateOTP · cơ thể hoàn chỉnh" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "Tải XUỐNG Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "Tải Xuống Nhà cung Cấp Phân Tích Android" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA → agent · kết quả đã chọn" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA → agent · hướng dẫn đã chọn" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "Agent → REA * read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA → agent · mục thứ bảy" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "Thực thi ban đầu * SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "Tải xuống thử thách ban đầu" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "Tải về người giải quyết" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "KẾT quả REA · đoạn trích mã giả" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → agent · trích đoạn hướng dẫn" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA → agent · hàm gọi trích đoạn" #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "Agent → REA * hai {ph0} yêu cầu" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA byte kết quả * giải mã như đôi" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "Bắt đầu với mục tiêu của riêng bạn" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "Tạo mã" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "Quy tắc phục hồi" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "Đồng hồ có thể điều chỉnh" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "Nhị phân" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "Kiểm tra mã" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "Phương trình" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "Đúng!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "Thực thi" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "PHÁT HIỆN REA" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "Phục Hồi C" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "Xác nhận" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "Ứng dụng đóng gói" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "Api tiếp xúc" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "GIẤY GÓI IPC" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "Clipboard" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "Mã DOS gốc" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA hướng dẫn" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "Tính toán góc" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "Vòng đạn" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "Api trang tiếp xúc" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "Trình kết XUẤT CUỘC GỌI IPC" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "Gửi đến clipboard hệ thống" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Lưu cục BỘ BỞI Notion" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Đầu vào đánh dấu" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "Đầu ra trình phân tích cú pháp có cấu trúc · đoạn trích" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "Phân tích ứng dụng của riêng bạn" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "Agent → REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA → agent * các trường được chọn" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "Agent → REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA → agent · trích đoạn hướng dẫn" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "Kết quả chức năng tương tự * aim trích đoạn" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "Tương Ứng Duy Trì C C" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "Vòng macro * chi NHÁNH TH04, đoạn trích" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "Góc và vận tốc * trích đoạn nguồn" @@ -12210,7 +12226,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12227,7 +12243,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12248,7 +12264,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12269,7 +12285,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12288,7 +12304,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12307,7 +12323,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12318,14 +12334,14 @@ msgstr "" "tôi.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "Tái thiết · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -12336,7 +12352,7 @@ msgstr "" "xét các thay đổi được đề xuất." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -12345,7 +12361,7 @@ msgstr "Một ví dụ được cung cấp · {ph0} và npm * Agent mã hóa c #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12364,7 +12380,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -12379,7 +12395,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12398,7 +12414,7 @@ msgstr "" #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12409,7 +12425,7 @@ msgstr "" " và viết tập tin.{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -12424,7 +12440,7 @@ msgstr "{ph0} * dòng 8-12" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12437,7 +12453,7 @@ msgstr "" " ra thực tế.{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -12448,7 +12464,7 @@ msgstr "" "đôi. Điều này kiểm tra trực tiếp bộ định dạng với {ph0}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -12456,7 +12472,7 @@ msgstr "{ph0} · CSV định dạng" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12465,7 +12481,7 @@ msgstr "" "Bạn sẽ cần {ph0} 22 (22.19+), 24 (24.11+) hoặc 26+. npm đi kèm với {ph1}." #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -12473,7 +12489,7 @@ msgstr "Không có {ph0}, hay không chắc chắn?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -12486,7 +12502,7 @@ msgstr "" "hãy cài đặt {ph1} 24 KG:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -12500,7 +12516,7 @@ msgstr "{ph0} * trích đoạn nguồn ví dụ" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -12509,9 +12525,9 @@ msgid "" msgstr "{ph0}Mở ví dụ{ph1} · {ph2}Tải về {ph3}{ph4} · {ph5}Tải về {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -12519,7 +12535,7 @@ msgstr "{ph0} * nguồn ví dụ" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -12533,7 +12549,7 @@ msgstr "" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12546,7 +12562,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -12559,7 +12575,7 @@ msgstr "Ví dụ: {ph0}vì sao Máy tính cho kết quả 220 khi tính {ph1}?{p #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12570,7 +12586,7 @@ msgstr "" "220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -12579,7 +12595,7 @@ msgstr "REA · đã tải {ph0} * các dòng đã chọn" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12597,7 +12613,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -12615,7 +12631,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -12628,28 +12644,28 @@ msgstr "" "phép tôi thay đổi thời gian.{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} * THÀNH VIÊN API" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} * TRỢ GIÚP IPC" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "chính/{ph0} * trình trợ giúp xử lý" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -12659,12 +12675,1405 @@ msgstr "chính/{ph0} * bộ thu clipboard" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "Bắt đầu {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "Chuyển sang giao diện sáng" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "Chuyển sang giao diện tối" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"Để kiểm tra phần thân yêu cầu và phản hồi HTTP, hãy dùng {ph0}Fiddler " +"Everywhere: bản ghi SAZ, MCP và kỹ năng công khai{ph1}. Xuất SAZ ho?c HAR " +"1.2 để lấy Evidence từ bản ghi trong REA ngoại tuyến, hoặc kết nối máy chủ " +"MCP của Everywhere để kiểm tra lưu lượng đã ghi cùng trợ lý của bạn." + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "Mô hình chuyên biệt{ph0}Bài viết" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Kỹ thuật đảo ngược có cần mô hình lớn hơn không?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "" +"Những suy nghĩ từ việc tái dựng Touhou về mô hình tổng quát, mô hình chuyên " +"biệt và cách học từ phản hồi của trình biên dịch." + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Bởi N0zoM1z0 · 13 tháng 10 năm 2026" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "Bỏ qua nội dung" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}Home{ph1} / {ph2}Blog{ph3} / Mô hình và kỹ thuật đảo ngược" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "Tiểu luận" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "Kỹ thuật đảo ngược có cần một mô hình lớn hơn không?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "Bởi N0zoM1z0 · 13 tháng 10 năm 2026" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "Điểm chính" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "" +"{ph0}Khả năng của mô hình ảnh hưởng đến những giả thuyết mà tác nhân AI có " +"thể đề xuất.{ph1} Các phiên sau đã giải quyết các vấn đề mà công việc trước " +"đó chưa được giải quyết." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "" +"{ph0}Một trình biên dịch quen thuộc cung cấp các mẫu cụ thể để một mô hình " +"chuyên biệt học.{ph1} Một số kết quả khớp mã máy chính xác phụ thuộc vào các" +" mẫu mã nguồn cụ thể, có thể tái sử dụng." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "" +"{ph0}Bao gồm kiến thức kho lưu trữ trong một so sánh công bằng.{ph1} Một mô " +"hình nhỏ hơn với khả năng truy xuất kiến thức tốt có thể đã có đủ thông tin " +"để đạt được tiến bộ." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "" +"{ph0}Huấn luyện mô hình để chọn thử nghiệm hữu ích tiếp theo và kiểm tra " +"công cụ xác minh của nó.{ph1} Phản hồi chỉ hữu ích trong phạm vi công cụ xác" +" minh những điều đúng." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "" +"{ph0}Đánh giá kết quả tái thiết đã được xác minh cùng với thời gian và chi " +"phí.{ph1} Đó là những gì tôi muốn đo lường cho quy trình làm việc hoàn chỉnh" +" của tác nhân AI." + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "Trong bài viết này" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}Mô hình mạnh hơn đã thay đổi điều gì?{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}Tại sao nên chuyên môn hóa?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}Kinh nghiệm này nên được lưu trữ ở đâu?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}Học thí nghiệm hữu ích tiếp theo{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}Học kỹ thuật đảo ngược và tăng cường{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}Khi công cụ xác minh sai{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}Một so sánh đáng chạy{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}Điều này gợi ý loại tác nhân AI nào?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "Mô hình mạnh hơn đã thay đổi điều gì?" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"Kể từ tháng 8 năm 2026, tôi đã khám phá mức độ kỹ thuật đảo ngược mà một tác" +" nhân có thể thực hiện khi có quyền truy cập vào một chương trình và cách " +"kiểm tra công việc của nó. Phần lớn kinh nghiệm của tôi đến từ việc xây dựng" +" lại trò chơi, đặc biệt là Touhou. Khi tôi thay đổi mô hình, các kho lưu trữ" +" đã lưu giữ một bản ghi về những gì mỗi phiên đã khôi phục được." + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"Phần lớn công việc hướng tới tái dựng chính xác: biên dịch mã nguồn đang " +"được duy trì bằng chuỗi công cụ lịch sử có phiên bản cố định, rồi kiểm tra " +"xem nó có tái tạo hàm đích hay không. Khi mô hình sau giải quyết được điểm " +"mà công việc trước bị mắc kẹt, thay đổi trong mã nguồn cho thấy điều gì đã " +"giúp tiến triển." + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "Các biến tạm thời cần có thời gian tồn tại chồng chéo" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"Phần lớn logic của hàm tấn công TH09 đã được xây dựng lại, nhưng trình biên " +"dịch vẫn lưu trữ các kết quả tạm thời khác với kết quả ban đầu. Vấn đề còn " +"lại là những kết quả đó cần tồn tại trong bao lâu và khi nào bộ nhớ của " +"chúng có thể được sử dụng lại." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"Bản ghi phiên {ph0}GPT-6-Sol{ph1} đã báo cáo sự không khớp này sau khi kiểm " +"tra một số cách sắp xếp mã nguồn thông thường. Khi {ph2}GPT-6.1-Sol kiểm tra" +" lại vấn đề{ph3}, nó đã đề xuất một giả thuyết hữu ích về thời gian tồn tại " +"của các biến tạm thời này." + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"Hàm này tạo ra các kết quả tạm thời và sao chép chúng vào các vị trí hoạt " +"ảnh. Trong C++, kết quả tạm thời vẫn tồn tại cho đến khi biểu thức sử dụng " +"nó kết thúc. Việc nhóm các hoạt động thực tế thành một biểu thức giúp giữ " +"cho các kết quả đó tồn tại cùng nhau, do đó trình biên dịch không thể sử " +"dụng lại cùng một bộ lưu trữ cho tất cả chúng nữa." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"Một kết quả vẫn được chia sẻ bộ nhớ với giá trị được sử dụng sau này để kiểm" +" tra xung đột. Việc đưa ra giá trị đó trong thời gian tồn tại của chính nó " +"đã giải quyết được sự chồng chéo còn lại. Sau một số thử nghiệm có mục tiêu," +" {ph0}việc biên dịch lại rõ ràng từ nguồn đã xác nhận rằng hàm đầy đủ khớp " +"với{ph1}." + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"Tôi quan tâm đến việc khám phá và thử nghiệm hỗ trợ lẫn nhau như thế nào. " +"Giả thuyết về thời gian tồn tại của đối tượng tạm thời đã mang lại cho tác " +"nhân AI một hướng đi mới. Phản hồi của trình biên dịch đã giúp nó tinh chỉnh" +" giả thuyết đó thành một cách sắp xếp mã nguồn phù hợp." + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "Biểu đồ luồng điều khiển khác" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"Hàm TH09 thứ hai cho biết tại sao hướng đi mới đó lại quan trọng. Ở đây, trở" +" ngại là làm thế nào một số chi nhánh chia sẻ công việc cuối cùng của họ. " +"Công việc trước đó của {ph0}GPT-6.1-Sol{ph1} có các phần của hàm khớp với " +"nhau, nhưng các nhánh vẫn được nối với nhau khác với ban đầu." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra đã thay đổi biểu đồ luồng điều khiển xung quanh{ph1}. Các " +"đường dẫn chính hiện đã dẫn đến bản cập nhật cuối cùng được chia sẻ và quay " +"trở lại. Trong cấu trúc nguồn đó, trình biên dịch kết hợp các nhánh giống " +"như bản gốc. Chức năng hoàn chỉnh đã khớp và một cuộc kiểm tra xây dựng lại " +"riêng biệt {ph2} đã xác nhận điều đó{ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}Việc thay đổi cách biểu diễn đã mở ra một không gian tìm kiếm hiệu quả " +"hơn.{ph1} Cả hai trường hợp đều cho tôi lý do để xem xét nghiêm túc khả năng" +" của mô hình chung: một tác nhân có thể tiếp tục thử các biến thể cục bộ " +"trong một thời gian dài trước khi tìm ra cách tốt hơn để thể hiện công việc " +"xung quanh." + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"Đồng thời, các phiên sau bắt đầu với nguồn trước đó và ghi lại lỗi. Công " +"việc tích lũy đó là một phần lợi thế của họ. Lịch sử cho phép chúng ta kiểm " +"tra những khám phá và kiểm tra chúng; một so sánh có kiểm soát sẽ giúp tách " +"biệt tác động của mô hình khỏi trải nghiệm mà nó kế thừa." + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"Đây là điều làm cho câu hỏi trở nên thú vị đối với tôi. Một số tiến bộ đến " +"từ việc tìm kiếm một đại diện mới. Phần lớn công việc còn lại liên quan đến " +"việc kiểm tra các cách sắp xếp mã nguồn khác nhau dựa trên một trình biên " +"dịch quen thuộc. Bao nhiêu trong số này đòi hỏi khả năng suy luận rộng? Một " +"mô hình có thể học được bao nhiêu khi làm việc liên tục với trình biên dịch " +"và mã đó?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "Tại sao một mô hình AI chuyên biệt có thể hoạt động tốt?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"Touhou cho chúng ta lý do cụ thể để mong đợi trải nghiệm đó sẽ hữu ích. Phần" +" lớn mã trò chơi đều đến từ cùng một tác giả, ZUN, vì vậy những thói quen " +"lặp đi lặp lại là một giả định khởi đầu hợp lý. Các kho lưu trữ hỗ trợ điều " +"đó bằng các ví dụ hữu ích: các vòng lặp liên quan và cách sắp xếp trợ giúp " +"đã cung cấp các giả thuyết cho các trò chơi." + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "" +"Các mẫu nguồn đó trở nên cụ thể hơn khi chúng tôi đưa trình biên dịch vào. " +"Trong một phiên bản và tập hợp các tùy chọn cụ thể, những thay đổi nhỏ về " +"nguồn có thể tạo ra những khác biệt lặp lại trong mã máy. Một số trong những" +" khác biệt đó mơ hồ một cách đáng ngạc nhiên." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"Ví dụ: trong TH095, {ph0}ngay cả tên biến cục bộ cũng có thể ảnh hưởng đến " +"vị trí VC7.1 lưu trữ nó{ph1}. Việc di chuyển khai báo của nó không giải " +"quyết được bố cục lưu trữ. Tuy nhiên, hàm nền trước đó đã tiết lộ kiểu đặt " +"tên ảnh hưởng đến sự lựa chọn của trình biên dịch. Điều đó gợi ý một giả " +"thuyết hứa hẹn hơn cho việc {ph2}tái tạo {ph3}{ph4}." + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "" +"Việc sử dụng lại mẫu đó cho biến kích thước tệp sẽ tạo ra bố cục cần thiết " +"mà không cần thêm bộ nhớ. Các chức năng đầy đủ sau đó phù hợp." + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "" +"Đây là một chi tiết rất cụ thể mà một mô hình AI đa năng có thể không biết " +"khi lần đầu gặp sự cố. Một mô hình chuyên dụng cho trình biên dịch này có " +"thể xem nhiều trường hợp như vậy và tìm hiểu xem biến thể mã nguồn nào đáng " +"để thử nghiệm trước tiên." + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"Cơ hội đặc biệt rõ ràng trong các bài toán so khớp cuối cùng khi chúng ta đã" +" hiểu rõ hành vi. Sau đó, chúng tôi sẽ hỏi trình biên dịch này sẽ chuyển sự " +"sắp xếp mã nguồn thông thường nào thành các lệnh máy được quan sát. Sự " +"chuyên môn hóa có thể giúp mô hình đề xuất các hình thức đó hiệu quả hơn, " +"trong khi mục tiêu vẫn xác định giả thuyết nào tồn tại." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"Các mẫu hữu ích phải đi kèm bối cảnh áp dụng. TH08 dùng phiên bản Visual C++" +" cũ hơn TH095 và TH09. TH04 dùng một trình biên dịch khác thuộc thời DOS. " +"{ph0}Việc tái dựng mã điều khiển người chơi{ph1} cần những giả thuyết khác " +"về cách viết mã và cách liên kết thành tệp thực thi. Cùng tác giả là một giả" +" định ban đầu; từng mục tiêu cho biết giả định đó có phù hợp không. Mô hình " +"chuyên biệt cần học cách phân biệt các bối cảnh này." + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "Kinh nghiệm này nên được lưu trữ ở đâu?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"Trước khi quyết định dạy những mẫu đó thông qua đào tạo mô hình, tôi sẽ xem " +"xét kiến thức mà chúng tôi đã lưu giữ trong kho. Trong {ph0}bài luận " +"trước{ph1}, tôi đã viết về việc nó trở thành bộ nhớ làm việc của dự án. Bộ " +"nhớ đó bao gồm các bài học về trình biên dịch, cùng với nguồn và các thử " +"nghiệm thất bại khiến chúng trở nên hữu ích." + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"Bằng cách truy xuất bản ghi đó, nhân viên hỗ trợ có thể bắt đầu với kết quả " +"đã biết và kiểm tra cách chúng tôi đạt được kết quả đó. Nó cũng có thể tránh" +" được những lựa chọn thay thế đã thất bại trong cùng bối cảnh. Điểm bắt đầu " +"được cải thiện mà không thay đổi các tham số đã huấn luyện của mô hình." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"Trong khi xây dựng lại chức năng tạo kẻ thù của TH09, phiên {ph0}GPT-6-Luna-" +"max{ph1} đã lấy một giả thuyết từ mã nguồn TH08 có liên quan. Mã trước đó đã" +" đề xuất cách tổ chức vòng lặp và xử lý các lỗi bên trong nó. Bằng chứng " +"riêng của TH09 đã cung cấp chi tiết cụ thể về trò chơi. Việc xây dựng lại từ" +" nguồn đã xác nhận rằng toàn bộ hàm khớp với bản gốc." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}\"Mô hình không biết lỗi của trình biên dịch\" và \"mô hình không thể " +"sử dụng nó\" là các vấn đề khác nhau.{ph1} Việc truy xuất có thể giải quyết " +"được vấn đề đầu tiên, nhưng việc biến thực tế đó thành một mã ứng viên hữu " +"ích vẫn cần nhiều công sức. Và nếu mã nguồn mã ứng viên không thành công, mô" +" hình phải quyết định kết quả có ý nghĩa gì cho lần thử tiếp theo. Biết mẫu " +"có liên quan chỉ là bước khởi đầu của quá trình đó." + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"Vì lý do đó, tôi sẽ đưa vào một mô hình AI có mục đích chung nhỏ hơn với khả" +" năng truy xuất tốt trong mọi so sánh. Cung cấp cho nó cùng một thư viện " +"kinh nghiệm sẽ giúp chúng tôi xác định nội dung đào tạo bổ sung: tạo ứng " +"viên tốt hơn, đưa ra quyết định tốt hơn sau khi phản hồi hoặc cả hai." + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "Học thí nghiệm hữu ích tiếp theo" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"Những quyết định sau khi được phản hồi là điều tôi muốn nghiên cứu nhất. " +"Trong tái cấu trúc tác nhân, mô hình đề xuất một lời giải thích và kiểm tra " +"nó dựa trên chương trình. Ngay cả khi mã nguồn ứng viên không thành công, " +"kết quả có thể thu hẹp các khả năng còn lại và đề xuất thử nghiệm tiếp theo " +"hữu ích hơn." + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "" +"Hãy xem xét lại ví dụ về kết quả tạm thời. Nguồn cuối cùng của nó cho thấy " +"sự sắp xếp đã có hiệu quả nhưng đường dẫn đến nguồn đó chứa nhiều thông tin " +"hơn. Mỗi thử nghiệm sau đây đã giúp xác định những gì vẫn cần thay đổi." + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "Thử nghiệm" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "Kết quả của nó đã dạy chúng ta điều gì" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "Hãy thử một cách khác để sao chép kết quả" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "Mã sao chép thay đổi nhưng chức năng vẫn khác." + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "Sử dụng trực tiếp các giá trị được trả về" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "Sao chép theo mẫu ban đầu, nhưng lưu trữ tạm thời vẫn khác." + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "Giữ tất cả các biến tạm thời hợp lệ cùng một lúc" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "" +"Chúng có bộ lưu trữ riêng biệt, nhưng một bộ vẫn chồng lên một giá trị được " +"sử dụng sau này để kiểm tra va chạm." + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "Giữ riêng giá trị kiểm tra va chạm" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "" +"Việc biên dịch lại rõ ràng từ nguồn xác nhận sự trùng khớp hoàn chỉnh." + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "" +"Các thử nghiệm được chọn từ quá trình tái cấu trúc chức năng tấn công ở " +"trên, được nhóm theo những gì chúng đã dạy chúng ta." + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"Một bản ghi huấn luyện lưu giữ trình tự này có thể dạy nhiều hơn chỉ riêng " +"nguồn cuối cùng. Nó kết nối từng thay đổi được đề xuất với kết quả được quan" +" sát và quyết định tiếp theo. Việc giữ lại các biến thể không hiệu quả cũng " +"rất quan trọng: chúng cho tác nhân sau này biết những giả thuyết nào đã được" +" kiểm tra trong bối cảnh đó." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}Tôi muốn mô hình học cách sử dụng phản hồi.{ph1} Kết quả trung lập là " +"lý do để xem xét lại biến thể; sự không phù hợp đã thay đổi có thể chỉ ra " +"một nguyên nhân khác. Khi các chỉnh sửa cục bộ không còn mang tính thông " +"tin, nhân viên sẽ có thể xem lại phần trình bày nguồn hoặc kiểm tra lại bằng" +" chứng." + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"Học cách đưa ra những lựa chọn đó đòi hỏi sự tự chủ. Đôi khi, bước tiếp theo" +" hữu ích là kiểm tra người gọi khác thay vì biên dịch một bản chỉnh sửa " +"khác. Một chuỗi các lần viết lại bắt buộc một cách cứng nhắc sẽ loại bỏ lựa " +"chọn đó, cùng với một phần hành vi mà chúng ta muốn mô hình học." + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "Tại sao kỹ thuật đảo ngược lại thú vị cho việc học tăng cường" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"Tái dựng trong phạm vi xác định là môi trường thực tế để nghiên cứu các lựa " +"chọn này. Khi phiên bản của mục tiêu và trình biên dịch được cố định, nhiều " +"thử nghiệm mã nguồn cho phản hồi nhanh và có thể lặp lại. Tác nhân có thể " +"biên dịch mã ứng viên, xem khác biệt rồi chọn bước tiếp theo." + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"Học tăng cường có thể rèn luyện quá trình ra quyết định đó thông qua phản " +"hồi mà nó nhận được. Một mã ứng viên được chấp nhận bởi một cuộc kiểm tra " +"xác định sẽ cho chúng ta một kết quả cụ thể, trong khi trình tự các lần thử " +"cho phép chúng ta quan sát xem cần bao nhiêu công sức để đạt được kết quả " +"đó." + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"Đã có nghiên cứu hỗ trợ hướng này. {ph0}LLM4Decompile{ph1} nghiên cứu các mô" +" hình chuyên dùng cho việc dịch ngược. {ph2}AutoDecompiler{ph3} đào tạo sàng" +" lọc nhiều lượt bằng cách sử dụng phản hồi của trình biên dịch và thực thi. " +"Nghiên cứu của họ tập trung vào phục hồi chức năng. Đối với công việc này, " +"tôi sẽ sử dụng chúng làm điểm khởi đầu cho nhiệm vụ liên quan là tìm nguồn " +"phù hợp với đầu ra của trình biên dịch lịch sử." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"Tuy nhiên, để đạt được nhiệm vụ được xác định rõ ràng như vậy, trước tiên " +"chúng ta có thể cần thiết lập tài nguyên nào mà hàm sở hữu hoặc nghĩ ra cách" +" mới để quan sát hành vi của chương trình khi chạy. Ví dụ: trong TH08, sự " +"khác biệt về va chạm {ph0} dẫn đến cách chương trình ban đầu xử lý các phép " +"tính dấu phẩy động{ph1}. Trước khi tác nhân có thể kiểm tra một sự điều " +"chỉnh hữu ích, nó phải tìm ra những gì cần đo lường." + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "" +"Điều này gợi ý một vai trò khác của một mô hình có khả năng rộng rãi: giúp " +"làm cho vấn đề có thể được kiểm tra ngay từ đầu. Khi kiểm tra đó tồn tại, " +"chúng tôi có thể điều tra xem chính sách tìm kiếm đã học có thể đi được bao " +"xa." + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "Khi công cụ xác minh sai" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"Khi dùng một phép kiểm tra để huấn luyện, phạm vi kiểm tra cũng trở thành " +"một phần của môi trường học. Tôi gọi chuẩn tham chiếu hoặc công cụ kiểm tra " +"đó là oracle. Ngay cả câu trả lời lặp lại được cũng cần được hiểu theo những" +" gì nó thực sự xác minh." + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 cho thấy vấn đề có thể ẩn ngoài phạm vi kiểm tra. Một số hàm tái dựng " +"dùng hằng số dấu phẩy động sai nhưng vẫn vượt qua so sánh chính xác. Bộ so " +"sánh điều chỉnh địa chỉ tái định vị trước khi kiểm tra lệnh máy, nhưng chỉ " +"kiểm tra giá trị tại các địa chỉ đó nếu chúng đã được ghi nhận rõ ràng để " +"xác minh. Những tham chiếu hằng số khác có thể vượt qua mà không được kiểm " +"tra giá trị." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"Để giải quyết khoảng trống này, {ph0}kiểm tra rộng hơn{ph1} đã tìm thấy các " +"hằng số không chính xác trong các hàm đã vượt qua quá trình xác minh. Trong " +"một phép tính, mã nguồn được xây dựng lại đã thêm {ph2}, trong khi mã nguồn " +"ban đầu được thêm {ph3}." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}Mô hình được khen thưởng bằng kiểm tra xác minh cũ có thể học cách tạo " +"ra bản dựng lại không chính xác.{ph1} Chúng tôi không đào tạo mô hình RL " +"bằng trình kiểm tra đó. Sự thất bại mà chúng tôi quan sát thấy nằm ở chính " +"việc kiểm tra. Nhưng nếu chúng ta sử dụng nó như một phần thưởng thì điểm mù" +" đó sẽ trở thành một phần của môi trường học tập." + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"Một bài kiểm tra chức năng có thể có điểm mù tương tự. {ph0}Nghiên cứu sử " +"dụng tính năng làm mờ vi phân trên bộ giải mã LLM{ph1} đã tìm thấy những " +"khác biệt về hành vi bên ngoài các thử nghiệm được cung cấp. Do đó, chúng ta" +" cần hiểu một bài kiểm tra đạt theo các trường hợp mà nó thực hiện. Tương " +"tự, một lệnh khớp phải được hiểu theo byte và dữ liệu mà nó xác minh." + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"Trước khi sử dụng một trong hai loại kiểm tra xác minh làm phần thưởng, tôi " +"sẽ kiểm tra nó với kết quả cố tình sai. Tôi cũng sẽ tách biệt sự chấp nhận " +"cuối cùng với mã nguồn mà tác nhân AI có thể chỉnh sửa. Mô hình phải vượt " +"qua quá trình xác minh bằng cách xây dựng lại chương trình một cách chính " +"xác. Mặt khác, chỉ cần sao chép một mảng byte từ mục tiêu có thể đánh lừa " +"một hệ thống tính điểm ngây thơ mà không khôi phục được mã nguồn hữu ích." + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "" +"{ph0}Cải thiện mô hình học và cải thiện công cụ xác minh là hai phần của " +"cùng một vấn đề nghiên cứu.{ph1} Mô hình càng giỏi tối ưu phản hồi được cung" +" cấp, chúng ta càng cần hiểu chính phản hồi đó." + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "Một so sánh đáng chạy" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"Với những bước kiểm tra đó, tôi sẽ bắt đầu so sánh trên nhóm nhiệm vụ VC7.1 " +"cố định. Đầu tiên, tôi sẽ thiết lập các đường cơ sở cho một mô hình AI có " +"mục đích chung mạnh mẽ và một mô hình nhỏ hơn. Việc bổ sung kiến ​​thức về " +"kho lưu trữ vào mô hình nhỏ hơn sẽ cho thấy những thay đổi trong quá trình " +"truy xuất. Từ đó, chuyên môn hóa được giám sát và phiên bản được đào tạo RL " +"sẽ cho phép chúng tôi kiểm tra nội dung đào tạo bổ sung." + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"Để làm cho những so sánh đó trở nên hữu ích, mỗi mô hình sẽ nhận được các " +"bằng chứng và công cụ mục tiêu giống nhau. Đối với các so sánh dành riêng " +"cho đào tạo, tôi cũng sẽ giữ nguyên mô hình cơ sở và kiến ​​thức có sẵn. Các" +" thử nghiệm lặp đi lặp lại sẽ giúp phân biệt một chiến lược tìm kiếm đáng " +"tin cậy với một giải pháp ứng viên tình cờ thành công." + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"Sau đó, tôi sẽ tách hai điều kiện bắt đầu: xây dựng lại một hàm từ các lệnh " +"máy của nó và đóng một số khác biệt cuối cùng trong nguồn được duy trì. Một " +"mô hình AI chuyên dụng có thể thực hiện xuất sắc nhiệm vụ thứ hai trong khi " +"một mô hình AI có mục đích chung thực hiện phần lớn công việc cần thiết để " +"đạt được nhiệm vụ đó. Việc đo lường chúng một cách riêng biệt sẽ tiết lộ sự " +"phân chia công việc đó." + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"Cả hai nhiệm vụ đều cần loại trừ các mẫu thử nghiệm khỏi quá trình đào tạo " +"và truy xuất. Trò chơi Touhou liên quan chia sẻ mã công cụ. Việc loại trừ " +"một trò chơi khỏi quá trình huấn luyện vẫn có thể để lại các chức năng gần " +"như giống hệt nhau trong tập huấn luyện. Thay vào đó, tôi sẽ loại trừ toàn " +"bộ các nhóm mã nguồn có liên quan và loại bỏ các câu trả lời đã được xác " +"minh của chúng khỏi cả dữ liệu huấn luyện và thư viện truy xuất." + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"Kết quả cần đo là các lần khớp hoàn chỉnh, được xác minh độc lập. Giới hạn " +"số mã ứng viên hoặc số lần biên dịch bằng nhau giúp so sánh chất lượng tìm " +"kiếm. Đo tổng thời gian và chi phí, kể cả biên dịch, cho biết chất lượng đó " +"có tạo ra quy trình hiệu quả không. Chi phí huấn luyện cần tính riêng." + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"Cả hai phép đo đều quan trọng. Một đề xuất rẻ tiền có thể dẫn đến một quy " +"trình làm việc tốn kém nếu nó tạo ra nhiều lần biên dịch không cung cấp " +"thông tin hữu ích. Ngược lại, một mô hình chậm hơn có thể tiết kiệm hơn nếu " +"nó tìm thấy một thử nghiệm hữu ích sớm hơn. Việc so sánh nên bao gồm những " +"chi phí này." + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"Việc đếm các kết quả được chấp nhận cũng giúp duy trì tiến độ trung gian. " +"Một TH09 {ph0}mã ứng viên lưu lại phát lại{ph1} có vẻ đầy hứa hẹn vì hàm " +"được biên dịch có kích thước như mong đợi nhưng so sánh đầy đủ vẫn tìm thấy " +"những khác biệt đáng kể. Những thay đổi trong cách trình biên dịch sắp xếp " +"các lệnh máy cũng có thể khiến mã ứng viên có vẻ gần hơn mà không giải quyết" +" được vấn đề cơ bản. Chẩn đoán như vậy có thể hướng dẫn thử nghiệm tiếp " +"theo, nhưng tôi sẽ xác thực bất kỳ phần thưởng nào cho việc \"tiến gần hơn\"" +" so với kiểm tra chấp nhận hoàn toàn." + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"Tôi sẽ quan tâm đến mô hình trên các kết quả này. Nếu một mô hình AI chuyên " +"dụng hoạt động tốt trong dòng trình biên dịch quen thuộc, liệu lợi thế đó có" +" tồn tại được khi thay đổi chuỗi công cụ không? Và một khi cả hai mô hình AI" +" đều có khả năng truy xuất tốt thì việc đào tạo vẫn bổ sung thêm bao nhiêu? " +"Câu trả lời sẽ giúp chúng ta quyết định xem mỗi loại mô hình sẽ hữu ích nhất" +" ở đâu." + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "Điều này gợi ý loại tác nhân AI nào?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"Nếu các mô hình tỏ ra hữu ích ở các giai đoạn khác nhau, thì sự sắp xếp hữu " +"ích có thể là một tác nhân rộng rãi có quyền truy cập vào một mô hình AI " +"chuyên dụng. Khi một nhiệm vụ trở thành một công cụ tìm kiếm trình biên dịch" +" quen thuộc, nó có thể yêu cầu mô hình AI chuyên biệt dành cho ứng viên. Nếu" +" kết quả không còn có ý nghĩa nữa, tác nhân rộng hơn có thể quay lại bằng " +"chứng mục tiêu hoặc tự điều tra phép đo." + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"Trong sự sắp xếp đó, sự chuyên môn hóa trở thành một công cụ mà đặc vụ có " +"thể lựa chọn khi cuộc điều tra phát triển. Người đại diện có quyền tự do " +"thay đổi hướng đi để có thể đạt được những đột phá trước đó." + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"Điều này diễn ra một cách tự nhiên từ sự chuyển dịch công nghiệp mà tôi đã " +"mô tả trong bài viết trước. Việc có thể chạy nhiều thử nghiệm hơn sẽ thay " +"đổi cách chúng ta tổ chức công việc. Nó cũng cho chúng ta lý do để hỏi những" +" quyết định nào cần được đánh giá rộng rãi và quyết định nào được cải thiện " +"thông qua kinh nghiệm lặp đi lặp lại với một nghề cụ thể." + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"Hiện tại, mô hình tổng quát mạnh nhất đã có chỗ đứng trong quy trình của tôi" +" vì giải quyết được những vấn đề trước đó còn bỏ ngỏ. Những thành công này " +"khiến tôi muốn xem kỹ quá trình: bao nhiêu phần phụ thuộc vào năng lực rộng " +"của mô hình, và bao nhiêu phần có thể giao cho một mô hình được huấn luyện " +"riêng cho kiểu tái dựng này?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "" +"{ph0}Các kho lưu trữ cung cấp cho chúng tôi một cách để kiểm tra câu " +"hỏi.{ph1} Tôi muốn sử dụng hồ sơ đó để xây dựng sự so sánh và xem những gì " +"chúng tôi học được." + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "Bằng chứng và quy kết mô hình" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"Các ví dụ mô tả các so sánh cấp độ chức năng lịch sử được ghi lại trong các " +"cam kết được liên kết. Kiểm tra thời gian chạy toàn bộ trò chơi là các cột " +"mốc riêng biệt. Nguồn và hồ sơ trùng khớp đã được xem xét vào ngày 13 tháng " +"10 năm 2026." + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"Nhãn TH09 {ph0} có nghĩa là GPT-6-Astra. Mô hình được liên kết với {ph1} đã " +"thay đổi theo thời gian, do đó, riêng nhãn đó không thể xác định được mô " +"hình được sử dụng trong một lần chạy cụ thể. Tên mô hình rõ ràng trong các " +"cam kết được trích dẫn khác cung cấp thông tin ghi nhận. Những lịch sử này " +"không bao gồm các phép đo nhất quán về chi phí hoặc nỗ lực cho mỗi lần chạy." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "" +"{ph0}TH09 thời gian tồn tại của đối tượng tạm thời:{ph1} {ph2}xem xét ngữ " +"cảnh trước đó{ph3} và {ph4} việc xây dựng lại hoàn chỉnh được xác minh bằng " +"cách biên dịch lại rõ ràng từ nguồn{ph5}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}Callback Front của TH09:{ph1} {ph2}các vùng chẩn đoán chưa khớp{ph3}, " +"{ph4}đồ thị luồng điều khiển mới của Astra{ph5} và {ph6}phép kiểm tra biên " +"dịch lại đã được chấp nhận{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}Kiến thức về trình biên dịch:{ph1} {ph2}TH095 tái sử dụng hành vi của " +"nhóm nhận dạng{ph3}, {ph4}TH04 mã nguồn người chơi và thứ tự trình liên " +"kết{ph5} và {ph6}Luna tái thiết hoàn toàn chức năng tạo kẻ thù của " +"TH09{ph7}." + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}Kiểm tra và chẩn đoán:{ph1} {ph2}kiểm tra hằng số dấu phẩy động của " +"TH08{ph3}, {ph4}điều tra số học của TH08{ph5} và {ph6}tái dựng chức năng lưu" +" replay của TH09{ph7}." + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "" +"Những so sánh được đề xuất giữa các mô hình chuyên dụng và chương trình đào " +"tạo RL là những thử nghiệm trong tương lai. Lịch sử dự án thúc đẩy họ. Không" +" có mô hình chuyên ngành được đào tạo nào được đánh giá cho bài tiểu luận " +"này." + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "Kỹ thuật đảo ngược có cần một mô hình lớn hơn không? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "" +"Việc tái xây dựng Touhou đã dạy tôi điều gì về các mô hình chung, mô hình " +"chuyên biệt và việc học cách đề xuất các giả thuyết tốt hơn từ phản hồi của " +"trình biên dịch." + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "Trên trang này" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "Mô hình và tiểu luận kỹ thuật đảo ngược" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "Các thí nghiệm tái thiết được chọn" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "Về đầu trang" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "" +"{ph0}Ghi chú bằng chứng chi tiết{ph1} bao gồm các kết quả so sánh và bối " +"cảnh thử nghiệm." + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "N0zoM1z0 · 13 tháng 10 năm 2026 · Bản nháp để góp ý" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "Hướng dẫn cài đặt" diff --git a/website/locales/zh-CN/messages.po b/website/locales/zh-CN/messages.po index 58908a5eb..9a4933ad7 100644 --- a/website/locales/zh-CN/messages.po +++ b/website/locales/zh-CN/messages.po @@ -8,76 +8,77 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted baseline; see website/locales/README.md for review workflow\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "跳转到内容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}首页{ph1} /博客" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "博客。" -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "逆向工程的思考。" #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "游戏重建{ph0}论文" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "逆向工程的工业革命" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " "agents, verification and knowledge that compounds across projects." msgstr "什么手动重新和重建TH08,TH095和TH04教我关于编程助手,验证和知识,跨项目的化合物。" -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "阅读文章" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "通过N0zoM1z0*10十月2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -96,6 +97,8 @@ msgid "" msgstr "对逆向工程的思考,借鉴与 REA 和AI编程助手。" #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -129,112 +132,117 @@ msgid "" "agent." msgstr "REA-了解软件的工作原理。 逆向工程与你的编程助手." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "REA 首页" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "主导航" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "在 GitHub 查看 REA" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "加入 REA 的 Discord 社区" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "在 X 上关注 REA" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -243,35 +251,35 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}首页{ph1} / {ph2}博客{ph3} / 东方游戏重建" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "随笔 · 东方游戏重建" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "逆向工程的工业革命。" -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "作者 N0zoM1z0 · 2026 年 10 月 10 日" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "要点" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -281,7 +289,7 @@ msgstr "{ph0}让编程助手自主开展调查。{ph1}明确目标和验收标 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -292,7 +300,7 @@ msgstr "{ph0}把代码仓库和 Git 当作工作记忆。{ph1}推理过程和代 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -302,7 +310,7 @@ msgstr "{ph0}结论要由证据决定。{ph1}说得再肯定,也需要验证 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -312,7 +320,7 @@ msgstr "{ph0}校验基准本身也要测试。{ph1}故意给它应当拒绝的 #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -320,65 +328,65 @@ msgid "" "methods are still taking shape. There is plenty left to explore." msgstr "{ph0}我们正处于逆向工程工业革命的早期。{ph1}方法还在成形,还有很多值得探索的地方。" -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "经验如何产生复利" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}人来定方向{ph1} · 目标和验收标准" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "自主探索" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "编程助手" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "选择实验。{ph0}提出假设。" -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "验证" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "校验基准" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "对照{ph0}具体的基准验证。" -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "代码仓库" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "工作记忆" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -387,7 +395,7 @@ msgstr "代码、证据、{ph0}检查和经验。" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -396,40 +404,40 @@ msgstr "不匹配{ph0}{ph1}修正假设{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "更好的{ph0}{ph1}起点{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "复用" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}通过{ph1} · 保留结果及其证据" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " "fixing the checks when we discover a gap." msgstr "每个项目都为下一个项目留下更好的起点。发现检查有漏洞时,也要把检查修好。" -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "在本文中" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -437,7 +445,7 @@ msgstr "{ph0}2026年8月{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -445,7 +453,7 @@ msgstr "{ph0}TH08:接续前人的工作{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -453,7 +461,7 @@ msgstr "{ph0}两种方法{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -461,7 +469,7 @@ msgstr "{ph0}TH095:经验的复利{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -469,7 +477,7 @@ msgstr "{ph0} TH04:跨架构{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -477,7 +485,7 @@ msgstr "{ph0}从精确到可读{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -485,18 +493,18 @@ msgstr "{ph0}工业化的转变{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}新的可能性{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "2026年8月发生了什么变化" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -507,7 +515,7 @@ msgid "" msgstr "" "在这之前,我做过很多手工逆向。我会反复查看一个函数,直到能解释它,再对照程序验证这个解释。想推进项目,就得亲自花更多时间研究下一个函数,脑子里也要记住越来越多的整体关系。" -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -518,7 +526,7 @@ msgstr "" "我的逆向工作主要围绕游戏。我希望通过重建弄清游戏的行为,最终做出移植版或 " "mod。这篇文章来自这些经历。方法可以迁移到其他领域,但每个领域都需要先明确:什么可以用可靠的基准来验证。" -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -528,7 +536,7 @@ msgid "" msgstr "" "2026 年 8 月,我开始认真探索让编程助手做逆向。有了程序本身和常用开发工具,它究竟能走多远?东方游戏重建给了我一个足够完整的项目来寻找答案。" -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -540,7 +548,7 @@ msgid "" msgstr "" "早期的进展让我吃惊。我不再需要为每一步作选择,调查也能持续推进。对比失败后,助手可能转去查看另一个调用方,写一段诊断程序,再根据结果决定下一步。这种自主性改变了我的工作:我可以更多关注项目方向,以及检查是否可靠。" -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -548,7 +556,7 @@ msgid "" "had just learned?" msgstr "速度先引起了我的注意。随后我开始想:当前项目结束后,什么会留下来?下一个游戏能不能用上我们刚学到的经验?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08:接续前人的工作" @@ -557,7 +565,7 @@ msgstr "TH08:接续前人的工作" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -569,7 +577,7 @@ msgstr "" "{ph0}TH08{ph1},也就是《东方永夜抄》,从接续{ph2}GensokyoClub " "的重建工作{ph3}开始。他们的公开源码提供了扎实的基础,也留下了构建经验和贡献历史。我在后续工作中保留了这些历史。" -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -579,7 +587,7 @@ msgstr "" "导入的历史截至 8 月 10 日的公开检查点。我的独立续作从 8 月 13 日开始。到 8 月 19 日,进度台账中已识别的 1,107 " "个游戏函数都有了源码。" -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -589,7 +597,7 @@ msgstr "" "8 月 24 日,我们提交了可玩的 Linux 重建移植版,距离开始续作约十一天。随后做出了 Web 版。8 月 30 日,原生 Linux 64 " "位版发布。" -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -601,7 +609,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -614,12 +622,12 @@ msgid "" msgstr "" "这让对照检查成为工作的核心。我把这些基准称为{ph0}校验基准(oracle){ph1}。代码对比可以检查重建函数是否复现原始指令;运行时检查可以确认已走过的路径是否到达预期状态。助手提出解释,再验证它。发现不匹配,就有了具体的调查方向。" -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "常量错了,却仍然“精确匹配”" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -628,7 +636,7 @@ msgstr "校验工具也是人写的软件。TH08 让我清楚地看到,多少 #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -639,7 +647,7 @@ msgstr "" "9 月,下游 Switch 移植版报告了一个 bug,最后追溯到道具自动收集。重建源码把玩家火力与 {ph0} 比较,而原版用的是 " "{ph1},即满火力的阈值。" -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -651,13 +659,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}可这个函数之前已经通过了精确对比。{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -669,7 +677,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -682,7 +690,7 @@ msgstr "漏洞就在这里:工具可以把重建指令的引用地址调整为 #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -694,7 +702,7 @@ msgstr "" "{ph0}9 月 2 日的修复{ph1}纠正了源码,并让比较工具检查被引用常量的实际字节。随后进行的{ph2}全面审计{ph3}检查了 1,548 " "处浮点常量引用,又在五个已通过验收的函数中发现十二处错误引用。" -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -704,7 +712,7 @@ msgstr "现在工具会检查每一处这样的浮点常量。测试还会故意 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -712,7 +720,7 @@ msgid "" "repairing the game." msgstr "{ph0}校验基准本身也需要重建。{ph1}修复它,就是修复游戏的一部分。" -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -725,7 +733,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -738,7 +746,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -746,7 +754,7 @@ msgid "" " for the next batch.{ph1}" msgstr "{ph0}每完成一批工作,我们既得到了还原的代码,也改善了下一批工作的环境。{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "两种不同的重建理念" @@ -755,7 +763,7 @@ msgstr "两种不同的重建理念" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -766,14 +774,14 @@ msgstr "" "GensokyoClub 的{ph0}公开 " "README{ph1}明确表达了对这种工作的异议。公告说,项目完成前,后续开发将在私下进行。其中有这样一段话:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" " our work paints a bad image for future decompilation efforts…" msgstr "“这个领域里出现了利用我们成果的投机者(AI 反编译和移植项目),给未来的反编译工作留下了不好的印象……”" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -786,7 +794,7 @@ msgstr "" "公告也提到了维护者承受的心理压力。他们的贡献政策不接受主要由 AI 生成的 " "PR。他们用业余时间投入了艰难的工作,这些成果让我的续作成为可能。我尊重他们付出的努力。我想讨论的分歧,是重建应当如何推进,以及贡献应当如何评价。" -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -796,7 +804,7 @@ msgid "" msgstr "" "在我熟悉的手工流程中,理解一个函数和重建它,通常由同一个人完成。项目非常依赖这个人的专业能力。很多推理发生在工作过程中,所以对贡献者本人的信任很重要。" -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -804,7 +812,7 @@ msgid "" "pursue the next investigation on its own." msgstr "已有项目本就会在源码和构建工具中保存知识。对我而言,变化在于:编程助手能利用这些知识,自主推进下一次调查。" -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -815,7 +823,7 @@ msgid "" msgstr "" "在我的续作中,我来确定目标和验收标准,助手有充分的调查自由。它提出的重建方案必须通过相应检查。我希望其他人能够看懂我们为什么选择这个实现,即使大部分工作由助手完成。" -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -825,7 +833,7 @@ msgid "" msgstr "" "这可能是一个艰难的转变。多年的细致工作,可能成为一个推进得更快的续作的基础。这会带来真实的归属与署名问题,也改变维护者在接受贡献前需要了解的事情。" -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -836,7 +844,7 @@ msgid "" msgstr "" "工业化的比喻有助于理解这一点。手工作业的过程往往依赖操作者的技艺。机器改变了这些技艺发挥作用的位置,但仍然需要人设计流程、识别错误产出。不同社区可以选择接受多少这样的变化。" -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -857,7 +865,7 @@ msgstr "我的选择是公开继续,注明继承的工作并保留其历史。 #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -868,14 +876,14 @@ msgstr "" "来源:GensokyoClub 的{ph0}README 公告{ph1}(于 2026 年 10 月 10 " "日核对)及其{ph2}贡献政策{ph3}。上面的引文为节选译文。TH08 的{ph4}贡献署名与来源记录{ph5}说明了独立续作的起点。" -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095:经验开始产生复利" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -887,7 +895,7 @@ msgstr "" "{ph0}TH095{ph1},也就是《东方文花帖》,让这些经验的价值更容易看清。仓库于 8 月 29 " "日建立,当时台账中确认的游戏函数数量为零。我们仍需研究游戏本身,但已经更清楚如何开始重建,以及怎样持续推进。" -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -898,7 +906,7 @@ msgstr "" "到 9 月 7 日,全部 697 个已识别游戏函数都有了源码。9 月 8 日,其中 696 个通过了精确对比。9 月 9 日,整个程序完成链接。9 月 " "10 日,Windows i386 重建版被记录为可玩,距离初始化约十二天。" -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -906,7 +914,7 @@ msgid "" "present in the tools and in the way the project was organized." msgstr "这比第一个项目的速度更让我兴奋。新目标能受益于另一个游戏的工作。经验已经进入工具,也进入了项目的组织方式。" -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -918,7 +926,7 @@ msgstr "" "例如,TH08 教会我们尽早关注整个程序。如果几个还原函数依赖同一份状态,分别对比它们仍然会留下一个关键问题:它们能否一起正常工作?这条经验影响了 " "TH095 的整程序构建方式。" -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -928,7 +936,7 @@ msgid "" msgstr "" "经验只记在我脑子里,我在场时它才有用。变成其他会话能运行的检查后,即使我离开,它仍能帮助项目。下一个助手可以利用检查结果,不用重复当初得出这条经验的调查。" -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -940,7 +948,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -949,7 +957,7 @@ msgid "" "actually new about its target." msgstr "{ph0}方法本身成了下一个游戏的起始材料。{ph1}我们可以把更多精力放在新目标真正不同的地方。" -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -958,7 +966,7 @@ msgid "" "the way it does." msgstr "后来加入的人也能受益。他们可以查看某个决定,重新运行检查,再继续工作。不用先重走整个项目的历史,才能理解源码为何这样写。" -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04:换了架构,工作方式仍然适用" @@ -967,7 +975,7 @@ msgstr "TH04:换了架构,工作方式仍然适用" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -980,7 +988,7 @@ msgstr "" "{ph0}TH04{ph1},也就是《东方幻想乡》,把这套工作带到了 PC-98 DOS 时代。这次是一个由四个程序协作的 16 " "位环境。理解硬件行为,需要和 Windows 游戏不同的证据。已有的{ph2}ReC98 工作{ph3}同样提供了宝贵的知识与源码材料。" -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -991,7 +999,7 @@ msgstr "" "DOS 重建版现在已经能运行。我手工打完了完整的 Normal 路线,看到结局,并检查了存档。目前正在做原生 64 位移植。先得到一个正常工作的 DOS" " 版,就为移植提供了参照。" -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1000,7 +1008,7 @@ msgid "" "next experiment." msgstr "架构改变了要调查的问题,也改变了用来验证的编译器和运行时。但助手依然能沿着问题找到结果,再用结果指导下一次实验。" -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1012,7 +1020,7 @@ msgstr "" "比如从游戏过程切换到结局:哪些状态需要跨越这个边界?哪个程序负责它们?我们可以对照 DOS 原版调查。只要证据和检查可用,助手就能像研究 Windows" " 游戏一样推进这个问题。" -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1020,7 +1028,7 @@ msgid "" "defined the problem; the workflow still gave us a way to solve it." msgstr "这就是 TH04 对这篇文章的意义。大幅的平台变化,并没有迫使我们重新发明一套工作方式。架构决定了问题,工作流程仍然提供了解决问题的方法。" -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1034,7 +1042,7 @@ msgstr "做 64 位移植时,我们可以把新实现与 DOS 上已经还原的 #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1042,19 +1050,19 @@ msgid "" "testing{ph1} · {ph2}64-bit port{ph3}. The port remains in development." msgstr "截至 2026 年 10 月 10 日:{ph0}DOS 重建与手工测试{ph1} · {ph2}64 位移植{ph3}。移植仍在开发中。" -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "从精确还原到可读源码" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "重建版能运行之后,我还希望别人能读懂它。" -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1066,7 +1074,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1078,7 +1086,7 @@ msgid "" msgstr "" "这就需要{ph0}语义重建{ph1}。一个还原字段可能仍然只有偏移作为标识。我们追踪游戏如何使用它,直到能解释其作用,再依据证据赋予合适的名称和类型。推理过程和源码一起保存,后来的人就能知道这个解释从何而来。" -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1090,14 +1098,14 @@ msgstr "" "移植时,语义尤其重要。绝对地址能告诉我数据在旧程序中的位置,却很难帮助 64 " "位实现决定哪个对象应当持有这份状态。要正确迁移行为,就得还原旧内存访问背后的关系。" -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "我现在采用这样的顺序:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1110,7 +1118,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1123,7 +1131,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1136,7 +1144,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1147,7 +1155,7 @@ msgstr "{ph0}再做现代平台移植。{ph1}把已经确定的行为带入新 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1159,7 +1167,7 @@ msgid "" msgstr "" "第二阶段的可玩构建,在第三阶段成为{ph0}第二套校验基准{ph1}。第一套检查修改后的源码是否仍然复现原版相关代码和数据;第二套检查重建程序是否能构建,并在实际测试的路径上保持正确行为。" -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1169,7 +1177,7 @@ msgid "" msgstr "" "它们能发现不同类型的错误。类型修改可能改变生成的指令。状态归属的修改,可能让游戏的两部分各自使用一份状态。保留两套检查,助手就能在继续重构之前,针对具体的失败展开调查。" -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1183,7 +1191,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1198,7 +1206,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1206,12 +1214,12 @@ msgid "" "makes the recovered knowledge usable.{ph1} A port can then build on both." msgstr "{ph0}精确重建提供基准,语义重建让还原的知识可用。{ph1}移植随后建立在两者之上。" -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "为什么这是工业化的转变" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1221,7 +1229,7 @@ msgid "" msgstr "" "这些项目改变了我投入注意力的地方。助手能自主推进大部分调查之后,改善它们的工作环境,就成了我最值得做的事情之一。一项工具的改进,可以帮助之后所有需要它的函数。" -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1231,7 +1239,7 @@ msgid "" msgstr "" "自主性在这里很重要。下一步该怎么做,常常在实验失败后才清楚。助手需要足够的自由,沿着结果探索意料之外的方向。如果每一步都要等我指定,大部分工作仍然绑在我的注意力上。" -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1241,7 +1249,7 @@ msgid "" msgstr "" "我预期助手会提出错误假设。关键是我们能否验证它们,并从结果中学习。失败的检查应该帮助它理解错误,再次尝试。我仍要判断:累积的证据是否足以支持某个项目里程碑。" -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1253,7 +1261,7 @@ msgstr "" "REA " "让助手能够使用分析工具。调查某函数的调用方时,它可以直接继续检查那个调用方。重建项目提供编译器和自己的对照检查。助手用它们验证提出的源码,看看解释在哪些地方成立。" -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1268,7 +1276,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1284,7 +1292,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1296,7 +1304,7 @@ msgid "" msgstr "" "{ph0}我们正处于这场工业化转变的早期。{ph1}许多基础设施还不成熟。助手推进工作的速度,可能超过原有检查的承受能力,所以流程也要一起发展。共享工具出现缺陷时,要修好它,并重查受影响的结果。下一个项目才能继承更可靠的工具。" -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1308,7 +1316,7 @@ msgstr "任何一段对话都有实际的长度限制。大型重建完成之前 #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1319,7 +1327,7 @@ msgstr "" "{ph0}Touhou Reconstruction " "Factory{ph1}正是为此而建立。它提供一种共用方式,让项目把检查和经验传递下去。一个游戏的工作,可以改善另一个游戏的起点。" -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1327,12 +1335,12 @@ msgid "" "changes how much the next person—or the next agent—can get done." msgstr "这就是工业化比喻对我的意义:经验开始进入别人也能使用的工具。改善工具,就能改变下一个人或下一个助手能完成多少工作。" -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "现在值得尝试的项目" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1340,7 +1348,7 @@ msgid "" "than I could realistically give it. Many projects would stay ideas." msgstr "速度的意义在于,它改变了是否开始一个项目的决定。某个游戏也许很值得逆向,却需要我投入远超现实所能承受的精力。很多项目因此一直停留在想法里。" -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1354,7 +1362,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1362,7 +1370,7 @@ msgid "" "accumulated knowledge would let an agent work on this reliably?{ph1}" msgstr "现在看到一个陌生程序,我会问:{ph0}怎样的工具访问、反馈和知识积累,能让助手可靠地推进这个项目?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1370,12 +1378,12 @@ msgid "" " how far that can take us." msgstr "这个问题让我考虑以前会放弃的项目。每个项目都能改善下一个项目的工作方式。我想继续探索,这能带我们走多远。" -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "项目里程碑与来源" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1407,7 +1415,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1440,7 +1448,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1457,7 +1465,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1480,7 +1488,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1501,7 +1509,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1515,7 +1523,7 @@ msgstr "{ph0}语义重建:{ph1}{ph2}TH08 可读性指南{ph3}和{ph4}Factory #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1534,7 +1542,7 @@ msgstr "{ph0}工业史:{ph1}{ph2}英国科学博物馆集团的蒸汽机示功 #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1546,7 +1554,7 @@ msgstr "{ph0}方法:{ph1}Factory 的{ph2}助手自主性{ph3}与{ph4}跨游戏 #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1564,27 +1572,27 @@ msgid "" "AI agents, and how knowledge compounds across TH08, TH095 and PC-98 TH04." msgstr "N0zoM1z0 回顾从手工逆向到编程助手参与的东方游戏重建,以及经验如何在 TH08、TH095 和 PC-98 TH04 之间积累。" -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "在项目之间传递经验" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "在本页" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "东方游戏重建随笔" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -1593,18 +1601,18 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}首页{ph1}{ph2}/{ph3}恐龙速度实验室" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "检查→重建→更改" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "重建恐龙的速度规则。" @@ -1613,7 +1621,7 @@ msgstr "重建恐龙的速度规则。" #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1624,15 +1632,15 @@ msgstr "" "要重新创建游戏的加速,首先找到控制其速度的规则。 {ph0} REA返回运行脚本;{ph1} 我们用它的规则来构建这个迷你游戏。 " "{ph2}速度可调。{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "在本页" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1640,7 +1648,7 @@ msgstr "{ph0}播放和改变速度{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1648,7 +1656,7 @@ msgstr "{ph0}读取恢复的规则{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1656,18 +1664,18 @@ msgstr "{ph0}检查重建{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}试试分析{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "播放和改变速度" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1675,54 +1683,54 @@ msgid "" "start at 6 and gradually accelerate again." msgstr "按播放,然后跳过仙人掌。 移动速度滑块尝试更慢或更快的游戏;它切换到固定的速度。 选择恢复的规则从6开始,然后再次逐渐加速。" -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "试玩重建版" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "开始" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "跳跃 ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "重新开始" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "速度" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "使用恢复的加速规则" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "原始规则:从6开始,然后向13增加。" -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "移动滑块来设置自己的速度。 空间或跳跃清除仙人掌。" -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "启用JavaScript播放重建。 上面的代码和解释仍然是可读的。" -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "读取脚本REA返回" @@ -1730,7 +1738,7 @@ msgstr "读取脚本REA返回" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1743,7 +1751,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1751,18 +1759,18 @@ msgid "" "update without a collision." msgstr "设置是 {ph0}, {ph1} 和 {ph2}. 游戏在没有碰撞的更新上运行此分支。" -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "在新游戏中使用相同的规则" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "复制" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -1777,18 +1785,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}下载速度规则{ph1} · {ph2}阅读游戏代码{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "检查重建" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -1796,41 +1804,41 @@ msgid "" "recovered rule." msgstr "我们称原来的游戏的更新功能与障碍和自动调度禁用。 将这些记录的速度与恢复规则的重播进行比较。" -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "更新资料" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "原创游戏" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "重建规则" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "运行速度检查" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " "final increment can take speed just above 13." msgstr "四舍五入为三位小数的值。 分支在添加之前进行检查,因此最终增量可以采用略高于13的速度。" -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "自己试试分析" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -1839,14 +1847,14 @@ msgstr "{ph0}设立 REA{ph1} 用你的编程助手。" #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "跟随 {ph0}浏览器连接步骤{ph1},使用 {ph2} 作为页面URL。" -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -1861,7 +1869,7 @@ msgstr "为你的编程助手提供页面URL和本地调试端点,然后复制 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -1873,7 +1881,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1886,7 +1894,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1899,7 +1907,7 @@ msgstr "要求跟进: {ph0}\"跳跃高度在哪里计算? 在新版本中添 #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1922,64 +1930,64 @@ msgid "" "speed and play." msgstr "阅读恐龙游戏的速度规则与REA,重建它,然后改变速度和发挥。" -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "恐龙速度重建" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "恐龙迷你游戏。 使用跳跃按钮或按空格键,而游戏是重点。" -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "复制重建速度规则" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "复制恐龙分析提示" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "跳转到内容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}首页{ph1} / FAQ" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA 常见问题。" -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "安装、更新、分析和故障排查。" -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "主题" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -1987,7 +1995,7 @@ msgstr "{ph0}安装与更新{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -1995,7 +2003,7 @@ msgstr "{ph0}分析{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2003,31 +2011,31 @@ msgstr "{ph0}故障排除{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}数据与分享{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "安装与更新" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "如何安装 REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "终端 · 配置编程助手" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "复制" @@ -2035,7 +2043,7 @@ msgstr "复制" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2047,12 +2055,12 @@ msgstr "" "setup 会注册 REA 的 MCP " "连接,并安装配套的调查技能。完成后重启助手,再提供目标路径和问题。{ph0}查看安装指南{ph1},了解前置条件和第一次分析的步骤。" -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "哪些编程助手能使用 REA?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2066,31 +2074,31 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}连接编程助手{ph1}。" -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "如何更新 REA?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " "npm:" msgstr "REA 更新很频繁,也会持续修复 bug。如果你通过 npm 安装了 CLI:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "终端 · 已安装的 CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2098,14 +2106,14 @@ msgid "" "agent through {ph0}, run:" msgstr "更新后,按照输出中的命令刷新配置。如果之前通过 {ph0} 配置助手,运行:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "终端 · 刷新助手配置" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2116,14 +2124,14 @@ msgstr "" "检查变更后,重启编程助手。REA 的连接配置指定了包版本,重新运行 setup 才会让助手使用新版本。临时执行 CLI 命令时,在 {ph0} " "后面接具体命令即可。" -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "只从 skills.sh 安装技能就够了吗?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2133,24 +2141,24 @@ msgid "" msgstr "" "技能告诉助手如何开展调查。还需要运行 {ph0}REA setup{ph1},连接 MCP 服务器并安装配套技能。随后重启助手,它才能调用工具。" -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "分析" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "REA 可以分析什么?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "根据手里的软件类型选择:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2160,7 +2168,7 @@ msgstr "{ph0}原生可执行文件和库{ph1}:函数、汇编、伪代码和 #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2170,7 +2178,7 @@ msgstr "{ph0}JavaScript 和 Electron 应用{ph1}:模块、导入、IPC 和源 #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2178,7 +2186,7 @@ msgstr "{ph0}浏览器页面{ph1}:脚本、请求和运行时观察。" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2187,12 +2195,12 @@ msgid "" "investigations." msgstr "REA 也提供托管程序集、Android APK、固件和打包资源的分析流程。{ph0}查看案例{ph1},了解完整的调查过程。" -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "需要 Hopper、Ghidra 或 IDA 吗?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2201,7 +2209,7 @@ msgstr "深度原生分析需要其中一个工具。静态 JavaScript 和 .NET #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2212,26 +2220,26 @@ msgstr "" "连接已有的 Ghidra 或 IDA 安装,或让 setup 检测 Hopper " "并提出安装计划。可用的分析后端取决于你的系统和分析目标。{ph0}配置原生分析{ph1}。" -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "不用编程助手,也能用 REA 吗?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " "Electron app:" msgstr "可以。CLI 使用同一套分析流程。对于本地 JavaScript 或 Electron 应用:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "终端 · 静态应用分析" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2240,13 +2248,13 @@ msgid "" msgstr "把路径换成解包后的应用目录或 ASAR 文件。{ph0}查看 CLI 的安装方式{ph1}。" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA 会返回什么代码?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2258,7 +2266,7 @@ msgstr "原生程序分析返回汇编、伪代码、函数调用、引用和相 #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2268,12 +2276,12 @@ msgid "" msgstr "" "助手根据这些结果解释行为,或编写实现并测试。{ph0}DX-Ball 计算规则{ph1}和{ph2}CTF flag 检查器{ph3}展示了这个过程。" -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "应该向助手提什么问题?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2288,7 +2296,7 @@ msgstr "提供一个本地目标,以及一个想调查的行为。比如 JavaS #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2296,7 +2304,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2304,18 +2312,18 @@ msgid "" "native, Electron and browser examples." msgstr "把路径换成自己的目标。{ph0}指南{ph1}提供了原生、Electron 和浏览器示例的 prompt。" -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "故障排除" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "为什么助手看不到 REA 工具?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2323,7 +2331,7 @@ msgid "" " {ph0}; for Codex:" msgstr "安装后重启或重新连接助手。用 {ph0} 检查 REA 注册情况。以 Codex 为例:" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "终端 · 检查一个客户端" @@ -2331,7 +2339,7 @@ msgstr "终端 · 检查一个客户端" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2339,14 +2347,14 @@ msgid "" "shows a missing or stale registration, run setup for that client:" msgstr "把 {ph0} 换成客户端 ID,例如 {ph1} 或 {ph2}。如果报告显示注册缺失或过期,为这个客户端运行 setup:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "终端 · 修复一个客户端的配置" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2355,14 +2363,14 @@ msgid "" "diagnostics{ph1}." msgstr "确认计划后重启客户端。如果注册正常但工具仍未出现,检查客户端的 MCP 连接错误。{ph0}查看更多配置诊断{ph1}。" -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "需要先启动 Hopper 吗?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2373,14 +2381,14 @@ msgstr "" "REA 会在操作需要时启动 Hopper。在 macOS " "上,首次使用时先完成演示模式或许可证激活的选择,再进行无人值守分析。{ph0}查看原生分析配置{ph1}。" -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "遇到 bug 怎么办?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2390,7 +2398,7 @@ msgstr "先{ph0}更新 REA{ph1},重启助手,再试一次相同任务。新 #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2400,24 +2408,24 @@ msgid "" msgstr "" "如果问题仍然存在,{ph0}提交 issue{ph1},附上 REA 版本、操作系统、目标类型、复现步骤和错误输出。涉及原生分析时,也写明分析后端。" -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "数据与分享" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "REA 会上传我的应用吗?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " "its model provider's data policy applies to those results." msgstr "REA 在你的机器上分析目标。助手会收到分析结果,这些结果受其模型服务商的数据政策约束。" -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "如何分享案例或参与贡献?" @@ -2426,7 +2434,7 @@ msgstr "如何分享案例或参与贡献?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2440,7 +2448,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2460,91 +2468,91 @@ msgid "" "coding agents, troubleshooting and sharing examples." msgstr "解答 REA 的常见问题:安装、更新、分析工具、编程助手、故障排查和分享案例。" -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "在本页" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "REA 常见问题" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "复制REA设置命令" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "复制REA更新命令" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "复制编程助手设置刷新命令" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "复制REA CLI分析命令" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "复制示例分析提示" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "复制客户端诊断命令" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "复制作用域设置命令" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "跳转到内容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}首页{ph1} / 第一次调查" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "弄清楚{ph0}导出的笔记写到哪里。" -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" " detail yourself." msgstr "用 REA 检查一个小应用,追踪 Export notes 按钮,再亲自验证一个细节。" -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "在这个练习中" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2552,7 +2560,7 @@ msgstr "{ph0}1. 配置{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2560,7 +2568,7 @@ msgstr "{ph0}2. 询问导出过程{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2568,7 +2576,7 @@ msgstr "{ph0}3. 追踪回答{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2576,13 +2584,13 @@ msgstr "{ph0}4. 检查预测{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. 再问一个问题{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. 把助手连接到 REA" @@ -2595,43 +2603,43 @@ msgstr "1. 把助手连接到 REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "复制" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "或者在终端中运行此命令:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " "connected? Continue below." msgstr "查看计划,确认配置后重启助手。如果已经连接,直接继续。" -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. 问清 CSV 写到哪里" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2642,7 +2650,7 @@ msgstr "" "示例是一个包含六个文件的 Electron 应用,带有{ph0}Export notes(导出笔记){ph1}按钮。助手无需安装或启动 Electron" " 就能检查代码。" -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2652,14 +2660,14 @@ msgstr "助手会下载并解压文件,再把目录交给 REA 检查。" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}下载示例ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2667,12 +2675,12 @@ msgid "" " path to the {ph0} folder and the same export question." msgstr "如果助手不能下载文件,你也可以手动解压。把 {ph0} 文件夹的路径交给它,再问同一个导出问题。" -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. 从回答追踪到代码" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "寻找带文件和行号的简短解释:" @@ -2681,7 +2689,7 @@ msgstr "寻找带文件和行号的简短解释:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2690,19 +2698,19 @@ msgid "" "{ph3}." msgstr "按钮发送 {ph0} 消息。主进程把笔记转换为 CSV,并将 {ph1} 写到用户的下载文件夹。列名为 {ph2} 和 {ph3}。" -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "从按钮到文件写入" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" " read from code." msgstr "REA 的静态分析把消息和处理函数关联起来。导出位置是从代码中读到的。" -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -2711,37 +2719,37 @@ msgstr "文件路径、格式化函数和写入调用都在这个处理函数中 #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}查看完整的代码追踪和记录的 REA 结果{ph1}。" -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. 检查预测" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " "contains a comma or quotation marks?" msgstr "CSV 用逗号分隔各列。如果笔记标题本身包含逗号或引号,会发生什么?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "自己检查一下" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "在解压后的 {ph0} 文件夹里打开终端:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -2750,24 +2758,24 @@ msgstr "" "这条命令需要 Bash、Zsh 等支持 here-document 的 shell。助手也可以在你的系统 shell 中运行同样的 " "JavaScript。" -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. 再问一个问题" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "在同一段对话中继续提问:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "如果文件无法写入,会发生什么?沿着错误处理追踪回页面。" -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -2778,7 +2786,7 @@ msgstr "也可以提供自己的应用,询问其中一个按钮、文件或行 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2790,7 +2798,7 @@ msgstr "{ph0}Notion 如何复制文本和 HTML{ph1}{ph2}追踪打包 Electron #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2802,7 +2810,7 @@ msgstr "{ph0}DX-Ball 如何计算声音左右位置{ph1}{ph2}查看原始指令 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2822,113 +2830,113 @@ msgid "" "go, and check the CSV formatter with a sample title." msgstr "用小型 Notes 应用尝试 REA。配置助手,询问导出的笔记写到哪里,再用一个示例标题验证 CSV 格式化函数。" -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "在本页" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "你的第一次REA调查" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "复制REA安装提示" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "复制安装命令" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "复制笔记调查提示" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "复制CSV检查提示" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "复制格式化程序检查命令" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "跳转到内容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}首页{ph1} / 开始使用" -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "安装与配置 REA。" -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "把 REA 连接到编程助手,或从终端检查本地应用。" -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "打开终端,检查版本:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "终端机" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "复制" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" msgstr "{ph0}Windows(PowerShell){ph1}" #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2939,7 +2947,7 @@ msgstr "如果提示接受条款,输入 Y。关闭 PowerShell,再次打开 #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2949,17 +2957,17 @@ msgstr "" "如果之后运行 {ph2} 时,PowerShell 提示{ph0}“running scripts is disabled on this " "system”{ph1}(系统禁止运行脚本),运行下面的命令一次,再重试:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "如果你使用 Homebrew:" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "其他情况:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "关闭终端,重新打开,然后运行:" @@ -2967,7 +2975,7 @@ msgstr "关闭终端,重新打开,然后运行:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2977,7 +2985,7 @@ msgstr "安装程序需要 {ph0} 和 {ph1}(Debian/Ubuntu 上用 {ph2} 安装 #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2987,7 +2995,7 @@ msgstr "发行版自带的 {ph0} 包经常早于 22.19。如果使用它,请 #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2995,14 +3003,14 @@ msgid "" "{ph0}nodejs.org{ph1}." msgstr "更喜欢普通安装包?从 {ph0}nodejs.org{ph1} 下载 LTS 版。" -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "配置方式" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3010,7 +3018,7 @@ msgstr "{ph0}连接编程助手{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3018,7 +3026,7 @@ msgstr "{ph0}使用CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3026,18 +3034,18 @@ msgstr "{ph0}配置原生分析{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}寻求帮助{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "连接编程助手" -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3047,12 +3055,12 @@ msgstr "" "运行 setup,把 REA 连接到编程助手。可选择 Claude Code、Codex、Cursor、Gemini CLI、Windsurf、Grok" " Build 和其他受支持的 MCP 客户端。Grok Bot 的连接器从聊天中添加。" -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "第一次使用编程助手?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3061,7 +3069,7 @@ msgid "" msgstr "" "编程助手是一种在你的电脑上工作、而不只待在浏览器页面里的 AI 助手。它能读取文件、运行命令,并在修改前征求确认。REA 为它提供逆向工程工具。" -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3071,7 +3079,7 @@ msgstr "如果还没有助手,选择一个,按照其安装页面操作并登 #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3082,7 +3090,7 @@ msgstr "{ph0}{ph1}Claude Code{ph2}{ph3},由 Anthropic 开发,需要付费 Cl #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3093,7 +3101,7 @@ msgstr "{ph0}{ph1}Codex{ph2}{ph3},由 OpenAI 开发,用 ChatGPT 账号登录 #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3101,7 +3109,7 @@ msgid "" "your choice." msgstr "{ph0}{ph1}OpenCode{ph2}{ph3},开源,可以连接你选择的模型服务商。" -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3116,18 +3124,18 @@ msgstr "打开助手,把下面的 prompt 复制进去。助手会运行 REA se #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "也可以自己运行 setup" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "怎么打开终端?" @@ -3136,7 +3144,7 @@ msgstr "怎么打开终端?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3150,7 +3158,7 @@ msgstr "{ph0}Windows:{ph1}打开开始菜单,输入 {ph2}PowerShell{ph3}, #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3162,7 +3170,7 @@ msgstr "{ph0}macOS:{ph1}按 {ph2} {ph3},输入 {ph4}Terminal{ph5},按 Ente #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3175,7 +3183,7 @@ msgstr "{ph0}Linux:{ph1}多数桌面环境可以按 {ph2} {ph3} {ph4}。" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3184,7 +3192,7 @@ msgid "" msgstr "" "用 {ph0} {ph1} 粘贴命令(macOS:{ph2} {ph3};Linux 终端:{ph4} {ph5} {ph6}),再按 Enter。" -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3192,12 +3200,12 @@ msgid "" "configuration. It asks before applying the changes." msgstr "选择客户端,并查看配置计划。REA 会添加 MCP 连接和配套调查技能,同时备份已有配置。确认后才会应用更改。" -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "配置完成后重启客户端。" -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "如何重启客户端?" @@ -3206,7 +3214,7 @@ msgstr "如何重启客户端?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3220,7 +3228,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3228,7 +3236,7 @@ msgid "" " and start it again." msgstr "{ph0}终端助手{ph1}(Claude Code、Codex、Gemini CLI):退出当前会话,再启动一次。" -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3236,7 +3244,7 @@ msgid "" msgstr "给助手目标路径和一个具体问题。比如 JavaScript 或 Electron 应用,可以这样开始:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3244,12 +3252,12 @@ msgid "" " dependencies involved, with the source locations for your findings." msgstr "检查 {ph0},找出它如何导出数据。展示涉及的入口点、函数调用和依赖,并给出分析结果对应的源码位置。" -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "把路径换成自己的本地目标。" -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "怎么取得文件夹的完整路径?" @@ -3258,7 +3266,7 @@ msgstr "怎么取得文件夹的完整路径?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3272,7 +3280,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3282,7 +3290,7 @@ msgstr "{ph0}macOS:{ph1}在 Finder 中右键文件夹,按住 Option,选择 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3290,31 +3298,31 @@ msgid "" "appears." msgstr "{ph0}所有系统:{ph1}把文件夹拖进终端窗口,也能显示路径。" -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "在终端里,包含空格的路径需要加引号。" -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "使用CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " "running the app:" msgstr "静态分析 JavaScript 或 Electron 应用目录、ASAR 文件,无需启动应用:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "静态应用分析" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3322,13 +3330,13 @@ msgid "" "Windows, a path such as {ph1} works here." msgstr "把路径换成解包后的应用目录或 {ph0} 文件。Windows 上也可以使用 {ph1} 这样的路径。" -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "在哪里找到应用的 .asar 文件?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3339,7 +3347,7 @@ msgstr "Electron 应用通常把它放在 {ph0} 文件夹中:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3351,7 +3359,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3362,20 +3370,20 @@ msgstr "{ph0}macOS:{ph1}{ph2}(右键应用,选择{ph3}“显示包内容 #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0}Linux:{ph1}通常位于 {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "有些应用安装在其他位置。在应用目录里搜索 {ph0}。" -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3384,43 +3392,43 @@ msgid "" msgstr "结果会识别应用,展示模块之间的关系,并给出源码位置。REA 无法解析的关系会在结果中注明。" #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "如果希望在 shell 中直接使用 {ph0} 命令:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "安装CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}继续看 JavaScript 应用指南{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "配置原生分析" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " "then give REA your executable or library." msgstr "原生二进制需要本地分析工具。在下面选择并配置一个工具,再提供可执行文件或库。" -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "选择工具:Ghidra、Hopper 或 IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3430,17 +3438,17 @@ msgstr "" "在 Linux 或 macOS 的 x64、arm64 上,使用已有的 Ghidra 12.1.x 和 64 位 JDK 21 或更新版本。Ghidra" " 需要对应主机架构的原生反编译器。运行 setup 前先设置路径:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "连接已有的 Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra 连接 · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3450,12 +3458,12 @@ msgstr "" "把两个路径换成自己的安装位置。setup 会检查路径,并为选定客户端保存有效配置。Linux arm64 上可能需要另行构建 Ghidra " "原生反编译器。" -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "在 Windows 上连接 Ghidra" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3465,32 +3473,32 @@ msgstr "" "Windows x64 提供实验性的只读支持:分析固定本地 NTFS 驱动器上的原生 x86、x64 PE 应用和 DLL。使用已有的 Ghidra " "12.1.x 和 64 位 JDK 21 或更新版本:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra 连接 · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "把两个路径换成安装位置,再查看 setup 计划。" -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" " existing installation or offers an installation plan for your approval." msgstr "在 macOS 或 Linux 上连接 Hopper。运行上面的 setup 命令,它会检测已有安装,或提出安装计划供你确认。" -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " "activation before an unattended analysis." msgstr "在 macOS 上,首次使用 Hopper 时先完成演示模式或许可证激活的选择,再做无人值守分析。" -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3500,7 +3508,7 @@ msgstr "" "已验证的 IDA 配置使用 Windows,连接已有的 MCP 注册,可附加到 GUI,也可使用无界面数据库。Linux 和 macOS " "的无界面分析仍未验证。" -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "连接已有的 IDA MCP 注册" @@ -3510,7 +3518,7 @@ msgstr "连接已有的 IDA MCP 注册" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3521,13 +3529,13 @@ msgstr "" "把上游服务器可用的 {ph0}、{ph1} 和可选的 {ph2} 保存在 JSON 文件中。已有的 {ph3} 对象中包含 {ph4} 条目也可以。运行" " setup 前让 REA 指向这个文件:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA 连接 · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3543,7 +3551,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3554,29 +3562,29 @@ msgstr "" "给 REA 原始可执行文件的路径,在 CLI 查询中加入 {ph0}。使用编程助手时,把 {ph1} 加入 REA 注册的环境配置,并在打开二进制时选择" " IDA。" -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "已配置 Ghidra 时,可以这样检查函数:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "函数分析" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "把 {ph0} 换成要检查的函数名或地址。" -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "原生分析会话如何工作" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3586,7 +3594,7 @@ msgstr "每条 CLI 命令导入并分析二进制文件,完成后关闭会话 #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3594,18 +3602,18 @@ msgid "" "leads to a recovered calculation." msgstr "{ph0}跟着原生分析示例{ph1},看看函数结果如何帮助还原计算规则。" -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "寻求帮助" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "助手看不到 REA 工具时" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3613,27 +3621,27 @@ msgid "" "{ph0}; for Codex:" msgstr "配置后重启或重新连接客户端。用 {ph0} 检查 REA 连接。以 Codex 为例:" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "检查一个客户端" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "分析后端出现问题时" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "检查正在使用的分析后端。以 Ghidra 为例:" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "检查一个分析后端" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "报告会列出失败的检查和建议的下一步。" @@ -3642,7 +3650,7 @@ msgstr "报告会列出失败的检查和建议的下一步。" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3653,7 +3661,7 @@ msgstr "{ph0}REA FAQ{ph1}{ph2}关于更新、助手和分析的常见解答。{p #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3665,7 +3673,7 @@ msgstr "{ph0}选择调查指南{ph1}{ph2}二进制、Electron 应用和浏览器 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3677,7 +3685,7 @@ msgstr "{ph0}GitHub issues{ph1}{ph2}附上命令与诊断结果,反馈问题 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3697,112 +3705,112 @@ msgid "" "app from the terminal. Setup, first questions and native provider guides." msgstr "把 REA 连接到编程助手,或用终端检查本地 JavaScript、Electron 应用。包含配置、首次提问和原生分析后端指南。" -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "复制Node.js版本检查" -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "复制Node.js的Windows安装命令" -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "复制PowerShell执行策略命令" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "复制 Homebrew Node.js 安装命令" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "复制macOS的fnm安装命令" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "复制 Node.js 24命令 macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "复制Linux的fnm安装命令" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "复制 Node.js 24命令 Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "在本页" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA入门指南" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "复制REA安装提示" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "复制编程助手设置命令" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "复制JavaScript分析命令" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "复制CLI安装命令" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "复制 macOS 和 Linux 的 Ghidra 连接命令" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "复制 Ghidra 连接 Windows PowerShell的" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "复制 IDA 连接 Windows PowerShell的" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "复制原生函数分析命令" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "复制客户端诊断命令" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "复制提供者诊断命令" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -3811,34 +3819,34 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}首页{ph1} / {ph2}指南{ph3} /浏览器观察" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "看看会发生什么{ph0}当你点击。" -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " "JavaScript that builds a download." msgstr "使用小型浏览器应用程序连接操作,其网络请求和构建下载的JavaScript。" -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "在本指南中" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -3846,7 +3854,7 @@ msgstr "{ph0}例子{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -3854,7 +3862,7 @@ msgstr "{ph0}打开浏览器{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -3862,7 +3870,7 @@ msgstr "{ph0}问问你的编程助手{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -3870,13 +3878,13 @@ msgstr "{ph0}从CLI捕获 {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}阅读请求和脚本{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "单击导出时会发生什么?" @@ -3886,7 +3894,7 @@ msgstr "单击导出时会发生什么?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3897,7 +3905,7 @@ msgstr "" "{ph0}Notes 浏览器示例{ph1}有一个{ph2}Export notes(导出笔记){ph3}按钮。点击后加载 {ph4},把两条笔记格式化为" " CSV,再开始下载。" -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "从点击到CSV下载" @@ -3908,7 +3916,7 @@ msgstr "从点击到CSV下载" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3922,7 +3930,7 @@ msgstr "{ph0}01 · 你{ph1}{ph2}点击 Export notes{ph3}{ph4}在捕获进行时 #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3938,7 +3946,7 @@ msgstr "{ph0}02*REA {ph1}{ph2}记录请求{ph3}{ph4}从所选页面捕获请求U #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3947,52 +3955,52 @@ msgid "" msgstr "" "{ph0}03 · 编程助手{ph1}{ph2}读取导出代码{ph3}{ph4}把观察到的请求与 {ph6} 中的 {ph5} 关联起来。{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "在单击导出注释之前开始捕获。" -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "使用远程调试打开Chrome" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " "debugging port. On Linux:" msgstr "用独立的浏览器配置和本地调试端口打开在线 Notes 示例。Linux 上:" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "启动示例浏览器" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "复制" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " "replace the page URL with another page you want to inspect." msgstr "在macOS或Windows上使用已安装的浏览器的可执行路径。 你可以将页面URL替换为要检查的其他页面。" -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" " the action, and close the browser when finished." msgstr "REA连接到这个现有的浏览器。 你可以控制页面,执行操作,并在完成后关闭浏览器。" -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "让你的编程助手看一个动作" @@ -4005,7 +4013,7 @@ msgstr "让你的编程助手看一个动作" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4017,7 +4025,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4028,7 +4036,7 @@ msgstr "" "是怎样生成的?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4036,7 +4044,7 @@ msgid "" "URL. Let it start the capture before you click." msgstr "示例 prompt。把调试地址 {ph0} 和页面网址交给助手。等它开始捕获,再点击按钮。" -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4044,23 +4052,23 @@ msgid "" "export." msgstr "你的编程助手发现页面目标,启动观察窗口,并读取生成的证据。 然后,它可以检查导出后面的脚本。" -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "或从终端捕获" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "查找页面的目标ID:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "查找页面" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4068,14 +4076,14 @@ msgid "" "ID, then run:" msgstr "选择网址为 Notes 示例的目标,把下面的 {ph0} 换成目标 ID,再运行:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "捕捉接下来的十秒" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4083,7 +4091,7 @@ msgid "" " in that browser. The result arrives after the observation window ends." msgstr "让命令连接几秒钟,再在浏览器中点击{ph0}Export notes{ph1}。观察时间窗口结束后会返回结果。" -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4091,49 +4099,49 @@ msgid "" "this capture." msgstr "捕获的结果包括所选页面、该窗口期间的网络活动以及JSON响应的形状。 较早的请求在此捕获之外。" -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "读取请求和导出脚本" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "在本地笔记示例中用REA4.1.0记录" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "捕获的事实" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "数值" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "请求" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "回应" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "请求发起者" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} · 脚本" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "响应结构" @@ -4141,19 +4149,19 @@ msgstr "响应结构" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} 与 {ph1} 和 {ph2} 字段" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "阅读加载的脚本" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4162,7 +4170,7 @@ msgid "" msgstr "请求指出了数据来源,REA 记录的请求发起方是 {ph0}。读取捕获的脚本源码,看看它如何使用数据:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4172,7 +4180,7 @@ msgid "" msgstr "下载是使用JSON响应在页面中构建的。 CSV格式化步骤来自脚本;网络捕获建立此单击请求 {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4182,7 +4190,7 @@ msgstr "查找请求的脚本 {ph0}. 它如何转义包含逗号或引号的标 #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4202,161 +4210,161 @@ msgid "" "inspect the request and follow the export script." msgstr "观察一个笔记导出与 REA:选择浏览器页面,捕获单击,检查请求并遵循导出脚本。" -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "在本页" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "浏览器观察" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "复制启动示例浏览器" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "复制示例提示" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "复制查找页面" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "复制捕获接下来的十秒钟" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "复制读取加载的脚本" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "跳转到内容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}首页{ph1} /指南" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA 分析指南。" -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " "guide includes a prompt, code and results." msgstr "分析本机函数、Electron导出或浏览器请求。 每个指南包括提示,代码和结果。" -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "第一次调查" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "设置REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "连接你的编程助手或使用 REA 从终端。" -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "开始使用 REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "原生二进制" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "恢复左/右声音位置的计算" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," " read numeric constants and check the recovered C." msgstr "从Windows游戏可执行文件开始。 检查指令,跟随调用者,读取数字常量并检查恢复的C。" -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "原生分析指南" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "追踪 CSV 导出" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " "process. Use REA to connect the API, IPC channel and file writer." msgstr "一个小Notes应用程序在渲染器,预加载和主进程中传播一个功能。 使用REA连接API,IPC通道和文件编写器。" -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript&Electron指南" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "对于更大的打包应用程序,请遵循 {ph0} Notion的剪贴板桥{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "浏览器行为" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "观察点击" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " "that turns its response into a download." msgstr "打开工作笔记示例,捕获导出请求并找到将其响应转换为下载的代码。" -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "浏览器观察指南" @@ -4373,12 +4381,12 @@ msgid "" "CSV export and a browser request." msgstr "通过简短的示例学习REA:本机计算,Electron CSV导出和浏览器请求。" -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -4387,34 +4395,34 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}首页{ph1} / {ph2}指南{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "追踪安 Electron{ph0}CSV 导出。" -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " "file writer." msgstr "按照一个按钮点击从页面API,通过Electron IPC,到CSV文件编写器。" -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "在本指南中" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4422,7 +4430,7 @@ msgstr "{ph0}例子{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4430,7 +4438,7 @@ msgstr "{ph0}问问你的编程助手{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4438,7 +4446,7 @@ msgstr "{ph0}跟踪导出代码{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4446,20 +4454,20 @@ msgstr "{ph0}试试这个例子{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}检查CSV写入器{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"Export notes(导出笔记)\"去哪儿了?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4470,7 +4478,7 @@ msgstr "" "本指南使用一个小型 Electron 应用。点击{ph0}Export notes(导出笔记){ph1}后,页面调用 " "API,通过进程边界进入主进程,最后写出 CSV。这个行为分散在几个文件中。" -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "该 CSV 跨导出 Electron 过程" @@ -4484,7 +4492,7 @@ msgstr "该 CSV 跨导出 Electron 过程" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4499,7 +4507,7 @@ msgstr "{ph0}渲染器→预加载{ph1}{ph2}{ph3}{ph4}{ph5}{ph6} 调用由 {ph7} #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4514,7 +4522,7 @@ msgstr "{ph0}进程之间{ph1}{ph2}{ph3}{ph4}{ph5}预加载调用IPC通道:主 #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4525,13 +4533,13 @@ msgstr "{ph0}主进程{ph1}{ph2}导出处理函数{ph3}{ph4}{ph5}处理这个通 #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} 格式化注释→ {ph1} 写道 {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -4539,14 +4547,14 @@ msgid "" "executes." msgstr "REA将字面IPC调用与其处理程序相匹配,并标识公开的API。 路径是从代码中推断出来的;运行时捕获可以检查执行的内容。" -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "询问有关 CSV 导出" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4562,14 +4570,14 @@ msgstr "{ph0}将你的编程助手连接到 REA{ph1} 并给它的应用程序目 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "复制" @@ -4580,7 +4588,7 @@ msgstr "复制" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4589,7 +4597,7 @@ msgid "" msgstr "{ph0}›{ph1}{ph2}用 REA 找出这个应用导出笔记时发生了什么。CSV 文件在哪里创建?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4597,7 +4605,7 @@ msgid "" "{ph0}." msgstr "示例提示。 包括应用程序文件夹的绝对路径或 {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -4605,17 +4613,17 @@ msgid "" " the export feature." msgstr "REA读取应用程序文件并构建入口点,模块和流程边界的映射。 你的编程助手使用该映射将调查范围缩小到导出功能。" -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "跟踪导出代码" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "页面调用一个小API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -4624,7 +4632,7 @@ msgstr "页面知道方法名称。 实现存在于预加载中,预加载将 #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4634,7 +4642,7 @@ msgstr "REA 记录 {ph0} 和直接写在代码中的通道名 {ph1},并将调 #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4642,14 +4650,14 @@ msgid "" "and the main process writes {ph1} into the user's Downloads folder." msgstr "读取处理函数就能回答最初的问题:{ph0} 格式化笔记,主进程将 {ph1} 写入用户的下载文件夹。" -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " "accompany the API, channel and handler findings." msgstr "使用 REA 4.1.0 分析下面可下载的示例。API、通道和处理函数的结果均附有源码位置。" -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "自己分析例子" @@ -4657,25 +4665,25 @@ msgstr "自己分析例子" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}下载示例ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "浏览六个源文件" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "静态应用分析" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4683,7 +4691,7 @@ msgid "" "channel and one matching handler in {ph0}. Source locations are in {ph1}." msgstr "将路径替换为你解压缩的文件夹。 你应该在以下位置找到一个IPC通道和一个匹配的处理程序 {ph0}. 源位置在 {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -4692,13 +4700,13 @@ msgid "" msgstr "" "对于你自己的应用程序,请对其目录或ASARpath使用相同的命令。 编程助手可以使用REA的功能跟踪工具跟随文字字符串,API名称或IPC通道。" -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "检查CSV写入器" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4706,7 +4714,7 @@ msgid "" "happens if writing the file fails?" msgstr "追踪 {ph0} 到处理函数。哪些输入传给 CSV 写入函数?如果写入失败,会怎样?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -4718,7 +4726,7 @@ msgstr "使用源位置检查这些详细信息。 计算的通道名称和不 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4730,7 +4738,7 @@ msgstr "{ph0}追踪 Notion 剪贴板桥接代码{ph1}{ph2}把同样的方法用 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4742,7 +4750,7 @@ msgstr "{ph0}观察浏览器导出{ph1}{ph2}捕获一个真正的点击,看看 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4763,32 +4771,32 @@ msgid "" "result." msgstr "通过具有REA的渲染器API,预加载和IPC处理程序跟踪Notes CSV导出。 包括可下载的示例文件和经过验证的分析结果。" -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "在本页" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "复制示例提示" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "复制静态应用程序分析" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -4797,34 +4805,34 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}首页{ph1} / {ph2}指南{ph3} /原生分析" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "恢复DX-Ball的{ph0}左/右声音位置的计算。" -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " "check the recovered C." msgstr "检查原始指令,识别输入和常量,然后检查恢复的C。" -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "在本指南中" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -4832,7 +4840,7 @@ msgstr "{ph0}例子{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4840,7 +4848,7 @@ msgstr "{ph0}问问你的编程助手{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -4848,7 +4856,7 @@ msgstr "{ph0}阅读REA结果{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -4856,18 +4864,18 @@ msgstr "{ph0}恢复和检查{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}使用你自己的二进制文件{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "计算左/右立体声声音定位" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -4876,7 +4884,7 @@ msgstr "在DX-Ball中,砖击提供水平屏幕位置。 声音代码将其转 #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4885,7 +4893,7 @@ msgid "" " way to investigate the missing arithmetic." msgstr "启动函数, {ph0},有一个简短的反编译器结果:调用 {ph1}. REA 还返回其指令和调用者,这给编程助手一种方法来调查丢失的算术。" -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "新的这些条款?" @@ -4894,7 +4902,7 @@ msgstr "新的这些条款?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4904,7 +4912,7 @@ msgstr "{ph0}指令:{ph1}处理器执行的步骤,以 {ph2}、{ph3} 这样 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4914,7 +4922,7 @@ msgstr "{ph0}反编译器结果/伪代码:{ph1} 分析工具试图将指令转 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4925,7 +4933,7 @@ msgstr "{ph0}调用方:{ph1}调用当前函数的函数,可以看出传入 #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4935,7 +4943,7 @@ msgstr "{ph0}地址:{ph1} 程序中的一个位置,用十六进制编写,如 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4943,7 +4951,7 @@ msgid "" "and decoded." msgstr "{ph0}常量:{ph1} 固定数字存储在程序中,读取为原始字节和解码。" -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "三件证据,一个计算" @@ -4954,7 +4962,7 @@ msgstr "三件证据,一个计算" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4969,7 +4977,7 @@ msgstr "{ph0}01 · 指令{ph1}{ph2}整数输入{ph3}{ph4}从栈读取一个值 #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4985,7 +4993,7 @@ msgstr "{ph0}02 · 调用方{ph1}{ph2}屏幕坐标{ph3}{ph4}砖块碰撞处理 #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4994,14 +5002,14 @@ msgid "" msgstr "" "{ph0}03 · 数据字节{ph1}{ph2}数值常量{ph3}{ph4}引用的字节解码为 {ph5}、{ph6} 和一个缩放系数。{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " "interprets them together." msgstr "REA提供指令,调用关系和字节。 编程助手一起解释它们。" -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "询问行为" @@ -5010,7 +5018,7 @@ msgstr "询问行为" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5018,19 +5026,19 @@ msgid "" "analysis tool{ph3}, provide the local executable and a question:" msgstr "{ph0}将 REA 连接到助手{ph1}并{ph2}配置原生分析工具{ph3}后,提供本地可执行文件和一个问题:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "我应该使用哪种分析工具?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA需要其中一个来阅读原生程序:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5043,7 +5051,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5055,7 +5063,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5064,7 +5072,7 @@ msgstr "{ph0} IDA {ph1} (Windows):用于具有MCP注册的现有IDA设置。" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5078,14 +5086,14 @@ msgstr "见 {ph0}设置原生分析{ph1} 为步骤。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "复制" @@ -5096,7 +5104,7 @@ msgstr "复制" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5105,7 +5113,7 @@ msgid "" msgstr "" "{ph0}›{ph1}{ph2}用 REA 找出 DX-Ball 如何计算声音的左右位置。解释计算过程,并展示代码。{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5115,7 +5123,7 @@ msgstr "" "示例 prompt。把本地 DX-Ball 1.07 可执行文件的路径交给助手。REA 不附带游戏,需要用自己的副本,也可以换成手里的其他小型 " "Windows 程序,问同类问题。" -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "如何获取文件的完整路径?" @@ -5124,7 +5132,7 @@ msgstr "如何获取文件的完整路径?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5138,7 +5146,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5148,7 +5156,7 @@ msgstr "{ph0} macOS :{ph1} 在Finder中,右键单击文件,按住选项并 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5156,30 +5164,30 @@ msgid "" "appears." msgstr "{ph0}任何系统:{ph1} 将文件拖到终端窗口中并显示其路径。" -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "阅读REA结果" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "阅读输入" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " "arithmetic. This is the input absent from the first pseudocode view." msgstr "指令加载一个整数参数并将其转换为浮点算术。 这是第一个伪代码视图中没有的输入。" -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "跟随调用方" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5187,24 +5195,24 @@ msgid "" "tile coordinate by 30; adding {ph0} (20) gives the brick's screen position." msgstr "REA 找到砖块碰撞处理函数。它先把砖块横坐标乘以 30,再加上 {ph0}(20),得到砖块的屏幕位置。" -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "读取引用的常量" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " "actual values; the instruction order tells the agent how they are used." msgstr "算术引用这些地址。 读取字节提供实际值;指令顺序告诉编程助手如何使用它们。" -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "写入并检查恢复的函数" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5212,7 +5220,7 @@ msgid "" "the center of the stereo field." msgstr "比例为1.0时,屏幕位置0、320和640在整数转换之前映射到-500、0和500。 计算将屏幕的中心置于立体场的中心。" -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5222,20 +5230,20 @@ msgstr "编程助手使用REA的发现来编写C.单独的检查将3,205个输 #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}查看完整的调查和组装到C的比较{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "用你自己的二进制文件试试" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5247,20 +5255,20 @@ msgstr "" "{ph0}连接原生分析提供程序{ph1},然后给你的编程助手一个本地可执行文件或库和一个要调查的函数。 " "有用的起始问题包括\"如何解析此文件?\"或\"哪个函数处理此菜单操作?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " "terminal. For a configured Ghidra installation:" msgstr "如果你已经知道函数名称或地址,则可以从终端查询它。 对于已配置的Ghidra安装:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "函数分析" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5272,7 +5280,7 @@ msgstr "" "替换目标路径和 {ph0} 使用你自己的函数名称或地址。 每个 CLI 调用导入并分析二进制文件,然后关闭其会话。 你的编程助手 MCP " "查询在该会话打开时重用导入的二进制文件。" -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5291,50 +5299,50 @@ msgid "" "caller, read constants and check reconstructed C." msgstr "使用REA恢复本机计算:检查指令,遵循调用者,读取常量并检查重构的C。" -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "在本页" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "机器代码程序分析" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "复制示例提示" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "复制函数分析" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "跳转到内容" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "在本页" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "安装与配置 REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5342,7 +5350,7 @@ msgstr "{ph0}安装与配置 REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5350,7 +5358,7 @@ msgstr "{ph0}什么是RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5358,7 +5366,7 @@ msgstr "{ph0}REA 如何帮忙{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5366,7 +5374,7 @@ msgstr "{ph0}恐龙游戏{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5374,7 +5382,7 @@ msgstr "{ph0}计算器{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5382,7 +5390,7 @@ msgstr "{ph0}试试REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5390,7 +5398,7 @@ msgstr "{ph0}更深入{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5398,25 +5406,25 @@ msgstr "{ph0}帮助和反馈{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}社区{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "和编程助手一起做逆向工程" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "弄清楚{ph0}软件如何工作。" -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5425,7 +5433,7 @@ msgstr "REA 为编程助手提供分析工具,让它检查程序并解释程 #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5433,13 +5441,13 @@ msgstr "已经了解逆向工程?{ph0}直接看分析指南 →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "想深入了解?{ph0}阅读博客 →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "把这段话复制给编程助手:" @@ -5452,38 +5460,38 @@ msgstr "把这段话复制给编程助手:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "复制" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "也可以在终端运行:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "确认安装计划后,重启编程助手。" -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "什么是逆向工程?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5496,7 +5504,7 @@ msgstr "通过{ph0}检查程序本身{ph1},弄清软件如何工作。" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5506,7 +5514,7 @@ msgstr "目标是理解一项功能,从而能{ph0}解释它{ph1}、{ph2}修改 #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -5514,7 +5522,7 @@ msgstr "使用 REA 之前 · 你要{ph0}亲自调查{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -5522,7 +5530,7 @@ msgstr "{ph0}01{ph1} 分析分支" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -5530,7 +5538,7 @@ msgstr "{ph0}02{ph1} 追踪函数调用" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -5540,20 +5548,20 @@ msgstr "{ph0}03{ph1} 还原计算规则" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}原始 x64 指令节选{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 · 走哪个分支?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5561,29 +5569,29 @@ msgid "" "these?”" msgstr "“{ph0}0x5b?0x5c?{ph1}两个跳转去了同一个位置。它们对应哪些运算符?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "查找命令 ID,再标明分支含义。" -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "除÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "乘×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · 这些函数调用做什么?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5591,24 +5599,24 @@ msgid "" "value goes in?{ph1}”" msgstr "“100 很明确,但函数调用只有地址。{ph0}哪个负责除法?传进去的是哪个值?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "检查辅助函数,追踪存储的数值。" -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "除法" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 · 规则是什么?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5616,19 +5624,19 @@ msgid "" "after +.”" msgstr "“这个分支乘上了另一个输入。所以在 + 之后,{ph0}10% 表示 200 的 10%{ph1}。”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "确定操作数的含义,并检查两条运算路径。" -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "专家思考过程示意" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5638,20 +5646,20 @@ msgstr "{ph0}你需要读懂指令、追踪调用,再还原计算过程。{ph1 #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "使用 REA · 你只需问{ph0}编程助手{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "一句话即可。" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -5665,49 +5673,49 @@ msgstr "{ph0}用日常语言{ph1}告诉助手你的问题。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 计算器" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "示例回答 · 根据分析结果" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "在 + 之后,% 按钮计算的是{ph0}第一个数的百分比。{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA 提供" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "处理函数的指令、反编译代码和调用关系。" -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "编程助手解释" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "走哪个分支、怎样计算,以及如何重新实现。" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5717,7 +5725,7 @@ msgstr "汇编节选自已安装的计算器 DLL。思考过程和回答用于 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5725,37 +5733,37 @@ msgid "" "Calculator and rebuild its % button." msgstr "{ph0}来试两个例子。{ph1}先调整游戏速度,再回到计算器,重新实现 % 按钮。" -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "示例 01 · Chrome 小恐龙游戏" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "为什么恐龙变得更快?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "目标" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "重建一个{ph0}速度可调{ph1}的游戏。" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "为什么逆向工程?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5763,61 +5771,61 @@ msgid "" "game{ph1}: how fast it starts, how much it increases and when it stops." msgstr "要复现加速过程,得先找到{ph0}实际运行的游戏中的规则{ph1}:起始速度是多少、每次增加多少、何时停止加速。" -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "试玩重建版" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "开始" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "跳跃 ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "重新开始" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "速度" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "使用还原的加速规则" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "原版规则:速度从 6 开始,逐渐增加到 13。" -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "拖动滑块,选择自己的速度。按空格键或“跳跃”越过仙人掌。" -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "启用 JavaScript 即可试玩。上面的代码和说明无需 JavaScript 也能阅读。" -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA 返回" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5833,7 +5841,7 @@ msgstr "{ph0}页面实际运行的脚本。{ph1}助手读取更新函数和速 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -5845,7 +5853,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 小恐龙游戏 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5858,7 +5866,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -5870,7 +5878,7 @@ msgstr "分析目标:{ph0}wayou 基于 Chromium 制作的浏览器版本{ph1} #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5878,12 +5886,12 @@ msgid "" "while speed is below {ph4}13{ph5}." msgstr "{ph0}起始速度为 6。{ph1}速度低于 {ph4}13{ph5} 时,每次没有发生碰撞的更新增加 {ph2}0.001{ph3}。" -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "打开速度实验室 →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "各部分负责什么" @@ -5894,7 +5902,7 @@ msgstr "各部分负责什么" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5908,7 +5916,7 @@ msgstr "{ph0}01 · REA{ph1}{ph2}读取正在运行的游戏脚本{ph3}{ph4}把 #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5922,7 +5930,7 @@ msgstr "{ph0}02 · 编程助手{ph1}{ph2}重建规则,加入控制{ph3}{ph4} #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5930,13 +5938,13 @@ msgid "" "acceleration, then choose your own pace.{ph5}" msgstr "{ph0}03 · 你{ph1}{ph2}调整速度,亲自试玩{ph3}{ph4}先体验原版加速,再选择自己的节奏。{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "查看脚本、验证过程和分析步骤" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5944,7 +5952,7 @@ msgid "" "and returned the loaded {ph0}, including its source and digest." msgstr "REA 通过本地调试连接检查 HTTP 浏览器版本,返回了已加载的 {ph0},包含源码和摘要。" -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -5956,7 +5964,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5969,7 +5977,7 @@ msgstr "新小游戏保留了这条速度规则。绘图、跳跃和碰撞代码 #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5984,26 +5992,26 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" "{ph0}Inspected speed code{ph1} · {ph2}Chromium Authors · BSD license{ph3}" msgstr "{ph0}分析的速度代码{ph1} · {ph2}Chromium Authors · BSD 许可证{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "示例 02 · Windows 计算器" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "重新实现计算器的 % 按钮。" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6012,7 +6020,7 @@ msgstr "做一个小计算器,能{ph0}正确处理 + 和 × 两种情况。{ph #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6020,29 +6028,29 @@ msgid "" " installed app to find which number the percentage is applied to." msgstr "同一个按钮,在{ph0}+ 和 × 后采用不同规则。{ph1}我们检查已安装的应用,弄清百分比究竟作用于哪个数。" -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "试试计算" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "重置" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "200的10%=20. 则200+20=220。" -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "根据实际分析得到的百分比规则制作的交互示例。" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6052,7 +6060,7 @@ msgstr "{ph0}一个分支除以 100;另一个还要乘上第一个数。{ph1} #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6066,7 +6074,7 @@ msgstr "对于这个例子, {ph0} 和 {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6080,7 +6088,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 重建 % 按钮 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6091,7 +6099,7 @@ msgstr "" "{ph0}›{ph1}{ph2}用 REA 检查 Windows 计算器的 % 按钮。还原 + 和 × " "后的规则,再做一个同时采用这两条规则的小计算器。{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "在 + 之后" @@ -6099,13 +6107,13 @@ msgstr "在 + 之后" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}取第一个数字的10%。{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "在 × 之后" @@ -6113,13 +6121,13 @@ msgstr "在 × 之后" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}把10%变成0.1。{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "从已安装的应用,到能运行的 % 按钮" @@ -6131,7 +6139,7 @@ msgstr "从已安装的应用,到能运行的 % 按钮" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6147,7 +6155,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6158,12 +6166,12 @@ msgstr "" "{ph0}03 · 编程助手解释{ph1}{ph2}解释并复现规则{ph3}{ph4}对照 Microsoft 的源码核实分支,再试试上面的 + 和 " "×。{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "查看实际代码和验证方式" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6183,7 +6191,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6191,29 +6199,29 @@ msgid "" "{ph4}Native setup guide{ph5}" msgstr "{ph0}百分比实现{ph1} · {ph2}Microsoft 测试用例{ph3} · {ph4}原生分析配置指南{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "第一次调查" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "用一个小应用试试 REA。" -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " "input." msgstr "下载 Notes 示例,追踪 CSV 导出,再修改一个输入来验证。" -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "跟着示例开始" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "想更深入吗?" @@ -6222,7 +6230,7 @@ msgstr "想更深入吗?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6240,13 +6248,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 网站" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "对,就是这个网站。" @@ -6259,7 +6267,7 @@ msgstr "对,就是这个网站。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6272,7 +6280,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 游戏重建" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6284,69 +6292,69 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}查看 DX-Ball 案例 →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "根据目标选择配置和分析指南:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "原生二进制" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" " and libraries." msgstr "检查可执行文件和库中的函数、字符串、引用和函数调用关系。" -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "原生分析指南" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " "or ASAR archive." msgstr "从应用目录或 ASAR 文件中分析模块、路由、IPC 和原生依赖。" -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "应用分析流程" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "浏览器与运行时活动" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " "across runs." msgstr "记录指定的浏览器或进程活动,再比较不同运行的结果。" -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "浏览器观察指南" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "有什么问题吗?" @@ -6357,7 +6365,7 @@ msgstr "有什么问题吗?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6367,12 +6375,12 @@ msgstr "" "{ph0}阅读 FAQ{ph1}、{ph2}在 Discord 和我们聊聊{ph3},或{ph4}提交 GitHub issue{ph5}反馈 bug " "和功能需求。" -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "加入社区" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -6391,64 +6399,64 @@ msgid "" " Follow clear guides and try interactive examples with REA." msgstr "和编程助手一起分析应用、二进制文件和浏览器行为。跟着清晰的指南,体验 REA 的交互示例。" -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "复制REA安装提示" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "复制安装命令" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "按照手动计算器分析" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "复制计算器百分比问题" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "小恐龙游戏。点击“跳跃”,或在游戏获得焦点后按空格键。" -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "复制恐龙分析提示" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "选择计算" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "复制计算器分析提示" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "复制网站项目提示" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "复制游戏重建提示" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -6457,43 +6465,43 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}首页{ph1} / {ph2}案例展示{ph3} /安卓" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "案例研究 · Aegis验证器" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "身份验证器如何{ph0}生成登录代码?" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " "in an Android APK, then rebuild it with a clock you can control." msgstr "六位验证码每 30 秒变化一次。用 REA 在 Android APK 中找出计算方法,再重建一个可调节时钟的演示。" -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 · Android · 正式发布 APK ·6.9MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "在GitHub上查看Aegis" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "从 APK 还原可复现的验证码" @@ -6505,7 +6513,7 @@ msgstr "从 APK 还原可复现的验证码" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6523,7 +6531,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6541,7 +6549,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6551,14 +6559,14 @@ msgid "" msgstr "" "{ph0}03 · 重建并验证{ph1}{ph2}调整时钟,查看验证码。{ph3}{ph4}新的浏览器演示复现规则,再用公开对照用例检查。{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "在本个案研究中" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -6566,7 +6574,7 @@ msgstr "{ph0}问问你的编程助手{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -6574,7 +6582,7 @@ msgstr "{ph0}试试代码生成器{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -6582,7 +6590,7 @@ msgstr "{ph0}用REA查找代码 {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -6590,7 +6598,7 @@ msgstr "{ph0}阅读计算{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -6598,20 +6606,20 @@ msgstr "{ph0}检查重建{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}亲自检查APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "问问你的编程助手" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6627,14 +6635,14 @@ msgstr "该应用程序显示更改的登录代码。 我们想找到 {ph0}是 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "复制" @@ -6642,7 +6650,7 @@ msgstr "复制" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6651,7 +6659,7 @@ msgid "" msgstr "" "这是用于下载的 APK 的示例 prompt,需要先配置 REA 的 Android 分析后端。{ph0}获取 APK 和分析配置 ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "试试代码生成器" @@ -6659,7 +6667,7 @@ msgstr "试试代码生成器" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6668,33 +6676,33 @@ msgid "" "produce the same code." msgstr "应用把时间划分为{ph0}每块 30 秒{ph1},再结合时间块编号和账户密钥生成验证码。同样的密钥和时间块,会得到同样的验证码。" -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "将时钟移动60秒" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "时间" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "秒数" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "我们的可调节示例时钟" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30秒区块" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "时间块" @@ -6703,35 +6711,35 @@ msgstr "时间块" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59秒{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "生成的验证码" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "帐户密钥+区块→六位数字" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "示例时间,以秒为单位" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59秒" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60秒" @@ -6740,7 +6748,7 @@ msgstr "60秒" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6750,7 +6758,7 @@ msgstr "在59秒: {ph0}287082.{ph1} 在60秒: {ph2}359152.{ph3} 在一个块内 #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6758,26 +6766,26 @@ msgid "" "the calculation recovered from the APK." msgstr "密钥是固定的,公开的 {ph0}RFC6238测试数据{ph1}. 该演示实现了从APK恢复的计算。" -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " "clock." msgstr "该图显示了59秒时的结果。 启用JavaScript以更改时钟。" -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "用REA查找代码" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "将APK缩小到三个类" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6785,7 +6793,7 @@ msgid "" "and imported accounts. TOTP means a time-based one-time password." msgstr "{ph0} 是计算逻辑的候选方法;另外两个涉及进度条和导入的账户。TOTP 指基于时间的一次性密码。" -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "将生成器连接到应用程序的显示器" @@ -6793,7 +6801,7 @@ msgstr "将生成器连接到应用程序的显示器" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6802,7 +6810,7 @@ msgid "" msgstr "REA 找到接受时间戳的方法重载,并定位基础方法的调用方。继续检查 {ph0},就能看到显示逻辑调用了 {ph1}。" #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6810,7 +6818,7 @@ msgid "" "{ph0} prefix." msgstr "请求显示缩短的输入路径。 结果类名省略常用 {ph0} 前缀。" -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "阅读计算" @@ -6818,7 +6826,7 @@ msgstr "阅读计算" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6830,7 +6838,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -6838,7 +6846,7 @@ msgstr "{ph0}01{ph1} 时间块" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -6846,7 +6854,7 @@ msgstr "{ph0}02{ph1} 键+块" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -6854,7 +6862,7 @@ msgstr "{ph0}03{ph1} 六位数" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6865,7 +6873,7 @@ msgstr "{ph0}时间选择块。{ph1} 秒30到59都给块1。 在60秒时,块 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6877,7 +6885,7 @@ msgstr "{ph0}密钥也会影响结果。{ph1} 生成函数把账户密钥和时 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6890,7 +6898,7 @@ msgstr "{ph0}保留六位数字。{ph1} 取除以 1,000,000 的余数,位数 #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6898,7 +6906,7 @@ msgid "" " right panel is an explanatory summary. {ph0}Aegis code is GPL-3.0.{ph1}" msgstr "这些节选来自多个检查过的方法,为便于显示增加了换行。右侧是解释性摘要。{ph0}Aegis 源码采用 GPL-3.0 许可。{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "验证码生成函数内部" @@ -6908,7 +6916,7 @@ msgstr "验证码生成函数内部" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6918,7 +6926,7 @@ msgstr "" "发布的 APK 将 {ph0} 放在 {ph1} 中。REA 从 {ph2} 追踪调用,并返回这个函数体;原始源码把辅助函数命名为 {ph3}。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -6933,13 +6941,13 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}与匹配的发布源进行比较{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "检查重建" @@ -6947,7 +6955,7 @@ msgstr "检查重建" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6958,22 +6966,22 @@ msgstr "" "我们将选定的 REA 返回的 Java 方法放进小型测试程序。它们的输出与独立重建的实现一致,共验证 {ph0}133 " "个测试用例{ph1},包括时间块边界和以零开头的验证码。" -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "示例时间" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "六位验证码" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30秒" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109秒" @@ -6981,7 +6989,7 @@ msgstr "1,111,111,109秒" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6989,31 +6997,31 @@ msgid "" "{ph0}RFC 6238{ph1}. Check the browser implementation against them:" msgstr "生成函数还符合 {ph0}RFC 6238{ph1} 中发布的六个 SHA-1 对照用例。可以用这些用例检查浏览器实现:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "运行对照检查" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "阅读演示的计算" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" "digit results." msgstr "参考案例使用八位数字。 检查也验证他们的六位数的结果。" -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " "was inspected statically." msgstr "验证运行提取的Java方法和新的演示。 对Android APK进行了静态检查。" -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "亲自检查APK" @@ -7021,7 +7029,7 @@ msgstr "亲自检查APK" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7033,7 +7041,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7041,19 +7049,19 @@ msgid "" "{ph1}. This case used JDK 21." msgstr "Android分析需要完整的JDK17或更高版本。 选择它与 {ph0} 或 {ph1}. 本案例使用了JDK21。" -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "让 REA 使用分析后端配置文件,再检查 APK:" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS/Linux" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7063,7 +7071,7 @@ msgstr "助手可以通过 REA CLI 继续使用上方的 prompt。如果使用 M #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7071,7 +7079,7 @@ msgid "" "different time interval?{ph1}" msgstr "下一个问题: {ph0}当帐户使用八位数字或不同的时间间隔时会发生什么?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "资料来源" @@ -7087,7 +7095,7 @@ msgstr "资料来源" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7099,14 +7107,14 @@ msgstr "{ph0}官方Aegis3.4.3发布{ph1} · {ph2}匹配源提交{ph3} · {ph4}GP #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}RFC6238参考案例{ph1} · {ph2}演示测试数据{ph3}" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7127,37 +7135,37 @@ msgid "" "calculation and try a reconstruction with an adjustable clock." msgstr "用 REA 检查 Aegis Android APK,还原六位登录验证码的计算,再试玩可调时钟的重建演示。" -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "在本页" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK案例研究" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "复制Aegis示例提示" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "按照登录代码计算" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "复制APK检查命令" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -7166,26 +7174,26 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}首页{ph1} / {ph2}案例展示{ph3} /CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "案例研究·Downunderctf2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "找到国旗{ph0}一个CTF二进制文件。" #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7193,17 +7201,17 @@ msgid "" "find an input that makes the original program print {ph0}." msgstr "使用方法 REA 要检查一个小的flag 检查器,将其规则转换为方程,并找到一个使原始程序打印的输入 {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "蒙面方格旗检查器 · 容易·Linuxx86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "查看原始挑战" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "从二进制到检查答案" @@ -7214,7 +7222,7 @@ msgstr "从二进制到检查答案" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7230,7 +7238,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7247,7 +7255,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7258,20 +7266,20 @@ msgstr "" "{ph0}03 · 解决并运行{ph1}{ph2}恢复旗→正确!{ph3}{ph4}一个Python脚本解决方程. REA " "捕获接受结果的原始程序。{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "挑战是由约瑟夫,发表在DownUnderCTF的官方代码仓库。" -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "在本个案研究中" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7279,7 +7287,7 @@ msgstr "{ph0}查找检查代码{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7287,7 +7295,7 @@ msgstr "{ph0}读一个面具{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7295,7 +7303,7 @@ msgstr "{ph0}汇编到可读代码{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7303,7 +7311,7 @@ msgstr "{ph0}解方程{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7311,20 +7319,20 @@ msgstr "{ph0}检查答案{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}你自己试试吧{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "查找检查代码" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7340,17 +7348,17 @@ msgstr "讲义是一个15KB可执行文件。 它要求一面旗帜,然后打 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "复制" @@ -7361,7 +7369,7 @@ msgstr "复制" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7372,33 +7380,33 @@ msgstr "" "{ph0}›{ph1}{ph2}使用REA分析ms_flag_checker并找到标志。 " "解释检查是如何工作的,然后用原始程序验证答案。{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " "native analysis provider connected." msgstr "一个示例提示,下载的质询在本地可用,并连接了原生分析提供程序。" -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "按照输入提示到其函数" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " "executable's original function names have been removed." msgstr "引用为编程助手提供了一个调查的地方,即使可执行文件的原始函数名已被删除。" -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "阅读检查器和它的两个助手" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7409,19 +7417,19 @@ msgstr "" "第一个循环复制36个字符代码。 检查循环解码掩码,对所选代码求和,并将结果与存储的数字进行比较。 其 {ph0}-字节跨步 {ph1} " "字节给出26个掩码。" -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " "is shortened for display; addresses refer to REA's imported image." msgstr "这些是来自新鲜REA分析的选择结果。 本地目标路径缩短显示;地址参考REA的导入图像。" -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "一张检查显示一个字符" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -7431,13 +7439,13 @@ msgstr "检查器将输入排列在6×6网格中。 掩码选择哪些单元格 #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "第七个检查只选择一个位置。 {ph0}打开图{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "从二进制文件中读取掩码及其目标" @@ -7446,7 +7454,7 @@ msgstr "从二进制文件中读取掩码及其目标" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7457,12 +7465,12 @@ msgstr "" "指示 {ph0} 将掩码字节读取为有符号值。 这就是为什么 {ph1} 表示-21. 目标是一个小端整数。 这些字节一起告诉编程助手 " "{ph2},所以该字符是 {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "从指令到可读的检查" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -7471,7 +7479,7 @@ msgstr "选择一个步骤将求和帮助程序及其调用者连接到C中的 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -7479,7 +7487,7 @@ msgstr "{ph0}01{ph1} 开始" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -7487,7 +7495,7 @@ msgstr "{ph0}02{ph1} 选择" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -7495,7 +7503,7 @@ msgstr "{ph0}03{ph1} 添加" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -7503,18 +7511,18 @@ msgstr "{ph0}04{ph1} 前进,前进" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} 比较一下" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA · 选定的原始说明" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "可读的C · 一检查摘要" @@ -7522,7 +7530,7 @@ msgstr "可读的C · 一检查摘要" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -7530,7 +7538,7 @@ msgstr "{ph0}01 · 从零开始。{ph1} {ph2} 持有运行总和。" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7540,7 +7548,7 @@ msgstr "{ph0}02 · 检查掩码单元格。{ph1} 零值跳过字符;非零值包 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7550,7 +7558,7 @@ msgstr "{ph0}03 · 添加字符代码。{ph1} 输入在相同偏移量处的整 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7562,7 +7570,7 @@ msgstr "{ph0}04 · 移动到下一个单元格。{ph1} 原始循环每个整数 #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7570,19 +7578,19 @@ msgid "" "in {ph2}. A mismatch jumps to {ph3}." msgstr "{ph0}05 · 与存储的目标进行比较。{ph1} 调用方在 {ph2}. 不匹配跳转到 {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " "explanatory summary with descriptive names and a flattened 36-cell loop." msgstr "指令来自求和助手及其调用者。 C是一个具有描述性名称和扁平36个单元格循环的解释性摘要。" -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "求解26个方程" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -7591,13 +7599,13 @@ msgid "" msgstr "" "大多数掩码选择几个单元格。 例如,第一次检查添加了16个字符代码,总共需要1441个。 重叠的选择给出了一个小的Python脚本可以一起求解的方程。" -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python · 求解器摘录" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7609,19 +7617,19 @@ msgstr "" "Z3是一个求解器,可以找到满足这些方程的值。 此摘录使用提取的检查,并假定 {ph0} 用字母,数字,下划线和大括号标记。 " "完整的下载包括所有26个面具和目标。" -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "下载完整的求解器" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "用原始程序检查答案" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7631,59 +7639,59 @@ msgid "" msgstr "" "REA的进程捕获记录接受已解决标志的原始可执行文件。 更改一个选定的字符 {ph0} 到 {ph1} 使第一和1440而不是1441,并且程序拒绝它。" -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "输入" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "观察到的输出" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "退出代码" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "解算者之旗" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "一个角色改变了" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "显示恢复的标志和捕获的输出" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA · 原始程序输出" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "复制标志" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " "challenge metadata, checked after solving the binary." msgstr "恢复的值还与组织者发布的挑战元数据中的标志相匹配,在解决二进制后检查。" -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "来源、目标身份和分析详细信息" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -7693,7 +7701,7 @@ msgstr "" "在2026年10月8日使用REA4.1.0和Ghidra12.1.4在Linux x64上进行新的分析和两个过程捕获。 " "二进制文件是一个剥离的x86-64ELF,15,248字节。" -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -7713,7 +7721,7 @@ msgstr "在阅读组织者的源代码或解决方案之前,对字符串引用 #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7721,25 +7729,25 @@ msgid "" "flag{ph3} · {ph4}REA evidence notes{ph5}" msgstr "{ph0}与主办方来源比较{ph1} · {ph2}挑战元数据和标志{ph3} · {ph4} REA证据说明{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "你自己试试吧" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " "prompt above to investigate with your agent, or run the included script." msgstr "将原始挑战和求解器下载到一个文件夹中。 使用上面的提示与你的编程助手进行调查,或运行包含的脚本。" -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "终端 · 解决和运行" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7748,7 +7756,7 @@ msgid "" "x86-64." msgstr "脚本打印候选标志;将其粘贴到程序的提示符处。 解决需要Python和 {ph0}. 运行原始可执行文件需要Linux x86-64。" -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "设置REA与你的编程助手" @@ -7766,27 +7774,27 @@ msgid "" "original program." msgstr "使用REA来解决DownUnderCTF的掩码方块flag 检查器。 找到检查函数,提取掩码并将恢复的标志与原始程序进行比较。" -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "在本页" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTFflag 检查个案研究" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "复制CTF示例提示" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "CTF掩码方程;在较小的屏幕上水平滚动" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -7794,42 +7802,42 @@ msgid "" "means the character is 7." msgstr "第七个掩码跳过21个单元格,选择位置21,然后跳过14。 只有该单元格贡献总和。 它所需的字符代码是55,这意味着字符是7。" -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "遵循CTF检查" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "复制CTF装配" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "复制可读CTF检查" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "复制CTF解算器摘录" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "复制恢复标志" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "复制CTF求解器命令" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -7838,35 +7846,35 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}首页{ph1} / {ph2}案例展示{ph3} / DX-Ball" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "案例 · DX-Ball 1.07" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "从可执行文件{ph0}重建 DX-Ball。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" " agent inspect the original, one function at a time." msgstr "目标是为这款 1996 年的 Windows 游戏重建一份可维护的 C 代码。REA 帮助编程助手逐个分析原版函数。" -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 · C · REA" @@ -7874,7 +7882,7 @@ msgstr "Windows i386 · C · REA" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -7885,7 +7893,7 @@ msgstr "" "从可执行文件中的一个函数,到经过验证的 C 代码:REA 提供指令、调用方和读取的数据,重建项目据此实现并测试函数。{ph0}查看大图{ph1}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "本案例内容" @@ -7893,7 +7901,7 @@ msgstr "本案例内容" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -7901,7 +7909,7 @@ msgstr "{ph0}项目进度{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -7909,7 +7917,7 @@ msgstr "{ph0}声像计算{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -7917,25 +7925,25 @@ msgstr "{ph0}检查结果{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}继续工作{ph1}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "个可维护的 C 函数" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "与原始代码的比较" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "个编译后字节匹配的函数" @@ -7947,7 +7955,7 @@ msgstr "个编译后字节匹配的函数" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -7956,13 +7964,13 @@ msgid "" msgstr "项目进度截至 2026 年 10 月 7 日。{ph0}进度记录{ph1} · {ph2}测试覆盖情况{ph3}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "当前进度" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -7975,13 +7983,13 @@ msgstr "" " Windows 集成。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "找出声音的左右位置如何计算" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -7997,17 +8005,17 @@ msgstr "砖块被击中时,它的横坐标会传给声音处理代码。这次 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "复制" @@ -8019,7 +8027,7 @@ msgstr "复制" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8029,7 +8037,7 @@ msgstr "" "{ph0}›{ph1}{ph2}用 REA 找出 DX-Ball 如何计算声音的左右位置。解释计算过程,并展示代码。{ph3}{ph4}{ph5}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8038,7 +8046,7 @@ msgid "" msgstr "把本地可执行文件交给编程助手,再使用这个示例 prompt。下面展示助手为回答问题发起的 REA 查询,以及得到的证据。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8050,7 +8058,7 @@ msgstr "助手用 REA 检查函数、追踪调用它的砖块碰撞函数,再 #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8061,13 +8069,13 @@ msgid "" msgstr "" "REA 最初返回的 {ph0} 伪代码声明了 {ph1},并调用 {ph2}。但指令中还有来自栈的输入和浮点运算。这个差异提示助手:还需要继续查。" -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "最初的反编译结果" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8075,20 +8083,20 @@ msgid "" msgstr "结果里能看到一次转换调用。继续阅读下面的指令,就能找出输入,以及传入这个调用前的计算。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "用 REA 回答三个问题" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "找回缺失的输入" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8097,7 +8105,7 @@ msgid "" msgstr "函数结果同时提供伪代码、指令和调用方。这里的 {ph0} 显示了反编译结果中缺失的整数输入。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "追踪调用方,理解输入含义" @@ -8105,7 +8113,7 @@ msgstr "追踪调用方,理解输入含义" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8113,26 +8121,26 @@ msgid "" "scale {ph0} by 30; adding 20 gives the brick's screen coordinate, {ph1}." msgstr "REA 在第一次结果中就给出了这个调用方。调用前的指令将 {ph0} 乘以 30,再加上 20,得到砖块的屏幕坐标 {ph1}。" -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "读取内存地址后面的值" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " "scale. The agent now has the values needed for the C expression." msgstr "返回的字节确定了两个运算常量,以及声像缩放系数的初始值。助手由此得到编写 C 表达式所需的数值。" -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "从 REA 分析结果到 C 代码" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8141,7 +8149,7 @@ msgstr "下面分五步展示计算。点击每一步,原始指令和对应的 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8149,7 +8157,7 @@ msgstr "{ph0}01{ph1} 输入" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8157,7 +8165,7 @@ msgstr "{ph0}02{ph1} 乘以" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8165,7 +8173,7 @@ msgstr "{ph0}03{ph1} 减去" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8173,20 +8181,20 @@ msgstr "{ph0}04{ph1} 缩放" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} 返回" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "原始 x86 · 节选" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "重建的 C 代码" @@ -8197,7 +8205,7 @@ msgstr "重建的 C 代码" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8216,7 +8224,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8233,7 +8241,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8251,7 +8259,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8268,7 +8276,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8280,7 +8288,7 @@ msgstr "" "{ph4},再与原始 x86 函数比较,验证返回值。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -8288,24 +8296,24 @@ msgid "" "setup and cleanup." msgstr "这段汇编节选包含输入、运算和返回指令。下面的完整列表还保留了中间的存储操作,以及函数开头和结尾的处理。" -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "完整汇编与相关证据" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA结果 · 0x406400–0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "调用方传入什么" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8313,55 +8321,55 @@ msgid "" "then pushes it before the call:" msgstr "{ph0} 处的砖块碰撞函数把格子坐标乘以 30,再加上 20,然后在调用前将结果压栈:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "读取数据确认了什么" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA 读取的字节,按小端双精度浮点数解码" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "地址" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "数值" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "用于" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "第一次乘法" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "减法" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} 最初" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "存储的声像缩放系数" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -8376,7 +8384,7 @@ msgstr "使用 REA 4.1.0 记录,分析目标为通过哈希确定的 DX-Ball 1 #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8384,13 +8392,13 @@ msgid "" "references{ph3}" msgstr "{ph0}重建源码{ph1} · {ph2}调查笔记与证据引用{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "验证还原的函数" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -8398,13 +8406,13 @@ msgid "" msgstr "还原的函数通过了两项检查:返回值与原版一致,编译后的字节与原始可执行文件一致。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3,205 个行为测试用例" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -8415,13 +8423,13 @@ msgstr "" "和 −1。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 字节完全匹配" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -8430,7 +8438,7 @@ msgid "" msgstr "C 函数使用指定的 VC4.0 工具链编译。应用经过检查的重定位,并核对引用的常量后,编译结果与原始函数的全部字节一致。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -8442,19 +8450,19 @@ msgstr "缩放系数为 1 时,计算在屏幕左边缘返回 −500,中心 #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}阅读编译器重播详细信息{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "继续调查" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -8463,14 +8471,14 @@ msgid "" msgstr "粒子更新、爆炸队列和奖励生成也使用同样的方法:检查相关函数,还原状态与依赖,再把实现和原版比较。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " "setup instructions and supply its matching original target. Then run:" msgstr "如果你也想分析这个声像函数,先按 DX-Ball 项目的说明配置环境,并准备匹配的原始文件。然后运行:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "在 DX-Ball 仓库目录中" @@ -8480,7 +8488,7 @@ msgstr "在 DX-Ball 仓库目录中" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8493,7 +8501,7 @@ msgstr "{ph0}DX-Ball 仓库{ph1}{ph2}当前源码、进度和本地配置。{ph3 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8508,7 +8516,7 @@ msgstr "{ph0}REA 分析流程{ph1}{ph2}追踪这段计算,再用同样方法 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8531,14 +8539,14 @@ msgid "" msgstr "查看 DX-Ball 的重建过程:用 REA 分析二进制文件,编写可维护的 C 代码,再通过原始 x86 行为测试和编译字节匹配验证。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ball 声像计算调查;小屏幕可横向滚动" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -8551,89 +8559,89 @@ msgstr "" "1.5625,减去 500.0,再乘以 pan_scale,最后返回整数。重建的 C 代码通过 3,205 个用例与原始 x86 函数比较,并用 " "VC4.0 编译结果匹配全部 63 字节。" -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "在本页" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball重建案例研究" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "复制示例提示" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "追踪声像计算" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "复制原始汇编摘录" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "复制声像函数" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "复制完整声像计算汇编" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "复制DX-Ball分析命令" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "跳转到内容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}首页{ph1} /陈列柜" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA 实际案例。" -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" " results." msgstr "安卓,游戏,Electron和CTF挑战,与代码,数字和检查结果。" -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android · APK 分析" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "验证器如何生成登录验证码" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -8641,22 +8649,22 @@ msgid "" "changes every 30 seconds." msgstr "在其发布的APK中找到Aegis的六位数代码计算。 使用REA跟踪生成方法,然后移动演示时钟以查看代码每30秒更改一次的原因。" -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "阅读Android案例研究" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF · 原生分析" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "分析 CTF flag 检查器" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -8664,22 +8672,22 @@ msgid "" "with the original program." msgstr "使用REA检查一个简单的DownUnderCTF挑战。 找到它的检查函数,将掩码和和转换为方程,然后用原始程序验证已求解的标志。" -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "阅读CTF案例研究" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "原生程序 · 重建" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball 的声像计算" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -8689,22 +8697,22 @@ msgstr "" "从1996年的Windows游戏中恢复左/右声音位置的计算。 " "REA的指令,调用者引用和数字常量导致一个小的C函数,对照原始行为和所有63个编译字节进行检查。" -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "阅读DX-Ball案例研究" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron · 功能追踪" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Notion 如何复制文本和 HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -8714,22 +8722,22 @@ msgstr "" "通过跟踪面向页面的API Notion包装好了 JavaScript. " "跟随它的IPC包装到系统剪贴板,然后看看一个小的HTML标记如何保持丰富的块数据连接到复制。" -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "阅读Notion案例研究" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS · 重建" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "TH04 如何把环形弹幕对准玩家" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -8737,24 +8745,24 @@ msgid "" "a ring aimed at the player." msgstr "用REA检查原始的16位角度助手。 将其乘法,除法和坐标操作匹配到可读的C++,然后看看它们如何产生一个针对玩家的环形弹幕。" -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "阅读TH04案例研究" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "循序渐进指南" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " "browser request. Each starts with a prompt and a concrete target." msgstr "本指南介绍了本机计算、Electron导出和浏览器请求。 每个都以提示和具体目标开始。" -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "阅读指南" @@ -8773,12 +8781,12 @@ msgstr "" "跟我来 REA 通过代码、数字和演示进行调查:Android身份验证器, DX-Ball, Notion, TH04 " "和一个DownUnderCTFflag 检查器。" -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -8787,37 +8795,37 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}首页{ph1} / {ph2}案例展示{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "个案研究*Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "如何 Notion 复制{ph0}文本和HTML。" -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " "process, to Electron's clipboard writer." msgstr "跟踪剪贴板调用从Notion的页面API,通过预加载和主进程,到Electron的剪贴板编写器。" -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion桌面7.6.1·JavaScript*REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Notion 桌面包中的桥接代码" @@ -8829,7 +8837,7 @@ msgstr "Notion 桌面包中的桥接代码" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8844,7 +8852,7 @@ msgstr "{ph0}01 · 面向页面的API{ph1} {ph2}{ph3}{ph4} {ph5}预加载公开 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8859,7 +8867,7 @@ msgstr "{ph0}02 · 预加载包装器{ph1} {ph2}{ph3}{ph4} {ph5}包装器发送 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8874,7 +8882,7 @@ msgstr "{ph0}03 · 主进程处理程序{ph1} {ph2}{ph3}{ph4} {ph5}接收器检 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8883,28 +8891,28 @@ msgid "" msgstr "{ph0}04 · 系统剪贴板{ph1} {ph2}{ph3}{ph4} {ph5}Electron 写入提供的文本和HTML。{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "一个通道连接双方: {ph0}" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " "Resolving the wrappers reveals the Electron calls behind those names." msgstr "预加载脚本和主进程使用同一个通道。解析包装函数后,就能看出这些名称背后实际调用的 Electron 函数。" -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "在本个案研究中" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -8912,7 +8920,7 @@ msgstr "{ph0}跟随剪贴板桥{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -8920,20 +8928,20 @@ msgstr "{ph0}保留内容块的结构{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}更多示例和来源{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "复制操作去哪里?" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8950,17 +8958,17 @@ msgstr "页面可以调用名为 {ph0} 的方法。它在预加载脚本中的 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "复制" @@ -8971,7 +8979,7 @@ msgstr "复制" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8980,20 +8988,20 @@ msgid "" msgstr "" "{ph0}›{ph1}{ph2}使用REA跟踪Notion如何将文本和HTML复制到系统剪贴板。 在每个步骤显示代码。{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " "coding agent." msgstr "一个示例提示与Notion的本地应用程序包可供你的编程助手." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA查找从哪里开始阅读" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9001,14 +9009,14 @@ msgid "" " the minified bundle:" msgstr "用 REA 分析标签页的预加载脚本,可以找到暴露给页面的 API,以及发送 IPC 请求的调用。两个结果都给出了在压缩代码中的位置:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA 分析结果 → 两个源码位置" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9022,7 +9030,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9034,25 +9042,25 @@ msgstr "" "助手打开这些位置,在组装的 API 中找到剪贴板成员,再读取 {ph0}。调用处传入 " "{ph1},让助手知道要在主进程代码中搜索哪个名称。下面四段代码展示这条调用链。" -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "四段简短代码" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " "Unrelated members are omitted." msgstr "从打包的JavaScript简化,具有可读的变量名称。 不相关的成员被省略。" -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "从公开到页面的API开始" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9060,14 +9068,14 @@ msgid "" "how the request leaves the page's process." msgstr "此成员提供通道名称。 的实施 {ph0} 告诉我们请求如何离开页面的进程。" -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "解析预加载的包装器" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9075,14 +9083,14 @@ msgid "" "response IPC. We can now look for {ph0} on the main-process side." msgstr "返回的函数通过 Electron 的请求/响应 IPC 转发参数。接下来可以在主进程中查找 {ph0}。" -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "检查接收器是如何注册的" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9090,13 +9098,13 @@ msgid "" "receiver for that channel." msgstr "主进程使用另一个包装器。 其 {ph0} 方法注册一个 {ph1} 那个频道的接收器。" -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "查找写入及其发件人检查" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9106,14 +9114,14 @@ msgstr "" "这就是调用的终点。处理函数检查发送方后,把收到的数据交给 Electron 的剪贴板 " "API。通道名和两个解析后的包装函数,把暴露给页面的方法连接到了这里。" -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "复制的块如何保持其结构?" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9122,83 +9130,83 @@ msgid "" msgstr "" "Notion 的网页编辑器通过 {ph0} 发送文本和 HTML。它在本地保留内容块数据,再在复制的 HTML 中放入一个 ID,将二者关联起来。" -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "保存的块数据的HTML链接" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "读取HTML ID" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "查找相同的本地ID" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "恢复Notion块数据" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " "when IDs match; a stale entry returns only text and HTML." msgstr "文本和 ID 为示意值。已记录的模块测试显示:ID 匹配时可以取回内容块数据;条目失效时只返回文本和 HTML。" -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." " Matching IDs restore the block data." msgstr "在粘贴时,Notion查找HTML ID并根据保存的复制进行检查。 匹配的Id恢复所述块数据。" -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "从2026年7月13日缓存的web资产中记录的剪贴板格式。" -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "更多示例和来源" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "另一个例子:Markdown 表格" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " "becomes header and data rows." msgstr "Notion将Markdown解析为块数据。 此示例显示表如何成为标题和数据行。" -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "通过Notion的Markdown解析器的表格" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " "and cells." msgstr "从提取的Markdown解析器记录输出。 表变为行和单元格。" -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "另一条路径:脱机SQLite连接" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9211,14 +9219,14 @@ msgstr "" "工具进程。后续的语句批次和结果直接通过这个端口传输。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " "tracing only the initial IPC request misses the later conversation." msgstr "追踪这次交接,就能知道数据库操作在哪个进程执行,也能解释为什么只跟踪最初的 IPC 请求会漏掉后续通信。" -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "资料来源及如何阅读摘录" @@ -9227,7 +9235,7 @@ msgstr "资料来源及如何阅读摘录" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9244,7 +9252,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9258,7 +9266,7 @@ msgstr "" "模块。这些资源有独立版本。保存的测试执行提取出的模块和小型测试程序;输出反映的是这些测试,没有记录桌面 UI 操作。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -9271,7 +9279,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9287,7 +9295,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9299,7 +9307,7 @@ msgstr "{ph0} JavaScript应用指南{ph1}{ph2}遵循一个小的Electron应用 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9322,52 +9330,52 @@ msgid "" msgstr "" "追踪 Notion 的剪贴板 API,经过 Electron 预加载脚本、IPC 包装函数和主进程。通过简短代码节选了解调用链,再查看富文本剪贴板格式。" -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "在本页" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron案例研究" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "复制Notion分析提示" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "复制Notion预加载摘录" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "复制 Notion 调用包装摘录" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "复制Notion处理程序包装器摘录" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "复制Notion剪贴板接收器摘录" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "在粘贴上还原丰富的剪贴板数据" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "回到顶部" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "跳转到内容" @@ -9376,43 +9384,43 @@ msgstr "跳转到内容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}首页{ph1} / {ph2}案例展示{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "个案研究·东方4:莲花地故事" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "重建TH04{ph0}子弹图案。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " "the original DOS function, then follow its instructions into readable C++." msgstr "一圈弹幕从一段简短的角度计算开始。用 REA 检查原始 DOS 函数,再把指令对应到可读的 C++ 代码。" -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98·16位DOS · C++和汇编" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "查看TH04重建" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "从原始指令到经过验证的源码" @@ -9423,7 +9431,7 @@ msgstr "从原始指令到经过验证的源码" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9438,7 +9446,7 @@ msgstr "{ph0}01 · 原创游戏{ph1}{ph2}主要。EXE文件{ph3}{ph4}该 PC-98 #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9456,7 +9464,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9472,7 +9480,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9484,21 +9492,21 @@ msgstr "" "字节匹配{ph3}{ph4}已记录的编译器检查覆盖了包含这个辅助函数的弹幕生成代码。{ph5}" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " "supplies the maintained source and compiler checks." msgstr "REA 返回原始代码和分析证据。TH04 项目提供维护中的源码,以及编译器检查结果。" -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "在本个案研究中" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -9506,7 +9514,7 @@ msgstr "{ph0}子弹环{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -9514,7 +9522,7 @@ msgstr "{ph0}REA 返回什么{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -9522,7 +9530,7 @@ msgstr "{ph0}汇编到C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -9530,19 +9538,19 @@ msgstr "{ph0}检查来源{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}完整项目{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "环形弹幕如何瞄准玩家" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -9558,16 +9566,16 @@ msgstr "Elly 的攻击请求一个初始数量为 16 的自机狙环形弹幕。 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的编程助手" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "复制" @@ -9578,7 +9586,7 @@ msgstr "复制" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9587,7 +9595,7 @@ msgid "" msgstr "" "{ph0}›{ph1}{ph2}使用REA查找TH04如何创建一个子弹环并将其瞄准玩家。 解释计算并显示代码。{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -9596,7 +9604,7 @@ msgstr "一个示例提示,原始可执行文件和重建签出可在本地使 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9609,7 +9617,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9617,12 +9625,12 @@ msgid "" "40 and template rotation 0. {ph0}Open figure{ph1}" msgstr "图中演示还原出的角度计算:子弹数量为 16,玩家方向为 40,模板旋转角为 0。{ph0}查看大图{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "还原源码中的发射模板" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Elly 的环形攻击 · 源码节选" @@ -9631,7 +9639,7 @@ msgstr "Elly 的环形攻击 · 源码节选" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9639,14 +9647,14 @@ msgid "" "{ph0}Read the attack's source{ph1}." msgstr "这些线在难度和性能调整之前选择模式。 {ph0}阅读攻击的来源{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "REA 返回什么" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9655,20 +9663,20 @@ msgid "" " result explain the pattern." msgstr "我们检查设置每颗子弹速度和角度的函数 {ph0}。REA 返回指令、伪代码和引用,其中三部分解释了这种弹幕如何生成。" -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "在阅读其代码之前检查DOS映像" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " "executable. The path above is shortened for display." msgstr "这项检查确认加载的代码和重定位记录对应提供的可执行文件。上方路径为便于显示而缩短。" -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "查看环形弹幕的乘除计算" @@ -9677,7 +9685,7 @@ msgstr "查看环形弹幕的乘除计算" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9687,13 +9695,13 @@ msgid "" msgstr "" "{ph0} 保存子弹索引。移位将它乘以 256,再除以从 {ph1} 读取的数量。重建源码把这个字段命名为 {ph2}。完整指令序列见下文。" -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "找到模式转向玩家的位置" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -9704,13 +9712,13 @@ msgstr "" "指令操作数显示了两个坐标差,以及一个计算方向的辅助函数。它的返回值加到相对环形角度上。源码名称让这些地址的含义更易读;REA " "则帮助助手核对地址背后的原始操作。" -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "从汇编到可读C++" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -9720,7 +9728,7 @@ msgstr "点击每一步,对照原始指令和角度计算。这份摘要展示 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -9728,7 +9736,7 @@ msgstr "{ph0}01{ph1} 索引" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -9736,7 +9744,7 @@ msgstr "{ph0}02{ph1} 等分" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -9744,7 +9752,7 @@ msgstr "{ph0}03{ph1} 瞄准" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -9752,18 +9760,18 @@ msgstr "{ph0}04{ph1} 旋转" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} 存储" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA · 原始 16 位指令" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "可读 C++ · 自机狙环形弹幕摘要" @@ -9772,7 +9780,7 @@ msgstr "可读 C++ · 自机狙环形弹幕摘要" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9785,7 +9793,7 @@ msgstr "{ph0}01 · 读取子弹索引。{ph1} 栈参数加载到 {ph2}。在 16 #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9800,7 +9808,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9815,7 +9823,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9829,7 +9837,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9842,7 +9850,7 @@ msgstr "" "后回绕,与无符号字节转换一致。周围源码还会根据这个角度和速率计算速度分量。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -9850,7 +9858,7 @@ msgid "" "maintained source in the linked project." msgstr "汇编节选展示自机狙环形分支、瞄准计算和最终存储。上面的 C++ 是便于阅读的摘要。下方的编译器检查针对链接项目中维护的源码。" -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "阅读维护的环和瞄准源" @@ -9867,7 +9875,7 @@ msgstr "阅读维护的环和瞄准源" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9875,37 +9883,37 @@ msgid "" "representation{ph5}" msgstr "{ph0}环宏{ph1} · {ph2}目标和速度源{ph3} · {ph4}角度表示{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "检查维护的源" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " "including this helper, with its pinned Turbo C++ 4.0J toolchain." msgstr "TH04 项目记录的检查使用指定的 Turbo C++ 4.0J 工具链,编译包含这个辅助函数的弹幕生成代码。" -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139匹配字节" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " "original executable." msgstr "编译的子弹生成代码与原始可执行文件的2,139字节部分相匹配。" -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "两个干净的构建" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -9916,66 +9924,66 @@ msgstr "两个单独的构建产生相同的匹配字节。 记录的输入哈 #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "2026年10月3日录得。 {ph0}阅读编译器检查{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "目标身份和分析范围" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "原始目标" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0},156,258字节,DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "佣工入境" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} 在REA的加载图像" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "原始文件偏移量" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0},返回 {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "记录代码检查" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA4.1.0*2026年10月7日" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -9984,7 +9992,7 @@ msgstr "编译器检查覆盖完整的弹幕添加代码段,包括这个辅助 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9998,7 +10006,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10012,7 +10020,7 @@ msgstr "" "对同一原始目标的检查。游戏文件的身份由仓库清单确定,独立原始转储的来源仍未确定。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10020,13 +10028,13 @@ msgid "" "project." msgstr "图中说明的是角度计算。完整游戏的控制、时序和 PC-98 硬件行为,在重建项目中有各自的运行时检查。" -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "完整的TH04重建" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10036,7 +10044,7 @@ msgstr "项目用维护中的 C++ 和汇编构建游戏的四个 DOS 程序。 #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10048,7 +10056,7 @@ msgstr "{ph0}探索 TH04 代码仓库{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10062,7 +10070,7 @@ msgstr "{ph0}子弹生成源{ph1}{ph2}完整的助手,其他模式类型和模 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10076,7 +10084,7 @@ msgstr "{ph0}DOS构建和运行指南{ph1}{ph2}构建源代码并在项目的PC- #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10098,29 +10106,29 @@ msgid "" "player." msgstr "用 REA 检查 TH04 的原始 16 位 DOS 代码。对照汇编与还原的 C++,了解环形弹幕如何等分方向并瞄准玩家。" -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "在本页" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04子弹型案例研究" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "复制TH04示例提示" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "TH04固定和瞄准子弹环;在较小的屏幕上水平滚动" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10131,27 +10139,27 @@ msgstr "" "两幅图展示 16 颗子弹的环。固定环从角度 0 开始。加上玩家方向 40 后,每个方向都旋转相同角度,高亮的第一颗子弹指向玩家。两者都保持 16 " "个角度单位的间距,即 22.5 度。" -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "复制 TH04 发射模板" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "按照TH04-环计算" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "复制TH04汇编摘录" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "复制可读瞄准环计算" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "回到顶部" @@ -10259,14 +10267,14 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "固定速度: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" "game check when rounded to three decimals." msgstr "重放了恢复的规则。 当四舍五入到三位小数时,所有四个值都匹配受控的原始游戏检查。" -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -10614,592 +10622,600 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "相同间距:256÷16=16角度单位=22.5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "案例展示" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "博客" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "开始使用" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "指南" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "源代码" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "MIT 许可证" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "加入社区" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "在 X 上关注我们" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA · 选定脚本源" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "源代码" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "预期格式化程序输出" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "指令" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "调用方" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "常量" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "C函数" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "按钮" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "预加载API" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV文件" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "你的点击" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "捕获的请求" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "导出脚本" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA 结果 · summary.ipc 摘录" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA指令摘录·0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA调用方摘录 · 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA字节结果 · 解释为little-endian双精度浮点数" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "恢复C · 摘录" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "看看 REA 如何工作 ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "查看案例 →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "实际脚本中的设置节选" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "% 处理函数的可读摘要" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA · 原始指令节选" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "运算符 ID · Microsoft 源码" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "在X上关注@reatools" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "编程助手→ REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA →编程助手 · 选定结果" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA →编程助手·方法和调用者" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA · 精选反编译Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "可读摘要 · 编程助手解释" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA · generateOTP 完整函数体" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "下载Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "下载 Android 分析后端" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "编程助手→ REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA →编程助手 · 选定结果" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA →编程助手 · 选择说明" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "编程助手→ REA · read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA →编程助手·第七项" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "原始可执行文件 · SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "下载原始挑战" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "下载求解器" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA结果 · 伪代码摘录" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "编程助手→ REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA →编程助手·指令摘录" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA →编程助手·调用方摘录" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "助手 → REA · 两次 {ph0} 请求" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA 字节结果 · 双精度浮点数解码" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "从你自己的目标开始" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "生成验证码" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "还原的规则" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "可调时钟" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "二进制" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "检查 flag 的代码" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "方程" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "正确!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "可执行文件" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA调查结果" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "还原的 C 代码" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "验证" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "打包应用程序" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "公开API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "IPC包装器" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "剪贴板" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "原始DOS代码" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA 指令" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "角度计算" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "环形弹幕" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "公开页面API" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "渲染器IPC调用" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "发送到系统剪贴板" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Notion本地保存" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Markdown 输入" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "结构化解析器输出 · 摘录" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "分析你自己的应用程序" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "编程助手→ REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA →编程助手 · 选定字段" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "编程助手→ REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA →编程助手·指令摘录" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "相同的函数结果 · 目标摘录" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "对应维护的C++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "环宏 · TH04分支,摘录" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "角度和速度 · 源摘录" @@ -11231,7 +11247,7 @@ msgstr "译文正在更新,这一页暂时显示英文。" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11246,7 +11262,7 @@ msgstr "{ph0}›{ph1}{ph2}用 REA 分析 {ph3},解释它如何导出数据。 #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11266,7 +11282,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11285,7 +11301,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11303,7 +11319,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11321,7 +11337,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11330,14 +11346,14 @@ msgid "" msgstr "{ph0}›{ph1}{ph2}用 REA 检查 {ph3}。帮我克隆这个网站。{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "重建工程 · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11346,7 +11362,7 @@ msgid "" msgstr "准备好 {ph0} 和 npm 后,运行 setup,选择编程助手,再确认拟进行的更改。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -11355,7 +11371,7 @@ msgstr "提供的示例 · {ph0} 和 npm · 编程助手" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11372,7 +11388,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -11386,7 +11402,7 @@ msgstr "{ph0}页面 · {ph1}{ph2}{ph3}Export notes(导出笔记){ph4}{ph5} #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11403,7 +11419,7 @@ msgstr "{ph0}桥接 · {ph1}{ph2}{ph3}{ph4}{ph5}{ph6}向主进程发送命名消 #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11413,7 +11429,7 @@ msgstr "" "{ph0}处理函数 · {ph1}{ph2}{ph3}写入 {ph4}{ph5}{ph6}调用 {ph7} 中的格式化函数,再写入文件。{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -11428,7 +11444,7 @@ msgstr "{ph0} · 第 8–12 行" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11440,7 +11456,7 @@ msgstr "" "格式化函数验证。展示预测和实际输出。{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11449,7 +11465,7 @@ msgid "" msgstr "标题保留在一个带引号的字段里,每个引号都写成两个。这里用 {ph0} 直接检查格式化函数。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -11457,7 +11473,7 @@ msgstr "{ph0} · CSV 格式化函数" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11465,7 +11481,7 @@ msgid "" msgstr "需要 {ph0} 22(22.19+)、24(24.11+)或 26+。npm 会随 {ph1} 一起安装。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -11473,7 +11489,7 @@ msgstr "还没安装 {ph0},或不确定?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11485,7 +11501,7 @@ msgstr "" "found”,先安装 {ph1} 24 LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -11499,7 +11515,7 @@ msgstr "{ph0} · 示例源摘录" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -11508,9 +11524,9 @@ msgid "" msgstr "{ph0}打开示例{ph1} · {ph2}下载 {ph3}{ph4} · {ph5}下载 {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -11518,7 +11534,7 @@ msgstr "{ph0} · 示例来源" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -11530,7 +11546,7 @@ msgstr "下载示例并解压缩。 存档包含完整的 {ph0} 文件夹。 分 #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11541,7 +11557,7 @@ msgstr "第一次使用,还没安装 {ph0} 或编程助手?{ph1}跟着安装 #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -11554,7 +11570,7 @@ msgstr "比如:{ph0}为什么计算器算 {ph1} 会得到 220?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11564,7 +11580,7 @@ msgstr "" "{ph0}›{ph1}{ph2}用 REA 检查 Windows 计算器。为什么 {ph3} 会得到 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -11573,7 +11589,7 @@ msgstr "REA · 已加载 {ph0} · 代码节选" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11589,7 +11605,7 @@ msgstr "我们已看到{ph0}为什么 {ph1} 得到 220。{ph2}现在把 + 和 × #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11607,7 +11623,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -11619,28 +11635,28 @@ msgstr "" "秒变化一次,再做一个可以调整时间的小演示。{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} · API 成员" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} · IPC 辅助函数" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "主要/{ph0} · 处理程序助手" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -11650,12 +11666,1177 @@ msgstr "主要/{ph0} · 剪贴板接收器" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "开始使用 {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "切换到浅色模式" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "切换到深色模式" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"要检查 HTTP 请求和响应正文,请使用{ph0}Fiddler Everywhere:SAZ 捕获、MCP 和公开技能{ph1}。导出 SAZ ? " +"HAR 1.2 可在 REA 中离线获取捕获 Evidence,也可以连接 Everywhere 的 MCP 服务器,让智能体检查已捕获的流量。" + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "专用模型{ph0}随笔" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "逆向工程需要更大的模型吗?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "从 Touhou 重建的经验,探讨通用模型、专用模型,以及如何从编译器反馈中学习。" + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "作者 N0zoM1z0 · 2026 年 10 月 13 日" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "跳转到内容" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}首页{ph1} / {ph2}博客{ph3} / 模型与逆向工程" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "随笔" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "逆向工程需要更大的模型吗?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "作者 N0zoM1z0 · 2026 年 10 月 13 日" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "要点" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "{ph0}模型能力会影响 agent 能提出哪些假设。{ph1} 后来的工作解决了早期尝试未能解决的问题。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "{ph0}熟悉的编译器为专用模型提供了具体的学习对象。{ph1} 有些精确匹配依赖细小但可以复用的源码模式。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "{ph0}也要公平评估代码仓库里的知识。{ph1} 较小的模型配合良好的检索,可能已经掌握了足以推进工作的知识。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "{ph0}训练模型选择下一个有价值的实验,同时检验它使用的验证器。{ph1} 反馈是否有用,取决于验证器究竟检查了什么。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "{ph0}结合时间和成本,评估通过验证的重建成果。{ph1} 这是我希望从整个 agent 工作流中获得的结果。" + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "在本文中" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}更强的模型改变了什么{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}为什么考虑专用模型?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}这些经验应该存在哪里?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}学习选择下一个有价值的实验{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}逆向工程与强化学习{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}当验证器出错时{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}值得做的对照实验{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}这意味着怎样的 agent?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "更强的模型改变了什么" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"从 2026 年 8 月开始,我一直在探索:如果给 agent " +"访问程序的能力,以及验证自身工作的手段,它能独立完成多少逆向工作?我的经验主要来自游戏重建,尤其是东方系列。随着我更换模型,代码仓库记录了每次工作还原出的内容。" + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"这些工作很大一部分追求精确重建:用固定版本的历史工具链编译我们维护的源码,检查它能否复现目标函数。当后来的模型解决了早期工作卡住的问题,我们可以从源码变化中看出,是什么促成了这次进展。" + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "临时值需要同时保持有效" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"TH09 " +"中一个攻击函数的大部分逻辑已经还原,但编译器对临时结果的存储安排仍然与原版不同。剩下的问题在于:这些结果的生命周期应该多长,编译器何时可以复用它们的存储空间?" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"{ph0}GPT-6-Sol 的一次工作记录{ph1}表明,尝试几种常见的源码写法后,差异仍未消除。后来,{ph2}GPT-6.1-Sol " +"重新研究这个问题{ph3},提出了一个有价值的假设:关键可能在于这些临时值的生命周期。" + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"这个函数会产生临时结果,再把它们复制到动画的位置数据中。在 C++ " +"中,临时结果会一直存在,直到使用它的表达式执行完毕。把实际操作放进同一个表达式,就能让这些结果同时存活,编译器也就不能为它们全部复用同一块存储空间。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"其中一个结果仍然与稍后用于碰撞检查的值共享存储。给那个值单独的生命周期后,最后一处重叠也消失了。经过几次有针对性的实验,{ph0}一次干净的重新构建确认,整个函数都已匹配{ph1}。" + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"我感兴趣的是,发现与验证如何共同推进工作。生命周期的假设给 agent 指明了新方向;编译器的反馈又帮助它逐步调整源码,直到找到匹配的写法。" + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "换一种控制流结构" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"TH09 的另一个函数说明了,新方向为什么重要。这次的难点是多个分支如何共享末尾的操作。{ph0}GPT-6.1-Sol " +"之前的工作{ph1}已经让函数的一些部分匹配,但分支汇合的方式仍与原版不同。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra " +"改写了外围的控制流图{ph1},让主要路径汇入共同的最终更新与返回。在这种源码结构下,编译器合并分支的方式与原版一致。整个函数实现了匹配,{ph2}另一次独立的重新构建也确认了这一结果{ph3}。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}换一种表达方式,打开了更有价值的搜索空间。{ph1} 这两个例子让我认真看待通用模型的能力:agent " +"可能花很长时间尝试局部变化,才找到一种更好的整体写法。" + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"不过,后来的工作也继承了之前的源码和失败记录。这些积累本身就是优势的一部分。历史记录让我们可以检查发现及其验证过程;要区分模型能力和继承经验各自带来的帮助,还需要对照实验。" + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"这正是我觉得有趣的地方。有些进展来自新的表达方式,剩下的大量工作则是在熟悉的编译器上试验不同写法。其中有多少需要广泛的推理能力?又有多少可以通过反复接触这个编译器和这些代码来学会?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "为什么专用模型可能做得很好?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"东方系列给了我们一个具体的理由,去期待经验积累能发挥作用。大量游戏代码出自同一个作者 " +"ZUN,因此,把反复出现的编程习惯作为初始假设是合理的。代码仓库也提供了实际例子:相似的循环和辅助函数组织方式,曾为其他游戏的重建提供假设。" + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "把编译器也考虑进去,这些源码模式就更加具体了。在固定版本和选项下,源码的小变化可能稳定地产生不同的机器码。其中一些规律藏得很深。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"以 TH095 为例,{ph0}连局部变量的名字,都可能改变 VC7.1 " +"为它安排的存储位置{ph1}。只移动声明并不能解决布局问题,但先前重建的一个背景函数揭示了会影响编译器选择的命名模式。这为{ph2}重建 " +"{ph3}{ph4}提供了更有希望的假设。" + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "把这个模式用于表示文件大小的变量,不增加额外存储就得到了所需布局。随后,整个函数实现了匹配。" + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "这类细节非常具体,通用模型第一次接触时未必知道。而针对这个编译器训练的专用模型,可以接触许多类似案例,学会哪些源码变化值得优先尝试。" + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"当我们已经理解函数行为,只剩最后的匹配差异时,这个机会尤其明显。此时的问题是:这个编译器会把哪一种普通写法编译成眼前的指令?专用训练可能让模型更高效地提出这些写法,而最终由目标程序决定哪些假设成立。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"但这些模式必须保留适用的上下文。TH08 使用的 Visual C++ 版本早于 TH095 和 TH09。TH04 用的是另一种 DOS " +"时代的编译器,其{ph0}玩家逻辑重建{ph1}需要不同的假设,既涉及源码写法,也涉及编译后的代码如何链接成可执行文件。同一作者为我们提供了先验,具体目标则告诉我们它是否适用。区分这些情况,也是专用模型需要学会的事。" + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "这些经验应该存在哪里?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"在决定通过训练让模型学会这些模式之前,我会先看看代码仓库里已有的知识。在{ph0}上一篇文章{ph1}中,我写过:仓库正在成为项目的工作记忆。这里保存着对编译器的认识,也保存着相关源码和失败实验,让这些经验有据可查。" + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"检索这些记录后,agent 可以从已知结果出发,看看我们是如何得到它的,也可以避开在相同条件下已经失败的方案。模型的参数没有改变,工作的起点却提高了。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"重建 TH09 的敌人生成函数时,{ph0}GPT-6-Luna-max 的一次工作{ph1}从 TH08 " +"对应的源码中找到了假设。之前的写法提示了循环该如何组织,以及内部失败该如何处理。TH09 " +"自身的证据补上了游戏特有的细节,干净的重新构建确认了整个函数的匹配。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}“模型不知道这个编译器特性”和“模型不会利用它”,是两个不同的问题。{ph1} " +"检索可能解决前者,但把知识变成有价值的候选源码,仍然需要能力。如果候选方案失败了,模型还得判断这次结果对下一次尝试意味着什么。知道相关模式,只是这个过程的起点。" + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"所以,在任何对照实验中,我都会加入一个具备良好检索能力的小型通用模型。给它相同的经验库,才能看清训练究竟增加了什么:更好的候选方案、更好的反馈后决策,还是两者都有?" + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "学习选择下一个有价值的实验" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"反馈之后如何决策,是我最想研究的部分。在 agent " +"驱动的重建中,模型提出解释,再用程序来验证。即使候选方案失败了,结果也可能缩小剩余的可能性,提示下一步更值得尝试什么。" + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "再看前面的临时结果例子。最终源码展示了成功的写法,但得到它的过程包含更多信息。下面的每次实验,都帮助我们确定了还有什么需要改变。" + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "实验" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "结果告诉了我们什么" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "尝试另一种复制结果的方式" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "复制代码改变了,但函数仍有差异。" + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "直接使用返回值" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "复制方式与原版一致,但临时存储布局仍有差异。" + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "让临时结果同时保持有效" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "它们得到了各自的存储空间,但其中一个仍与稍后用于碰撞检查的值重叠。" + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "让碰撞检查的值拥有独立存储" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "干净的重新构建确认了整个函数的匹配。" + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "选自前面攻击函数的重建实验,按每次得到的认识整理。" + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"保存这个过程的训练记录,比单独保存最终源码能教会模型更多东西。它把每个改动、观察到的结果和下一步决策联系起来。无效的尝试也值得保留:后来的 agent " +"可以据此知道,在这个上下文中,哪些假设已经检验过。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}我希望模型学会如何利用反馈。{ph1} " +"结果没有变化,可能意味着该重新考虑这个改动;差异发生变化,则可能指向另一个原因。当局部修改不再提供有效信息时,agent " +"应该可以重新考虑源码的整体表达,或者回头检查证据。" + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"学会这些选择,需要自主性。有时,更有价值的下一步是检查另一个调用者,而不是再修改一次源码并编译。如果强制按照固定顺序改写,就会剥夺这种选择,也失去一部分我们希望模型学会的行为。" + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "为什么逆向工程值得用来探索强化学习" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"范围明确的重建任务,为研究这些选择提供了一个实际环境。目标和编译器版本固定之后,许多源码实验都能快速给出可重复的反馈。agent " +"可以编译候选源码、检查差异,再根据观察选择下一步。" + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"强化学习可以利用这些反馈,训练模型的决策过程。候选源码通过明确定义的检查,就给出了一个具体成果;而尝试的过程,让我们可以看到实现它花了多少功夫。" + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"已有研究支持这个方向。{ph0}LLM4Decompile{ph1}研究专门用于反编译的模型。{ph2}AutoDecompiler{ph3}利用编译和执行反馈,训练多轮改进能力。这些研究关注的是功能还原。对于我们的工作,我会以它们为起点,研究一个相关任务:找到能复现历史编译器输出的源码。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"不过,要得到这样一个定义明确的任务,有时得先确定函数负责哪些资源,或者设计新的方法观察程序运行时的行为。在 TH08 " +"中,{ph0}一次碰撞差异最终追溯到原版处理浮点计算的方式{ph1}。agent 必须先弄清楚该测量什么,才能验证有价值的修正。" + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "这提示了能力全面的模型的另一个作用:先把问题变得可验证。验证手段建立起来后,我们才可以研究,学出来的搜索策略能走多远。" + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "当验证器出错时" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"一旦用某项检查来训练模型,它的覆盖范围就会成为学习环境的一部分。我把这种参考标准或验证器称为 " +"oracle。即使它能给出可重复的答案,我们也必须知道,这个答案覆盖了什么。" + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 " +"展示了检查范围之外可能藏着多少问题。一些重建函数使用了错误的浮点常量,却仍然通过了精确比较。比较器会先调整重定位地址,再检查指令;但只有明确登记过的常量,才会进一步检查地址指向的值。其他常量引用,即使值没被检查,也可能通过。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"为了补上这个漏洞,{ph0}一次更全面的审计{ph1}在已经通过检查的函数中找到了错误常量。有一个计算中,重建源码加的是 {ph2},而原版加的是 " +"{ph3}。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}如果用旧检查的结果作为奖励,模型可能学会生成错误的重建源码。{ph1} 我们没有用这个验证器训练 RL " +"模型;实际观察到的是检查本身的漏洞。但如果把它用作奖励,同一个盲点也会进入学习环境。" + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"功能测试也可能存在类似盲点。{ph0}针对 LLM " +"反编译器的差分模糊测试研究{ph1}发现,在已有测试之外,程序行为仍可能不同。因此,理解“测试通过”时,必须看它实际覆盖了哪些情况;理解“指令匹配”时,也必须看它检查了哪些字节和数据。" + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"在把任何一种检查用作奖励之前,我都会用刻意构造的错误来测试它。我还会把最终验收机制放在候选源码可修改的范围之外,让模型通过正确重建来满足检查。否则,直接复制目标程序的字节数组,也可能骗过简单的评分,却没有还原出有用的源码。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "{ph0}改进模型和改进它的验证器,属于同一个研究问题。{ph1} 模型越擅长优化我们给它的反馈,我们就越需要理解反馈本身。" + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "值得做的对照实验" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"具备这些检查之后,我会从一组固定的 VC7.1 " +"任务开始比较。先为强通用模型和小型通用模型建立基线,再给小模型加入仓库知识,观察检索带来的变化。接着比较监督训练的专用模型,以及在此基础上进行 RL " +"训练的版本,看看训练增加了什么。" + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"为了让比较有意义,每个模型都应获得相同的目标证据和工具。专门比较训练效果时,还要固定基础模型和可用知识。重复实验有助于区分可靠的搜索策略与偶然成功的候选方案。" + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"我还会区分两种起点:从指令开始重建函数,以及在已有源码中消除最后几处差异。专用模型可能很擅长后者,而通用模型承担了到达这个阶段的大部分工作。分别评估,才能看清这种分工。" + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"两类任务都需要真正未见过的测试案例。东方系列的相关游戏会共享引擎代码,只留出某个游戏,仍可能让几乎相同的函数进入训练集。我会改为按相关源码家族留出测试集,并把它们通过验证的答案同时排除在训练数据和检索库之外。" + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"在这些案例上,要统计的是完整、独立验证过的匹配成果。给每个模型相同的候选数量或编译次数预算,可以比较搜索质量。记录总耗时和总成本,包括编译,才能知道这种质量是否转化成了高效的工作流。训练成本也要单独计算。" + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"两种角度都重要。一个便宜的提议,如果导致大量无效编译,整个工作流仍可能很贵。反过来,较慢的模型如果更早找到有价值的实验,也可能更划算。对照实验应当反映这些成本。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"只统计通过验收的结果,也能帮助我们合理看待中间进展。TH09 " +"的一个{ph0}录像保存候选方案{ph1}看起来很有希望,因为编译后函数的大小符合预期,但完整比较仍发现大量差异。编译器改变指令排列,也可能让候选源码看起来更接近,却没有解决根本问题。这些诊断可以指导下一步,但若要奖励“变得更接近”,我会先对照完整验收检查,确认这种奖励有效。" + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"我想看这些结果呈现出什么规律。如果专用模型在熟悉的编译器上表现很好,换了工具链后,这种优势还在吗?当双方都拥有良好的检索能力时,训练还能增加多少价值?这些答案能帮助我们决定,每类模型最适合用在哪里。" + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "这意味着怎样的 agent?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"如果不同模型在不同阶段各有所长,一种有价值的安排可能是:让能力全面的 agent " +"可以调用专用模型。当任务变成一种熟悉的编译器搜索时,它可以请专用模型提出候选方案。如果结果开始说不通,通用 agent " +"可以回头检查目标证据,或者调查测量本身。" + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"在这样的安排中,专用模型成为 agent 随着调查进展可以选择的工具。agent 仍然拥有改变方向的自由,而这正是前面那些突破发生的重要条件。" + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"这自然延续了上一篇文章中谈到的工业化转变。能够开展更多实验,会改变我们组织工作的方式,也让我们有理由追问:哪些决策需要全面的判断,哪些可以通过反复积累某项具体技艺来改善?" + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"目前,最强的通用模型解决了我过去没能解决的问题,因此在我的工作流中占据了一席之地。正是这些成功,让我想更仔细地研究过程:有多少依赖模型能力的广度?又有多少可以交给专门学习这类重建的模型?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "{ph0}这些代码仓库让我们有机会验证这个问题。{ph1} 我想利用这些记录建立对照实验,看看我们能学到什么。" + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "证据与模型归属" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"这些例子来自链接提交中记录的历史函数级比较。整款游戏的运行时检查属于另一个里程碑。相关源码与匹配记录核查于 2026 年 10 月 13 日。" + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"TH09 中的标签 {ph0} 对应 GPT-6-Astra。{ph1} " +"会随当时使用的模型变化,因此仅凭这个标签无法确定某次运行的具体模型。其他引用提交中的明确模型名,提供了对应的归属记录;这些历史记录并没有统一的单次运行成本或投入统计。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "{ph0}TH09 临时值生命周期:{ph1}{ph2}早期上下文检查{ph3}与{ph4}完整的干净重建{ph5}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front 回调:{ph1}{ph2}未匹配的诊断区域{ph3}、{ph4}Astra " +"提出的新控制流图{ph5}与{ph6}通过验收的重新编译检查{ph7}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}编译器知识:{ph1}{ph2}TH095 标识符分桶规律的复用{ph3}、{ph4}TH04 " +"玩家源码与链接顺序{ph5}、{ph6}Luna 完成的 TH09 敌人生成函数匹配{ph7}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}检查与诊断:{ph1}{ph2}TH08 浮点常量审计{ph3}、{ph4}TH08 数值问题调查{ph5}、{ph6}TH09 " +"录像保存重建{ph7}。" + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "文中提出的专用模型与 RL 对照,属于未来实验。项目历史为这些想法提供了依据;本文尚未评估经过训练的专用模型。" + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "逆向工程需要更大的模型吗? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "东方重建让我如何思考通用模型、专用模型,以及怎样从编译器反馈中学会提出更好的假设。" + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "在本页" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "模型与逆向工程随笔" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "重建实验选例" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "回到顶部" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "{ph0}详细证据记录{ph1}包含历史比较结果与实验背景。" + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "作者 N0zoM1z0 · 2026 年 10 月 13 日 · 待审草稿" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "安装指南" diff --git a/website/locales/zh-TW/messages.po b/website/locales/zh-TW/messages.po index fe632d045..af7b68bcd 100644 --- a/website/locales/zh-TW/messages.po +++ b/website/locales/zh-TW/messages.po @@ -8,76 +8,77 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Initial-Translation: Machine-assisted Traditional Chinese baseline; community review welcome\n" -#: website/public/blog/index.html:108 +#: website/public/blog/index.html:103 msgctxt "page:blog/index.html" msgid "Skip to content" msgstr "跳轉到內容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/blog/index.html:190 +#: website/public/blog/index.html:194 #, python-brace-format msgctxt "page:blog/index.html" msgid "{ph0}Home{ph1} / Blog" msgstr "{ph0}首頁{ph1} /部落格" -#: website/public/blog/index.html:191 +#: website/public/blog/index.html:195 msgctxt "page:blog/index.html" msgid "Blog." msgstr "部落格。" -#: website/public/blog/index.html:192 +#: website/public/blog/index.html:196 msgctxt "page:blog/index.html" msgid "Thoughts on reverse engineering." msgstr "逆向工程的思考。" #. {ph0}: <br /> -#: website/public/blog/index.html:196 +#: website/public/blog/index.html:214 #, python-brace-format msgctxt "page:blog/index.html" msgid "Game reconstruction{ph0}Essay" msgstr "遊戲重建{ph0}論文" -#: website/public/blog/index.html:198 +#: website/public/blog/index.html:216 msgctxt "page:blog/index.html" msgid "The industrial revolution in reverse engineering" msgstr "逆向工程的工業革命" -#: website/public/blog/index.html:199 +#: website/public/blog/index.html:217 msgctxt "page:blog/index.html" msgid "" "What manual RE and reconstructing TH08, TH095 and TH04 taught me about " "agents, verification and knowledge that compounds across projects." msgstr "什麼手動重新和重建TH08,TH095和TH04教我關於程式設計助手,驗證和知識,跨專案的化合物。" -#: website/public/blog/index.html:204 +#: website/public/blog/index.html:207 website/public/blog/index.html:222 msgctxt "page:blog/index.html" msgid "Read the article" msgstr "閱讀文章" -#: website/public/blog/index.html:207 +#: website/public/blog/index.html:225 msgctxt "page:blog/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "透過N0zoM1z0*10十月2026" #. {ph0}: <span aria-hidden="true"> #. {ph1}: </span> -#: website/public/blog/index.html:226 -#: website/public/blog/touhou-reconstruction/index.html:1076 -#: website/public/examples/dino-lab/index.html:471 -#: website/public/faq/index.html:569 -#: website/public/first-investigation/index.html:519 -#: website/public/get-started/index.html:878 -#: website/public/guides/browser/index.html:494 -#: website/public/guides/index.html:278 -#: website/public/guides/javascript/index.html:499 -#: website/public/guides/native/index.html:505 website/public/index.html:1187 -#: website/public/showcase/aegis/index.html:804 -#: website/public/showcase/ctf/index.html:773 -#: website/public/showcase/dx-ball/index.html:781 -#: website/public/showcase/index.html:313 -#: website/public/showcase/notion/index.html:627 -#: website/public/showcase/th04/index.html:796 +#: website/public/blog/index.html:244 +#: website/public/blog/reverse-engineering-models/index.html:883 +#: website/public/blog/touhou-reconstruction/index.html:1080 +#: website/public/examples/dino-lab/index.html:475 +#: website/public/faq/index.html:573 +#: website/public/first-investigation/index.html:523 +#: website/public/get-started/index.html:882 +#: website/public/guides/browser/index.html:507 +#: website/public/guides/index.html:282 +#: website/public/guides/javascript/index.html:503 +#: website/public/guides/native/index.html:509 website/public/index.html:1191 +#: website/public/showcase/aegis/index.html:808 +#: website/public/showcase/ctf/index.html:777 +#: website/public/showcase/dx-ball/index.html:785 +#: website/public/showcase/index.html:317 +#: website/public/showcase/notion/index.html:631 +#: website/public/showcase/th04/index.html:800 #, python-brace-format msgctxt "shared" msgid "{ph0}↑{ph1} Top" @@ -96,6 +97,8 @@ msgid "" msgstr "對逆向工程的思考,借鑑與 REA 和AI程式設計助手。" #: website/public/blog/index.html:75 website/public/blog/index.html:88 +#: website/public/blog/reverse-engineering-models/index.html:75 +#: website/public/blog/reverse-engineering-models/index.html:88 #: website/public/blog/touhou-reconstruction/index.html:75 #: website/public/blog/touhou-reconstruction/index.html:88 #: website/public/examples/dino-lab/index.html:75 @@ -129,112 +132,117 @@ msgid "" "agent." msgstr "REA-瞭解軟體的工作原理。 逆向工程與你的程式設計助手." -#: website/public/blog/index.html:113 -#: website/public/blog/touhou-reconstruction/index.html:113 -#: website/public/examples/dino-lab/index.html:114 -#: website/public/faq/index.html:113 -#: website/public/first-investigation/index.html:113 -#: website/public/get-started/index.html:113 -#: website/public/guides/browser/index.html:113 -#: website/public/guides/index.html:113 -#: website/public/guides/javascript/index.html:113 -#: website/public/guides/native/index.html:113 website/public/index.html:115 -#: website/public/showcase/aegis/index.html:114 -#: website/public/showcase/ctf/index.html:113 -#: website/public/showcase/dx-ball/index.html:113 -#: website/public/showcase/index.html:113 -#: website/public/showcase/notion/index.html:113 -#: website/public/showcase/th04/index.html:113 +#: website/public/blog/index.html:108 +#: website/public/blog/reverse-engineering-models/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/examples/dino-lab/index.html:109 +#: website/public/faq/index.html:108 +#: website/public/first-investigation/index.html:108 +#: website/public/get-started/index.html:108 +#: website/public/guides/browser/index.html:108 +#: website/public/guides/index.html:108 +#: website/public/guides/javascript/index.html:108 +#: website/public/guides/native/index.html:108 website/public/index.html:110 +#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/index.html:108 +#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/th04/index.html:108 msgctxt "shared" msgid "REA home" msgstr "REA 首頁" -#: website/public/blog/index.html:117 -#: website/public/blog/touhou-reconstruction/index.html:117 -#: website/public/examples/dino-lab/index.html:118 -#: website/public/faq/index.html:117 -#: website/public/first-investigation/index.html:117 -#: website/public/get-started/index.html:117 -#: website/public/guides/browser/index.html:117 -#: website/public/guides/index.html:117 -#: website/public/guides/javascript/index.html:117 -#: website/public/guides/native/index.html:117 website/public/index.html:119 -#: website/public/showcase/aegis/index.html:118 -#: website/public/showcase/ctf/index.html:117 -#: website/public/showcase/dx-ball/index.html:117 -#: website/public/showcase/index.html:117 -#: website/public/showcase/notion/index.html:117 -#: website/public/showcase/th04/index.html:117 +#: website/public/blog/index.html:112 +#: website/public/blog/reverse-engineering-models/index.html:112 +#: website/public/blog/touhou-reconstruction/index.html:112 +#: website/public/examples/dino-lab/index.html:113 +#: website/public/faq/index.html:112 +#: website/public/first-investigation/index.html:112 +#: website/public/get-started/index.html:112 +#: website/public/guides/browser/index.html:112 +#: website/public/guides/index.html:112 +#: website/public/guides/javascript/index.html:112 +#: website/public/guides/native/index.html:112 website/public/index.html:114 +#: website/public/showcase/aegis/index.html:113 +#: website/public/showcase/ctf/index.html:112 +#: website/public/showcase/dx-ball/index.html:112 +#: website/public/showcase/index.html:112 +#: website/public/showcase/notion/index.html:112 +#: website/public/showcase/th04/index.html:112 msgctxt "shared" msgid "Main navigation" msgstr "主導航" -#: website/public/blog/index.html:126 -#: website/public/blog/touhou-reconstruction/index.html:126 -#: website/public/examples/dino-lab/index.html:127 -#: website/public/faq/index.html:126 -#: website/public/first-investigation/index.html:126 -#: website/public/get-started/index.html:126 -#: website/public/guides/browser/index.html:126 -#: website/public/guides/index.html:126 -#: website/public/guides/javascript/index.html:126 -#: website/public/guides/native/index.html:126 website/public/index.html:128 -#: website/public/showcase/aegis/index.html:127 -#: website/public/showcase/ctf/index.html:126 -#: website/public/showcase/dx-ball/index.html:126 -#: website/public/showcase/index.html:126 -#: website/public/showcase/notion/index.html:126 -#: website/public/showcase/th04/index.html:126 +#: website/public/blog/index.html:130 +#: website/public/blog/reverse-engineering-models/index.html:130 +#: website/public/blog/touhou-reconstruction/index.html:130 +#: website/public/examples/dino-lab/index.html:131 +#: website/public/faq/index.html:130 +#: website/public/first-investigation/index.html:130 +#: website/public/get-started/index.html:130 +#: website/public/guides/browser/index.html:130 +#: website/public/guides/index.html:130 +#: website/public/guides/javascript/index.html:130 +#: website/public/guides/native/index.html:130 website/public/index.html:132 +#: website/public/showcase/aegis/index.html:131 +#: website/public/showcase/ctf/index.html:130 +#: website/public/showcase/dx-ball/index.html:130 +#: website/public/showcase/index.html:130 +#: website/public/showcase/notion/index.html:130 +#: website/public/showcase/th04/index.html:130 msgctxt "shared" msgid "REA on GitHub" msgstr "在 GitHub 檢視 REA" -#: website/public/blog/index.html:146 -#: website/public/blog/touhou-reconstruction/index.html:146 -#: website/public/examples/dino-lab/index.html:147 -#: website/public/faq/index.html:146 -#: website/public/first-investigation/index.html:146 -#: website/public/get-started/index.html:146 -#: website/public/guides/browser/index.html:146 -#: website/public/guides/index.html:146 -#: website/public/guides/javascript/index.html:146 -#: website/public/guides/native/index.html:146 website/public/index.html:148 -#: website/public/showcase/aegis/index.html:147 -#: website/public/showcase/ctf/index.html:146 -#: website/public/showcase/dx-ball/index.html:146 -#: website/public/showcase/index.html:146 -#: website/public/showcase/notion/index.html:146 -#: website/public/showcase/th04/index.html:146 +#: website/public/blog/index.html:150 +#: website/public/blog/reverse-engineering-models/index.html:150 +#: website/public/blog/touhou-reconstruction/index.html:150 +#: website/public/examples/dino-lab/index.html:151 +#: website/public/faq/index.html:150 +#: website/public/first-investigation/index.html:150 +#: website/public/get-started/index.html:150 +#: website/public/guides/browser/index.html:150 +#: website/public/guides/index.html:150 +#: website/public/guides/javascript/index.html:150 +#: website/public/guides/native/index.html:150 website/public/index.html:152 +#: website/public/showcase/aegis/index.html:151 +#: website/public/showcase/ctf/index.html:150 +#: website/public/showcase/dx-ball/index.html:150 +#: website/public/showcase/index.html:150 +#: website/public/showcase/notion/index.html:150 +#: website/public/showcase/th04/index.html:150 msgctxt "shared" msgid "Join REA on Discord" msgstr "加入 REA 的 Discord 社群" -#: website/public/blog/index.html:165 -#: website/public/blog/touhou-reconstruction/index.html:165 -#: website/public/examples/dino-lab/index.html:166 -#: website/public/faq/index.html:165 -#: website/public/first-investigation/index.html:165 -#: website/public/get-started/index.html:165 -#: website/public/guides/browser/index.html:165 -#: website/public/guides/index.html:165 -#: website/public/guides/javascript/index.html:165 -#: website/public/guides/native/index.html:165 website/public/index.html:167 -#: website/public/showcase/aegis/index.html:166 -#: website/public/showcase/ctf/index.html:165 -#: website/public/showcase/dx-ball/index.html:165 -#: website/public/showcase/index.html:165 -#: website/public/showcase/notion/index.html:165 -#: website/public/showcase/th04/index.html:165 +#: website/public/blog/index.html:169 +#: website/public/blog/reverse-engineering-models/index.html:169 +#: website/public/blog/touhou-reconstruction/index.html:169 +#: website/public/examples/dino-lab/index.html:170 +#: website/public/faq/index.html:169 +#: website/public/first-investigation/index.html:169 +#: website/public/get-started/index.html:169 +#: website/public/guides/browser/index.html:169 +#: website/public/guides/index.html:169 +#: website/public/guides/javascript/index.html:169 +#: website/public/guides/native/index.html:169 website/public/index.html:171 +#: website/public/showcase/aegis/index.html:170 +#: website/public/showcase/ctf/index.html:169 +#: website/public/showcase/dx-ball/index.html:169 +#: website/public/showcase/index.html:169 +#: website/public/showcase/notion/index.html:169 +#: website/public/showcase/th04/index.html:169 msgctxt "shared" msgid "Follow REA on X" msgstr "在 X 上關注 REA" -#: website/public/blog/index.html:226 +#: website/public/blog/index.html:244 msgctxt "page:blog/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/blog/touhou-reconstruction/index.html:108 +#: website/public/blog/touhou-reconstruction/index.html:103 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -243,35 +251,35 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:190 +#: website/public/blog/touhou-reconstruction/index.html:194 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Touhou reconstruction" msgstr "{ph0}首頁{ph1} / {ph2}部落格{ph3} / 東方遊戲重建" -#: website/public/blog/touhou-reconstruction/index.html:194 +#: website/public/blog/touhou-reconstruction/index.html:198 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Essay · Touhou reconstruction" msgstr "隨筆 · 東方遊戲重建" -#: website/public/blog/touhou-reconstruction/index.html:195 +#: website/public/blog/touhou-reconstruction/index.html:199 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The industrial revolution in reverse engineering." msgstr "逆向工程的工業革命。" -#: website/public/blog/touhou-reconstruction/index.html:196 +#: website/public/blog/touhou-reconstruction/index.html:200 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "By N0zoM1z0 · 10 October 2026" msgstr "作者 N0zoM1z0 · 2026 年 10 月 10 日" -#: website/public/blog/touhou-reconstruction/index.html:198 +#: website/public/blog/touhou-reconstruction/index.html:202 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Takeaway" msgstr "要點" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:200 +#: website/public/blog/touhou-reconstruction/index.html:204 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -281,7 +289,7 @@ msgstr "{ph0}讓程式設計助手自主開展調查。{ph1}明確目標和驗 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:205 +#: website/public/blog/touhou-reconstruction/index.html:209 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -293,7 +301,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:210 +#: website/public/blog/touhou-reconstruction/index.html:214 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -303,7 +311,7 @@ msgstr "{ph0}結論要由證據決定。{ph1}說得再肯定,也需要驗證 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:215 +#: website/public/blog/touhou-reconstruction/index.html:219 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -313,7 +321,7 @@ msgstr "{ph0}驗證基準本身也要測試。{ph1}故意給它應當拒絕的 #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:220 +#: website/public/blog/touhou-reconstruction/index.html:224 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -321,65 +329,65 @@ msgid "" "methods are still taking shape. There is plenty left to explore." msgstr "{ph0}我們正處於逆向工程工業革命的早期。{ph1}方法還在成形,還有很多值得探索的地方。" -#: website/public/blog/touhou-reconstruction/index.html:232 +#: website/public/blog/touhou-reconstruction/index.html:236 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "How experience compounds" msgstr "經驗如何產生複利" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:233 +#: website/public/blog/touhou-reconstruction/index.html:237 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Human direction{ph1} · Goal and acceptance criteria" msgstr "{ph0}人來定方向{ph1} · 目標和驗收標準" -#: website/public/blog/touhou-reconstruction/index.html:321 +#: website/public/blog/touhou-reconstruction/index.html:325 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Autonomy" msgstr "自主探索" -#: website/public/blog/touhou-reconstruction/index.html:322 +#: website/public/blog/touhou-reconstruction/index.html:326 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Agent" msgstr "程式設計助手" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:323 +#: website/public/blog/touhou-reconstruction/index.html:327 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Choose an experiment.{ph0}Propose a hypothesis." msgstr "選擇實驗。{ph0}提出假設。" -#: website/public/blog/touhou-reconstruction/index.html:326 +#: website/public/blog/touhou-reconstruction/index.html:330 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Verification" msgstr "驗證" -#: website/public/blog/touhou-reconstruction/index.html:327 +#: website/public/blog/touhou-reconstruction/index.html:331 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Oracle" msgstr "驗證基準" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:328 +#: website/public/blog/touhou-reconstruction/index.html:332 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Test against a{ph0}concrete reference." msgstr "對照{ph0}具體的基準驗證。" -#: website/public/blog/touhou-reconstruction/index.html:331 +#: website/public/blog/touhou-reconstruction/index.html:335 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Repository" msgstr "程式碼儲存庫" -#: website/public/blog/touhou-reconstruction/index.html:332 +#: website/public/blog/touhou-reconstruction/index.html:336 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Working memory" msgstr "工作記憶" #. {ph0}: <br /> -#: website/public/blog/touhou-reconstruction/index.html:333 +#: website/public/blog/touhou-reconstruction/index.html:337 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Code, evidence,{ph0}checks and lessons." @@ -388,7 +396,7 @@ msgstr "程式碼、證據、{ph0}檢查和經驗。" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:335 +#: website/public/blog/touhou-reconstruction/index.html:339 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Mismatch{ph0}{ph1}Revise the hypothesis{ph2}" @@ -397,40 +405,40 @@ msgstr "不匹配{ph0}{ph1}修正假設{ph2}" #. {ph0}: <br /> #. {ph1}: <strong> #. {ph2}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:338 +#: website/public/blog/touhou-reconstruction/index.html:342 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "A better{ph0}{ph1}starting point{ph2}" msgstr "更好的{ph0}{ph1}起點{ph2}" -#: website/public/blog/touhou-reconstruction/index.html:341 +#: website/public/blog/touhou-reconstruction/index.html:345 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Reuse" msgstr "複用" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:342 +#: website/public/blog/touhou-reconstruction/index.html:346 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Pass{ph1} · Keep the result and its evidence" msgstr "{ph0}透過{ph1} · 保留結果及其證據" -#: website/public/blog/touhou-reconstruction/index.html:354 +#: website/public/blog/touhou-reconstruction/index.html:358 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Each project leaves the next with a better starting point. That includes " "fixing the checks when we discover a gap." msgstr "每個專案都為下一個專案留下更好的起點。發現檢查有漏洞時,也要把檢查修好。" -#: website/public/blog/touhou-reconstruction/index.html:361 +#: website/public/blog/touhou-reconstruction/index.html:365 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "In this article" msgstr "在本文中" #. {ph0}: <a href="#august"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:363 +#: website/public/blog/touhou-reconstruction/index.html:367 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}August 2026{ph1}" @@ -438,7 +446,7 @@ msgstr "{ph0}2026年8月{ph1}" #. {ph0}: <a href="#th08"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:364 +#: website/public/blog/touhou-reconstruction/index.html:368 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH08: the continuation{ph1}" @@ -446,7 +454,7 @@ msgstr "{ph0}TH08:接續前人的工作{ph1}" #. {ph0}: <a href="#different-approaches"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:365 +#: website/public/blog/touhou-reconstruction/index.html:369 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Two approaches{ph1}" @@ -454,7 +462,7 @@ msgstr "{ph0}兩種方法{ph1}" #. {ph0}: <a href="#th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:366 +#: website/public/blog/touhou-reconstruction/index.html:370 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH095: compounding{ph1}" @@ -462,7 +470,7 @@ msgstr "{ph0}TH095:經驗的複利{ph1}" #. {ph0}: <a href="#th04"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:367 +#: website/public/blog/touhou-reconstruction/index.html:371 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}TH04: across architectures{ph1}" @@ -470,7 +478,7 @@ msgstr "{ph0} TH04:跨架構{ph1}" #. {ph0}: <a href="#semantic-reconstruction"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:368 +#: website/public/blog/touhou-reconstruction/index.html:372 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}From exact to readable{ph1}" @@ -478,7 +486,7 @@ msgstr "{ph0}從精確到可讀{ph1}" #. {ph0}: <a href="#industrial-shift"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:371 +#: website/public/blog/touhou-reconstruction/index.html:375 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}The industrial shift{ph1}" @@ -486,18 +494,18 @@ msgstr "{ph0}工業化的轉變{ph1}" #. {ph0}: <a href="#possibilities"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:372 +#: website/public/blog/touhou-reconstruction/index.html:376 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}What becomes possible{ph1}" msgstr "{ph0}新的可能性{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:377 +#: website/public/blog/touhou-reconstruction/index.html:381 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What changed in August 2026" msgstr "2026年8月發生了什麼變化" -#: website/public/blog/touhou-reconstruction/index.html:378 +#: website/public/blog/touhou-reconstruction/index.html:382 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Before this work, I had done a lot of manual reverse engineering. I would " @@ -508,7 +516,7 @@ msgid "" msgstr "" "在這之前,我做過很多手工逆向。我會反覆檢視一個函式,直到能解釋它,再對照程式驗證這個解釋。想推進專案,就得親自花更多時間研究下一個函式,腦子裡也要記住越來越多的整體關係。" -#: website/public/blog/touhou-reconstruction/index.html:385 +#: website/public/blog/touhou-reconstruction/index.html:389 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Most of my RE work is on games. I reconstruct them so their behavior can be " @@ -519,7 +527,7 @@ msgstr "" "我的逆向工作主要圍繞遊戲。我希望透過重建弄清遊戲的行為,最終做出移植版或 " "mod。這篇文章來自這些經歷。方法可以遷移到其他領域,但每個領域都需要先明確:什麼可以用可靠的基準來驗證。" -#: website/public/blog/touhou-reconstruction/index.html:392 +#: website/public/blog/touhou-reconstruction/index.html:396 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In August 2026, I started exploring agent-driven RE seriously. I wanted to " @@ -529,7 +537,7 @@ msgid "" msgstr "" "2026 年 8 月,我開始認真探索讓程式設計助手做逆向。有了程式本身和常用開發工具,它究竟能走多遠?東方遊戲重建給了我一個足夠完整的專案來尋找答案。" -#: website/public/blog/touhou-reconstruction/index.html:398 +#: website/public/blog/touhou-reconstruction/index.html:402 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The early progress was startling. An investigation could keep moving without" @@ -541,7 +549,7 @@ msgid "" msgstr "" "早期的進展讓我吃驚。我不再需要為每一步作選擇,調查也能持續推進。對比失敗後,助手可能轉去檢視另一個呼叫方,寫一段診斷程式,再根據結果決定下一步。這種自主性改變了我的工作:我可以更多關注專案方向,以及檢查是否可靠。" -#: website/public/blog/touhou-reconstruction/index.html:407 +#: website/public/blog/touhou-reconstruction/index.html:411 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace got my attention first. Then I began wondering what would survive " @@ -549,7 +557,7 @@ msgid "" "had just learned?" msgstr "速度先引起了我的注意。隨後我開始想:當前專案結束後,什麼會留下來?下一個遊戲能不能用上我們剛學到的經驗?" -#: website/public/blog/touhou-reconstruction/index.html:414 +#: website/public/blog/touhou-reconstruction/index.html:418 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH08: building on human work" msgstr "TH08:接續前人的工作" @@ -558,7 +566,7 @@ msgstr "TH08:接續前人的工作" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/GensokyoClub/th08" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:415 +#: website/public/blog/touhou-reconstruction/index.html:419 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -570,7 +578,7 @@ msgstr "" "{ph0}TH08{ph1},也就是《東方永夜抄》,從接續{ph2}GensokyoClub " "的重建工作{ph3}開始。他們的公開原始碼提供了紮實的基礎,也留下了構建經驗和貢獻歷史。我在後續工作中保留了這些歷史。" -#: website/public/blog/touhou-reconstruction/index.html:424 +#: website/public/blog/touhou-reconstruction/index.html:428 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The imported history ends at the public 10 August checkpoint. My independent" @@ -580,7 +588,7 @@ msgstr "" "匯入的歷史截至 8 月 10 日的公開檢查點。我的獨立續作從 8 月 13 日開始。到 8 月 19 日,進度臺賬中已識別的 1,107 " "個遊戲函式都有了原始碼。" -#: website/public/blog/touhou-reconstruction/index.html:429 +#: website/public/blog/touhou-reconstruction/index.html:433 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A playable Linux reconstruction port was committed on 24 August, roughly " @@ -590,7 +598,7 @@ msgstr "" "8 月 24 日,我們提交了可玩的 Linux 重建移植版,距離開始續作約十一天。隨後做出了 Web 版。8 月 30 日,原生 Linux 64 " "位版釋出。" -#: website/public/blog/touhou-reconstruction/index.html:434 +#: website/public/blog/touhou-reconstruction/index.html:438 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "What struck me was that the work had reached a program people could run. " @@ -602,7 +610,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:441 +#: website/public/blog/touhou-reconstruction/index.html:445 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -615,12 +623,12 @@ msgid "" msgstr "" "這讓對照檢查成為工作的核心。我把這些基準稱為{ph0}驗證基準(oracle){ph1}。程式碼對比可以檢查重建函式是否復現原始指令;執行時檢查可以確認已走過的路徑是否到達預期狀態。助手提出解釋,再驗證它。發現不匹配,就有了具體的調查方向。" -#: website/public/blog/touhou-reconstruction/index.html:449 +#: website/public/blog/touhou-reconstruction/index.html:453 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "An exact match with the wrong constant" msgstr "常量錯了,卻仍然“精確匹配”" -#: website/public/blog/touhou-reconstruction/index.html:450 +#: website/public/blog/touhou-reconstruction/index.html:454 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "An oracle is software someone wrote. TH08 gave me a clear reminder of how " @@ -629,7 +637,7 @@ msgstr "校驗工具也是人寫的軟體。TH08 讓我清楚地看到,多少 #. {ph0}: <code>0.0</code> #. {ph1}: <code>128.0</code> -#: website/public/blog/touhou-reconstruction/index.html:454 +#: website/public/blog/touhou-reconstruction/index.html:458 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -640,7 +648,7 @@ msgstr "" "9 月,下游 Switch 移植版報告了一個 bug,最後追溯到道具自動收集。重建原始碼把玩家火力與 {ph0} 比較,而原版用的是 " "{ph1},即滿火力的閾值。" -#: website/public/blog/touhou-reconstruction/index.html:460 +#: website/public/blog/touhou-reconstruction/index.html:464 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Normal power is non-negative, so the reconstructed power check was " @@ -652,13 +660,13 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:467 +#: website/public/blog/touhou-reconstruction/index.html:471 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}Yet the function had already passed the exact comparison.{ph1}" msgstr "{ph0}可這個函式之前已經透過了精確對比。{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:473 +#: website/public/blog/touhou-reconstruction/index.html:477 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A rebuild can put a constant at a different address. The comparison tool " @@ -670,7 +678,7 @@ msgstr "" #. {ph0}: <code>128.0</code> #. {ph1}: <code>0.0</code> -#: website/public/blog/touhou-reconstruction/index.html:480 +#: website/public/blog/touhou-reconstruction/index.html:484 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -683,7 +691,7 @@ msgstr "漏洞就在這裡:工具可以把重建指令的引用地址調整為 #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th08/pull/13"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:486 +#: website/public/blog/touhou-reconstruction/index.html:490 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -695,7 +703,7 @@ msgstr "" "{ph0}9 月 2 日的修復{ph1}糾正了原始碼,並讓比較工具檢查被引用常量的實際位元組。隨後進行的{ph2}全面審計{ph3}檢查了 1,548 " "處浮點常量引用,又在五個已透過驗收的函式中發現十二處錯誤引用。" -#: website/public/blog/touhou-reconstruction/index.html:497 +#: website/public/blog/touhou-reconstruction/index.html:501 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The comparison now checks every such floating literal. Its tests include " @@ -705,7 +713,7 @@ msgstr "現在工具會檢查每一處這樣的浮點常量。測試還會故意 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:502 +#: website/public/blog/touhou-reconstruction/index.html:506 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -713,7 +721,7 @@ msgid "" "repairing the game." msgstr "{ph0}驗證基準本身也需要重建。{ph1}修復它,就是修復遊戲的一部分。" -#: website/public/blog/touhou-reconstruction/index.html:506 +#: website/public/blog/touhou-reconstruction/index.html:510 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That matters when the team is mostly one person working with agents. I " @@ -726,7 +734,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:514 +#: website/public/blog/touhou-reconstruction/index.html:518 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -739,7 +747,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:523 +#: website/public/blog/touhou-reconstruction/index.html:527 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -747,7 +755,7 @@ msgid "" " for the next batch.{ph1}" msgstr "{ph0}每完成一批工作,我們既得到了還原的程式碼,也改善了下一批工作的環境。{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:531 +#: website/public/blog/touhou-reconstruction/index.html:535 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Two different ideas of reconstruction" msgstr "兩種不同的重建理念" @@ -756,7 +764,7 @@ msgstr "兩種不同的重建理念" #. href="https://web.archive.org/web/20260909051514/https://github.com/GensokyoClub/th08#important- #. notice" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:532 +#: website/public/blog/touhou-reconstruction/index.html:536 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -767,14 +775,14 @@ msgstr "" "GensokyoClub 的{ph0}公開 " "README{ph1}明確表達了對這種工作的異議。公告說,專案完成前,後續開發將在私下進行。其中有這樣一段話:" -#: website/public/blog/touhou-reconstruction/index.html:543 +#: website/public/blog/touhou-reconstruction/index.html:547 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The rise of grifters (AI decompilations and ports) in this space taking from" " our work paints a bad image for future decompilation efforts…" msgstr "“這個領域裡出現了利用我們成果的投機者(AI 反編譯和移植專案),給未來的反編譯工作留下了不好的印象……”" -#: website/public/blog/touhou-reconstruction/index.html:549 +#: website/public/blog/touhou-reconstruction/index.html:553 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The notice also describes the psychological toll on the maintainers. Their " @@ -787,7 +795,7 @@ msgstr "" "公告也提到了維護者承受的心理壓力。他們的貢獻政策不接受主要由 AI 生成的 " "PR。他們用業餘時間投入了艱難的工作,這些成果讓我的續作成為可能。我尊重他們付出的努力。我想討論的分歧,是重建應當如何推進,以及貢獻應當如何評價。" -#: website/public/blog/touhou-reconstruction/index.html:558 +#: website/public/blog/touhou-reconstruction/index.html:562 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In the manual workflow I knew, developing an understanding of a function and" @@ -797,7 +805,7 @@ msgid "" msgstr "" "在我熟悉的手工流程中,理解一個函式和重建它,通常由同一個人完成。專案非常依賴這個人的專業能力。很多推理發生在工作過程中,所以對貢獻者本人的信任很重要。" -#: website/public/blog/touhou-reconstruction/index.html:565 +#: website/public/blog/touhou-reconstruction/index.html:569 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Existing projects already preserve knowledge in their source and build " @@ -805,7 +813,7 @@ msgid "" "pursue the next investigation on its own." msgstr "已有專案本就會在原始碼和構建工具中儲存知識。對我而言,變化在於:程式設計助手能利用這些知識,自主推進下一次調查。" -#: website/public/blog/touhou-reconstruction/index.html:570 +#: website/public/blog/touhou-reconstruction/index.html:574 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "In my continuation, I decide the objective and the standard for accepting a " @@ -816,7 +824,7 @@ msgid "" msgstr "" "在我的續作中,我來確定目標和驗收標準,助手有充分的調查自由。它提出的重建方案必須透過相應檢查。我希望其他人能夠看懂我們為什麼選擇這個實現,即使大部分工作由助手完成。" -#: website/public/blog/touhou-reconstruction/index.html:577 +#: website/public/blog/touhou-reconstruction/index.html:581 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This can be a difficult transition. Years of careful work may become the " @@ -826,7 +834,7 @@ msgid "" msgstr "" "這可能是一個艱難的轉變。多年的細緻工作,可能成為一個推進得更快的續作的基礎。這會帶來真實的歸屬與署名問題,也改變維護者在接受貢獻前需要了解的事情。" -#: website/public/blog/touhou-reconstruction/index.html:583 +#: website/public/blog/touhou-reconstruction/index.html:587 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The industrial analogy helps me think about this. In a craft, much of the " @@ -837,7 +845,7 @@ msgid "" msgstr "" "工業化的比喻有助於理解這一點。手工作業的過程往往依賴操作者的技藝。機器改變了這些技藝發揮作用的位置,但仍然需要人設計流程、識別錯誤產出。不同社群可以選擇接受多少這樣的變化。" -#: website/public/blog/touhou-reconstruction/index.html:591 +#: website/public/blog/touhou-reconstruction/index.html:595 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "My choice is to continue openly, with the inherited work credited and its " @@ -858,7 +866,7 @@ msgstr "我的選擇是公開繼續,註明繼承的工作並保留其歷史。 #. href="https://github.com/N0zoM1z0/th08/blob/d2a00f4acb4a13916e07a00bd13f714961714628/README.md#credits- #. and-provenance" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:597 +#: website/public/blog/touhou-reconstruction/index.html:601 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -869,14 +877,14 @@ msgstr "" "來源:GensokyoClub 的{ph0}README 公告{ph1}(於 2026 年 10 月 10 " "日核對)及其{ph2}貢獻政策{ph3}。上面的引文為節選譯文。TH08 的{ph4}貢獻署名與來源記錄{ph5}說明了獨立續作的起點。" -#: website/public/blog/touhou-reconstruction/index.html:615 +#: website/public/blog/touhou-reconstruction/index.html:619 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH095: experience starts compounding" msgstr "TH095:經驗開始產生複利" #. {ph0}: <a href="https://github.com/N0zoM1z0/th095"> #. {ph1}: </a> -#: website/public/blog/touhou-reconstruction/index.html:616 +#: website/public/blog/touhou-reconstruction/index.html:620 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -888,7 +896,7 @@ msgstr "" "{ph0}TH095{ph1},也就是《東方文花帖》,讓這些經驗的價值更容易看清。儲存庫於 8 月 29 " "日建立,當時臺賬中確認的遊戲函式數量為零。我們仍需研究遊戲本身,但已經更清楚如何開始重建,以及怎樣持續推進。" -#: website/public/blog/touhou-reconstruction/index.html:624 +#: website/public/blog/touhou-reconstruction/index.html:628 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "By 7 September, all 697 identified game functions had source. By 8 " @@ -899,7 +907,7 @@ msgstr "" "到 9 月 7 日,全部 697 個已識別遊戲函式都有了原始碼。9 月 8 日,其中 696 個透過了精確對比。9 月 9 日,整個程式完成連結。9 月" " 10 日,Windows i386 重建版被記錄為可玩,距離初始化約十二天。" -#: website/public/blog/touhou-reconstruction/index.html:631 +#: website/public/blog/touhou-reconstruction/index.html:635 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I found this more exciting than the first project's speed. A fresh target " @@ -907,7 +915,7 @@ msgid "" "present in the tools and in the way the project was organized." msgstr "這比第一個專案的速度更讓我興奮。新目標能受益於另一個遊戲的工作。經驗已經進入工具,也進入了專案的組織方式。" -#: website/public/blog/touhou-reconstruction/index.html:637 +#: website/public/blog/touhou-reconstruction/index.html:641 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For example, TH08 had taught us to pay attention to the assembled program " @@ -919,7 +927,7 @@ msgstr "" "例如,TH08 教會我們儘早關注整個程式。如果幾個還原函式依賴同一份狀態,分別對比它們仍然會留下一個關鍵問題:它們能否一起正常工作?這條經驗影響了 " "TH095 的整程式構建方式。" -#: website/public/blog/touhou-reconstruction/index.html:644 +#: website/public/blog/touhou-reconstruction/index.html:648 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A lesson that stays in my head is useful while I am there. Once it becomes a" @@ -929,7 +937,7 @@ msgid "" msgstr "" "經驗只記在我腦子裡,我在場時它才有用。變成其他會話能執行的檢查後,即使我離開,它仍能幫助專案。下一個助手可以利用檢查結果,不用重複當初得出這條經驗的調查。" -#: website/public/blog/touhou-reconstruction/index.html:650 +#: website/public/blog/touhou-reconstruction/index.html:654 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The floating-literal bug belongs in that memory too. It explains why " @@ -941,7 +949,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:656 +#: website/public/blog/touhou-reconstruction/index.html:660 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -950,7 +958,7 @@ msgid "" "actually new about its target." msgstr "{ph0}方法本身成了下一個遊戲的起始材料。{ph1}我們可以把更多精力放在新目標真正不同的地方。" -#: website/public/blog/touhou-reconstruction/index.html:664 +#: website/public/blog/touhou-reconstruction/index.html:668 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The same benefit is available to people joining later. They can inspect a " @@ -959,7 +967,7 @@ msgid "" "the way it does." msgstr "後來加入的人也能受益。他們可以檢視某個決定,重新執行檢查,再繼續工作。不用先重走整個專案的歷史,才能理解原始碼為何這樣寫。" -#: website/public/blog/touhou-reconstruction/index.html:672 +#: website/public/blog/touhou-reconstruction/index.html:676 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "TH04: the workflow survives a different architecture" msgstr "TH04:換了架構,工作方式仍然適用" @@ -968,7 +976,7 @@ msgstr "TH04:換了架構,工作方式仍然適用" #. {ph1}: </a> #. {ph2}: <a href="https://github.com/nmlgc/ReC98"> #. {ph3}: </a> -#: website/public/blog/touhou-reconstruction/index.html:673 +#: website/public/blog/touhou-reconstruction/index.html:677 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -981,7 +989,7 @@ msgstr "" "{ph0}TH04{ph1},也就是《東方幻想鄉》,把這套工作帶到了 PC-98 DOS 時代。這次是一個由四個程式協作的 16 " "位環境。理解硬體行為,需要和 Windows 遊戲不同的證據。已有的{ph2}ReC98 工作{ph3}同樣提供了寶貴的知識與原始碼材料。" -#: website/public/blog/touhou-reconstruction/index.html:682 +#: website/public/blog/touhou-reconstruction/index.html:686 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The DOS reconstruction is now working. In my manual testing, I played " @@ -992,7 +1000,7 @@ msgstr "" "DOS 重建版現在已經能執行。我手工打完了完整的 Normal 路線,看到結局,並檢查了存檔。目前正在做原生 64 位移植。先得到一個正常工作的 DOS" " 版,就為移植提供了參照。" -#: website/public/blog/touhou-reconstruction/index.html:688 +#: website/public/blog/touhou-reconstruction/index.html:692 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The architecture changed what we needed to investigate. It also changed the " @@ -1001,7 +1009,7 @@ msgid "" "next experiment." msgstr "架構改變了要調查的問題,也改變了用來驗證的編譯器和執行時。但助手依然能沿著問題找到結果,再用結果指導下一次實驗。" -#: website/public/blog/touhou-reconstruction/index.html:694 +#: website/public/blog/touhou-reconstruction/index.html:698 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Consider the transition from gameplay to an ending. We need to know what " @@ -1013,7 +1021,7 @@ msgstr "" "比如從遊戲過程切換到結局:哪些狀態需要跨越這個邊界?哪個程式負責它們?我們可以對照 DOS 原版調查。只要證據和檢查可用,助手就能像研究 Windows" " 遊戲一樣推進這個問題。" -#: website/public/blog/touhou-reconstruction/index.html:702 +#: website/public/blog/touhou-reconstruction/index.html:706 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This is why TH04 matters to the argument. A substantial platform change did " @@ -1021,7 +1029,7 @@ msgid "" "defined the problem; the workflow still gave us a way to solve it." msgstr "這就是 TH04 對這篇文章的意義。大幅的平臺變化,並沒有迫使我們重新發明一套工作方式。架構決定了問題,工作流程仍然提供瞭解決問題的方法。" -#: website/public/blog/touhou-reconstruction/index.html:708 +#: website/public/blog/touhou-reconstruction/index.html:712 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "For the 64-bit port, we can now examine the new implementation against " @@ -1035,7 +1043,7 @@ msgstr "做 64 位移植時,我們可以把新實現與 DOS 上已經還原的 #. {ph1}: </a > #. {ph2}: <a href="https://github.com/N0zoM1z0/th04/tree/port/modern-64" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:713 +#: website/public/blog/touhou-reconstruction/index.html:717 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1043,19 +1051,19 @@ msgid "" "testing{ph1} · {ph2}64-bit port{ph3}. The port remains in development." msgstr "截至 2026 年 10 月 10 日:{ph0}DOS 重建與手工測試{ph1} · {ph2}64 位移植{ph3}。移植仍在開發中。" -#: website/public/blog/touhou-reconstruction/index.html:726 +#: website/public/blog/touhou-reconstruction/index.html:730 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "From exact code to readable code" msgstr "從精確還原到可讀原始碼" -#: website/public/blog/touhou-reconstruction/index.html:727 +#: website/public/blog/touhou-reconstruction/index.html:731 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Once a reconstruction works, I want someone else to be able to understand " "it." msgstr "重建版能執行之後,我還希望別人能讀懂它。" -#: website/public/blog/touhou-reconstruction/index.html:731 +#: website/public/blog/touhou-reconstruction/index.html:735 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "To me, assembly and raw offsets can feel like old friends. I realise this is" @@ -1067,7 +1075,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:737 +#: website/public/blog/touhou-reconstruction/index.html:741 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1079,7 +1087,7 @@ msgid "" msgstr "" "這就需要{ph0}語義重建{ph1}。一個還原欄位可能仍然只有偏移作為標識。我們追蹤遊戲如何使用它,直到能解釋其作用,再依據證據賦予合適的名稱和型別。推理過程和原始碼一起儲存,後來的人就能知道這個解釋從何而來。" -#: website/public/blog/touhou-reconstruction/index.html:745 +#: website/public/blog/touhou-reconstruction/index.html:749 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "This becomes especially important for a port. An absolute address tells me " @@ -1091,14 +1099,14 @@ msgstr "" "移植時,語義尤其重要。絕對地址能告訴我資料在舊程式中的位置,卻很難幫助 64 " "位實現決定哪個物件應當持有這份狀態。要正確遷移行為,就得還原舊記憶體訪問背後的關係。" -#: website/public/blog/touhou-reconstruction/index.html:752 +#: website/public/blog/touhou-reconstruction/index.html:756 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The order I now use is:" msgstr "我現在採用這樣的順序:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:754 +#: website/public/blog/touhou-reconstruction/index.html:758 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1111,7 +1119,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:761 +#: website/public/blog/touhou-reconstruction/index.html:765 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1124,7 +1132,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:768 +#: website/public/blog/touhou-reconstruction/index.html:772 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1137,7 +1145,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:777 +#: website/public/blog/touhou-reconstruction/index.html:781 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1148,7 +1156,7 @@ msgstr "{ph0}再做現代平臺移植。{ph1}把已經確定的行為帶入新 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/blog/touhou-reconstruction/index.html:784 +#: website/public/blog/touhou-reconstruction/index.html:788 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1160,7 +1168,7 @@ msgid "" msgstr "" "第二階段的可玩構建,在第三階段成為{ph0}第二套驗證基準{ph1}。第一套檢查修改後的原始碼是否仍然復現原版相關程式碼和資料;第二套檢查重建程式是否能構建,並在實際測試的路徑上保持正確行為。" -#: website/public/blog/touhou-reconstruction/index.html:792 +#: website/public/blog/touhou-reconstruction/index.html:796 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "They catch different mistakes. A type change can alter the generated " @@ -1170,7 +1178,7 @@ msgid "" msgstr "" "它們能發現不同型別的錯誤。型別修改可能改變生成的指令。狀態歸屬的修改,可能讓遊戲的兩部分各自使用一份狀態。保留兩套檢查,助手就能在繼續重構之前,針對具體的失敗展開調查。" -#: website/public/blog/touhou-reconstruction/index.html:799 +#: website/public/blog/touhou-reconstruction/index.html:803 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "A name needs evidence of its own. An exact comparison cannot tell us whether" @@ -1184,7 +1192,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:806 +#: website/public/blog/touhou-reconstruction/index.html:810 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1199,7 +1207,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:817 +#: website/public/blog/touhou-reconstruction/index.html:821 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1207,12 +1215,12 @@ msgid "" "makes the recovered knowledge usable.{ph1} A port can then build on both." msgstr "{ph0}精確重建提供基準,語義重建讓還原的知識可用。{ph1}移植隨後建立在兩者之上。" -#: website/public/blog/touhou-reconstruction/index.html:826 +#: website/public/blog/touhou-reconstruction/index.html:830 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "What makes this an industrial shift" msgstr "為什麼這是工業化的轉變" -#: website/public/blog/touhou-reconstruction/index.html:827 +#: website/public/blog/touhou-reconstruction/index.html:831 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "These projects changed where I spent my attention. Once agents could carry " @@ -1222,7 +1230,7 @@ msgid "" msgstr "" "這些專案改變了我投入注意力的地方。助手能自主推進大部分調查之後,改善它們的工作環境,就成了我最值得做的事情之一。一項工具的改進,可以幫助之後所有需要它的函式。" -#: website/public/blog/touhou-reconstruction/index.html:834 +#: website/public/blog/touhou-reconstruction/index.html:838 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Autonomy matters here. The useful next step often becomes clear only after a" @@ -1232,7 +1240,7 @@ msgid "" msgstr "" "自主性在這裡很重要。下一步該怎麼做,常常在實驗失敗後才清楚。助手需要足夠的自由,沿著結果探索意料之外的方向。如果每一步都要等我指定,大部分工作仍然綁在我的注意力上。" -#: website/public/blog/touhou-reconstruction/index.html:841 +#: website/public/blog/touhou-reconstruction/index.html:845 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "I expect the agent to make wrong hypotheses. What matters is whether we can " @@ -1242,7 +1250,7 @@ msgid "" msgstr "" "我預期助手會提出錯誤假設。關鍵是我們能否驗證它們,並從結果中學習。失敗的檢查應該幫助它理解錯誤,再次嘗試。我仍要判斷:累積的證據是否足以支援某個專案里程碑。" -#: website/public/blog/touhou-reconstruction/index.html:848 +#: website/public/blog/touhou-reconstruction/index.html:852 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "REA gives the agent access to analysis tools. A question about a function's " @@ -1254,7 +1262,7 @@ msgstr "" "REA " "讓助手能夠使用分析工具。調查某函式的呼叫方時,它可以直接繼續檢查那個呼叫方。重建專案提供編譯器和自己的對照檢查。助手用它們驗證提出的原始碼,看看解釋在哪些地方成立。" -#: website/public/blog/touhou-reconstruction/index.html:855 +#: website/public/blog/touhou-reconstruction/index.html:859 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The TH08 bug shows why those checks deserve engineering attention of their " @@ -1269,7 +1277,7 @@ msgstr "" #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:862 +#: website/public/blog/touhou-reconstruction/index.html:866 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1285,7 +1293,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:879 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1297,7 +1305,7 @@ msgid "" msgstr "" "{ph0}我們正處於這場工業化轉變的早期。{ph1}許多基礎設施還不成熟。助手推進工作的速度,可能超過原有檢查的承受能力,所以流程也要一起發展。共享工具出現缺陷時,要修好它,並重查受影響的結果。下一個專案才能繼承更可靠的工具。" -#: website/public/blog/touhou-reconstruction/index.html:885 +#: website/public/blog/touhou-reconstruction/index.html:889 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "There is also a practical limit to any one conversation. It will end before " @@ -1309,7 +1317,7 @@ msgstr "任何一段對話都有實際的長度限制。大型重建完成之前 #. {ph0}: <a href="https://github.com/N0zoM1z0/touhou-reconstruction-factory" #. > #. {ph1}: </a > -#: website/public/blog/touhou-reconstruction/index.html:891 +#: website/public/blog/touhou-reconstruction/index.html:895 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1320,7 +1328,7 @@ msgstr "" "{ph0}Touhou Reconstruction " "Factory{ph1}正是為此而建立。它提供一種共用方式,讓專案把檢查和經驗傳遞下去。一個遊戲的工作,可以改善另一個遊戲的起點。" -#: website/public/blog/touhou-reconstruction/index.html:901 +#: website/public/blog/touhou-reconstruction/index.html:905 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That is what makes the industrial analogy meaningful to me. Experience " @@ -1328,12 +1336,12 @@ msgid "" "changes how much the next person—or the next agent—can get done." msgstr "這就是工業化比喻對我的意義:經驗開始進入別人也能使用的工具。改善工具,就能改變下一個人或下一個助手能完成多少工作。" -#: website/public/blog/touhou-reconstruction/index.html:909 +#: website/public/blog/touhou-reconstruction/index.html:913 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "The projects we can now consider" msgstr "現在值得嘗試的專案" -#: website/public/blog/touhou-reconstruction/index.html:910 +#: website/public/blog/touhou-reconstruction/index.html:914 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The pace matters because it changes the decision to begin. A game could be " @@ -1341,7 +1349,7 @@ msgid "" "than I could realistically give it. Many projects would stay ideas." msgstr "速度的意義在於,它改變了是否開始一個專案的決定。某個遊戲也許很值得逆向,卻需要我投入遠超現實所能承受的精力。很多專案因此一直停留在想法裡。" -#: website/public/blog/touhou-reconstruction/index.html:916 +#: website/public/blog/touhou-reconstruction/index.html:920 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "Now I can see a way to keep such a project moving through repeated " @@ -1355,7 +1363,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/blog/touhou-reconstruction/index.html:923 +#: website/public/blog/touhou-reconstruction/index.html:927 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1363,7 +1371,7 @@ msgid "" "accumulated knowledge would let an agent work on this reliably?{ph1}" msgstr "現在看到一個陌生程式,我會問:{ph0}怎樣的工具訪問、反饋和知識積累,能讓助手可靠地推進這個專案?{ph1}" -#: website/public/blog/touhou-reconstruction/index.html:930 +#: website/public/blog/touhou-reconstruction/index.html:934 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "That question makes me consider projects I would previously have left alone." @@ -1371,12 +1379,12 @@ msgid "" " how far that can take us." msgstr "這個問題讓我考慮以前會放棄的專案。每個專案都能改善下一個專案的工作方式。我想繼續探索,這能帶我們走多遠。" -#: website/public/blog/touhou-reconstruction/index.html:938 +#: website/public/blog/touhou-reconstruction/index.html:942 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Project milestones and sources" msgstr "專案里程碑與來源" -#: website/public/blog/touhou-reconstruction/index.html:939 +#: website/public/blog/touhou-reconstruction/index.html:943 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" "The dates describe recorded project checkpoints, checked against public " @@ -1408,7 +1416,7 @@ msgstr "" #. {ph10}: <a #. href="https://github.com/N0zoM1z0/th08/releases/tag/v0.2.0-linux-64bit" > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:947 +#: website/public/blog/touhou-reconstruction/index.html:951 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1441,7 +1449,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th095/blob/3442dcf29d9e0b5bef384a49bd0c9ad32a711826/docs/WHOLE_BUILD_TODO.md" #. > #. {ph11}: </a > -#: website/public/blog/touhou-reconstruction/index.html:970 +#: website/public/blog/touhou-reconstruction/index.html:974 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1458,7 +1466,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th04/blob/bb9faca54e2eb3c0d6c757c75d59ac29d2cd5e93/docs/RE_HANDOFF.md" #. > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:993 +#: website/public/blog/touhou-reconstruction/index.html:997 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1481,7 +1489,7 @@ msgstr "" #. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" #. > #. {ph7}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1002 +#: website/public/blog/touhou-reconstruction/index.html:1006 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1502,7 +1510,7 @@ msgstr "" #. factory/blob/717e1b8560783ed17a39fdf159d30aa16bb307a7/docs/semantic- #. reconstruction.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1016 +#: website/public/blog/touhou-reconstruction/index.html:1020 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1516,7 +1524,7 @@ msgstr "{ph0}語義重建:{ph1}{ph2}TH08 可讀性指南{ph3}和{ph4}Factory #. href="https://collection.sciencemuseumgroup.org.uk/objects/co51439/watts- #. steam-engine-indicator" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1028 +#: website/public/blog/touhou-reconstruction/index.html:1032 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1535,7 +1543,7 @@ msgstr "{ph0}工業史:{ph1}{ph2}英國科學博物館集團的蒸汽機示功 #. factory/blob/038b6bed51d273c8b3680553b6f43e1b97d19bd1/docs/knowledge- #. base.md" > #. {ph5}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1037 +#: website/public/blog/touhou-reconstruction/index.html:1041 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "" @@ -1547,7 +1555,7 @@ msgstr "{ph0}方法:{ph1}Factory 的{ph2}助手自主性{ph3}與{ph4}跨遊戲 #. {ph1}: </a> #. {ph2}: <a class="text-link" href="../../showcase/th04/" > #. {ph3}: </a > -#: website/public/blog/touhou-reconstruction/index.html:1052 +#: website/public/blog/touhou-reconstruction/index.html:1056 #, python-brace-format msgctxt "page:blog/touhou-reconstruction/index.html" msgid "{ph0}More articles{ph1} · {ph2}Explore a TH04 investigation{ph3}" @@ -1566,27 +1574,27 @@ msgid "" msgstr "" "N0zoM1z0 回顧從手工逆向到程式設計助手參與的東方遊戲重建,以及經驗如何在 TH08、TH095 和 PC-98 TH04 之間積累。" -#: website/public/blog/touhou-reconstruction/index.html:346 +#: website/public/blog/touhou-reconstruction/index.html:350 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Experience carried between projects" msgstr "在專案之間傳遞經驗" -#: website/public/blog/touhou-reconstruction/index.html:360 +#: website/public/blog/touhou-reconstruction/index.html:364 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/blog/touhou-reconstruction/index.html:375 +#: website/public/blog/touhou-reconstruction/index.html:379 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Touhou reconstruction essay" msgstr "東方遊戲重建隨筆" -#: website/public/blog/touhou-reconstruction/index.html:1076 +#: website/public/blog/touhou-reconstruction/index.html:1080 msgctxt "page:blog/touhou-reconstruction/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/examples/dino-lab/index.html:109 +#: website/public/examples/dino-lab/index.html:104 msgctxt "page:examples/dino-lab/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -1595,18 +1603,18 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <span> #. {ph3}: </span> -#: website/public/examples/dino-lab/index.html:191 +#: website/public/examples/dino-lab/index.html:195 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Home{ph1}{ph2}/{ph3}Dinosaur speed lab" msgstr "{ph0}首頁{ph1}{ph2}/{ph3}恐龍速度實驗室" -#: website/public/examples/dino-lab/index.html:194 +#: website/public/examples/dino-lab/index.html:198 msgctxt "page:examples/dino-lab/index.html" msgid "Inspect → rebuild → change" msgstr "檢查→重建→更改" -#: website/public/examples/dino-lab/index.html:195 +#: website/public/examples/dino-lab/index.html:199 msgctxt "page:examples/dino-lab/index.html" msgid "Rebuild the dinosaur’s speed rule." msgstr "重建恐龍的速度規則。" @@ -1615,7 +1623,7 @@ msgstr "重建恐龍的速度規則。" #. {ph1}: </strong> #. {ph2}: <mark class="prose-highlight"> #. {ph3}: </mark> -#: website/public/examples/dino-lab/index.html:196 +#: website/public/examples/dino-lab/index.html:200 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1626,15 +1634,15 @@ msgstr "" "要重新建立遊戲的加速,首先找到控制其速度的規則。 {ph0} REA返回執行指令碼;{ph1} 我們用它的規則來構建這個迷你遊戲。 " "{ph2}速度可調。{ph3}" -#: website/public/examples/dino-lab/index.html:205 -#: website/public/examples/dino-lab/index.html:204 +#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:208 msgctxt "page:examples/dino-lab/index.html" msgid "On this page" msgstr "在本頁" #. {ph0}: <a href="#play"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:207 +#: website/public/examples/dino-lab/index.html:211 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Play and change the speed{ph1}" @@ -1642,7 +1650,7 @@ msgstr "{ph0}播放和改變速度{ph1}" #. {ph0}: <a href="#rule"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:208 +#: website/public/examples/dino-lab/index.html:212 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Read the recovered rule{ph1}" @@ -1650,7 +1658,7 @@ msgstr "{ph0}讀取恢復的規則{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:209 +#: website/public/examples/dino-lab/index.html:213 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -1658,18 +1666,18 @@ msgstr "{ph0}檢查重建{ph1}" #. {ph0}: <a href="#inspect"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:210 +#: website/public/examples/dino-lab/index.html:214 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Try the analysis{ph1}" msgstr "{ph0}試試分析{ph1}" -#: website/public/examples/dino-lab/index.html:215 +#: website/public/examples/dino-lab/index.html:219 msgctxt "page:examples/dino-lab/index.html" msgid "Play and change the speed" msgstr "播放和改變速度" -#: website/public/examples/dino-lab/index.html:216 +#: website/public/examples/dino-lab/index.html:220 msgctxt "page:examples/dino-lab/index.html" msgid "" "Press Play, then jump over the cactus. Move the speed slider to try a slower" @@ -1677,54 +1685,54 @@ msgid "" "start at 6 and gradually accelerate again." msgstr "按播放,然後跳過仙人掌。 移動速度滑塊嘗試更慢或更快的遊戲;它切換到固定的速度。 選擇恢復的規則從6開始,然後再次逐漸加速。" -#: website/public/examples/dino-lab/index.html:222 +#: website/public/examples/dino-lab/index.html:226 msgctxt "page:examples/dino-lab/index.html" msgid "Play the reconstruction" msgstr "試玩重建版" -#: website/public/examples/dino-lab/index.html:254 +#: website/public/examples/dino-lab/index.html:258 msgctxt "page:examples/dino-lab/index.html" msgid "Play" msgstr "開始" -#: website/public/examples/dino-lab/index.html:257 +#: website/public/examples/dino-lab/index.html:261 msgctxt "page:examples/dino-lab/index.html" msgid "Jump ↑" msgstr "跳躍 ↑" -#: website/public/examples/dino-lab/index.html:258 +#: website/public/examples/dino-lab/index.html:262 msgctxt "page:examples/dino-lab/index.html" msgid "Restart" msgstr "重新開始" -#: website/public/examples/dino-lab/index.html:261 +#: website/public/examples/dino-lab/index.html:265 msgctxt "page:examples/dino-lab/index.html" msgid "Speed" msgstr "速度" -#: website/public/examples/dino-lab/index.html:271 +#: website/public/examples/dino-lab/index.html:275 msgctxt "page:examples/dino-lab/index.html" msgid "Use the recovered acceleration rule" msgstr "使用恢復的加速規則" -#: website/public/examples/dino-lab/index.html:275 +#: website/public/examples/dino-lab/index.html:279 msgctxt "page:examples/dino-lab/index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "原始規則:從6開始,然後向13增加。" -#: website/public/examples/dino-lab/index.html:278 +#: website/public/examples/dino-lab/index.html:282 msgctxt "page:examples/dino-lab/index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "移動滑塊來設定自己的速度。 空間或跳躍清除仙人掌。" -#: website/public/examples/dino-lab/index.html:283 +#: website/public/examples/dino-lab/index.html:287 msgctxt "page:examples/dino-lab/index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "啟用JavaScript播放重建。 上面的程式碼和解釋仍然是可讀的。" -#: website/public/examples/dino-lab/index.html:291 +#: website/public/examples/dino-lab/index.html:295 msgctxt "page:examples/dino-lab/index.html" msgid "Read the script REA returned" msgstr "讀取指令碼REA返回" @@ -1732,7 +1740,7 @@ msgstr "讀取指令碼REA返回" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > #. {ph2}: <code>index.js</code> -#: website/public/examples/dino-lab/index.html:292 +#: website/public/examples/dino-lab/index.html:296 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1745,7 +1753,7 @@ msgstr "" #. {ph0}: <code>SPEED: 6</code> #. {ph1}: <code>ACCELERATION: 0.001</code> #. {ph2}: <code>MAX_SPEED: 13</code> -#: website/public/examples/dino-lab/index.html:308 +#: website/public/examples/dino-lab/index.html:312 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1753,18 +1761,18 @@ msgid "" "update without a collision." msgstr "設定是 {ph0}, {ph1} 和 {ph2}. 遊戲在沒有碰撞的更新上執行此分支。" -#: website/public/examples/dino-lab/index.html:313 +#: website/public/examples/dino-lab/index.html:317 msgctxt "page:examples/dino-lab/index.html" msgid "Use the same rule in the new game" msgstr "在新遊戲中使用相同的規則" -#: website/public/examples/dino-lab/index.html:319 -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:323 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy" msgstr "複製" -#: website/public/examples/dino-lab/index.html:332 +#: website/public/examples/dino-lab/index.html:336 msgctxt "page:examples/dino-lab/index.html" msgid "" "The mini-game uses this function for automatic acceleration. Moving the " @@ -1779,18 +1787,18 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="../../assets/dino-demo.js"> #. {ph3}: </a> -#: website/public/examples/dino-lab/index.html:338 +#: website/public/examples/dino-lab/index.html:342 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Download the speed rule{ph1} · {ph2}Read the game code{ph3}" msgstr "{ph0}下載速度規則{ph1} · {ph2}閱讀遊戲程式碼{ph3}" -#: website/public/examples/dino-lab/index.html:346 +#: website/public/examples/dino-lab/index.html:350 msgctxt "page:examples/dino-lab/index.html" msgid "Check the reconstruction" msgstr "檢查重建" -#: website/public/examples/dino-lab/index.html:347 +#: website/public/examples/dino-lab/index.html:351 msgctxt "page:examples/dino-lab/index.html" msgid "" "We called the original game’s update function with obstacles and automatic " @@ -1798,41 +1806,41 @@ msgid "" "recovered rule." msgstr "我們稱原來的遊戲的更新功能與障礙和自動排程禁用。 將這些記錄的速度與恢復規則的重播進行比較。" -#: website/public/examples/dino-lab/index.html:356 +#: website/public/examples/dino-lab/index.html:360 msgctxt "page:examples/dino-lab/index.html" msgid "Updates" msgstr "更新資料" -#: website/public/examples/dino-lab/index.html:357 +#: website/public/examples/dino-lab/index.html:361 msgctxt "page:examples/dino-lab/index.html" msgid "Original game" msgstr "原創遊戲" -#: website/public/examples/dino-lab/index.html:358 +#: website/public/examples/dino-lab/index.html:362 msgctxt "page:examples/dino-lab/index.html" msgid "Reconstructed rule" msgstr "重建規則" -#: website/public/examples/dino-lab/index.html:385 +#: website/public/examples/dino-lab/index.html:389 msgctxt "page:examples/dino-lab/index.html" msgid "Run the speed check" msgstr "執行速度檢查" -#: website/public/examples/dino-lab/index.html:388 +#: website/public/examples/dino-lab/index.html:392 msgctxt "page:examples/dino-lab/index.html" msgid "" "Values rounded to three decimals. The branch checks before adding, so the " "final increment can take speed just above 13." msgstr "四捨五入為三位小數的值。 分支在新增之前進行檢查,因此最終增量可以採用略高於13的速度。" -#: website/public/examples/dino-lab/index.html:394 +#: website/public/examples/dino-lab/index.html:398 msgctxt "page:examples/dino-lab/index.html" msgid "Try the analysis yourself" msgstr "自己試試分析" #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/examples/dino-lab/index.html:396 +#: website/public/examples/dino-lab/index.html:400 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}Set up REA{ph1} with your coding agent." @@ -1841,14 +1849,14 @@ msgstr "{ph0}設立 REA{ph1} 用你的程式設計助手。" #. {ph0}: <a href="../../guides/browser/#prepare" > #. {ph1}: </a > #. {ph2}: <code>https://wayou.github.io/t-rex-runner/</code> -#: website/public/examples/dino-lab/index.html:400 +#: website/public/examples/dino-lab/index.html:404 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" "Follow the {ph0}browser connection steps{ph1}, using {ph2} as the page URL." msgstr "跟隨 {ph0}瀏覽器連線步驟{ph1},使用 {ph2} 作為頁面URL。" -#: website/public/examples/dino-lab/index.html:407 +#: website/public/examples/dino-lab/index.html:411 msgctxt "page:examples/dino-lab/index.html" msgid "" "Give your agent the page URL and local debugging endpoint, then copy this " @@ -1863,7 +1871,7 @@ msgstr "為你的程式設計助手提供頁面URL和本地除錯端點,然後 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/examples/dino-lab/index.html:414 +#: website/public/examples/dino-lab/index.html:418 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -1875,7 +1883,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/examples/dino-lab/index.html:427 +#: website/public/examples/dino-lab/index.html:431 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1888,7 +1896,7 @@ msgstr "" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/examples/dino-lab/index.html:436 +#: website/public/examples/dino-lab/index.html:440 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1901,7 +1909,7 @@ msgstr "要求跟進: {ph0}\"跳躍高度在哪裡計算? 在新版本中新 #. {ph1}: </a > #. {ph2}: <a href="../../assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/examples/dino-lab/index.html:443 +#: website/public/examples/dino-lab/index.html:447 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "" @@ -1924,64 +1932,64 @@ msgid "" "speed and play." msgstr "閱讀恐龍游戲的速度規則與REA,重建它,然後改變速度和發揮。" -#: website/public/examples/dino-lab/index.html:213 +#: website/public/examples/dino-lab/index.html:217 msgctxt "page:examples/dino-lab/index.html" msgid "Dinosaur speed reconstruction" msgstr "恐龍速度重建" -#: website/public/examples/dino-lab/index.html:244 +#: website/public/examples/dino-lab/index.html:248 msgctxt "page:examples/dino-lab/index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "恐龍迷你遊戲。 使用跳躍按鈕或按空格鍵,而遊戲是重點。" -#: website/public/examples/dino-lab/index.html:319 +#: website/public/examples/dino-lab/index.html:323 msgctxt "page:examples/dino-lab/index.html" msgid "Copy reconstructed speed rule" msgstr "複製重建速度規則" -#: website/public/examples/dino-lab/index.html:418 +#: website/public/examples/dino-lab/index.html:422 msgctxt "page:examples/dino-lab/index.html" msgid "Copy dinosaur analysis prompt" msgstr "複製恐龍分析提示" -#: website/public/examples/dino-lab/index.html:471 +#: website/public/examples/dino-lab/index.html:475 msgctxt "page:examples/dino-lab/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/faq/index.html:108 +#: website/public/faq/index.html:103 msgctxt "page:faq/index.html" msgid "Skip to content" msgstr "跳轉到內容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/faq/index.html:190 +#: website/public/faq/index.html:194 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Home{ph1} / FAQ" msgstr "{ph0}首頁{ph1} / FAQ" -#: website/public/faq/index.html:191 +#: website/public/faq/index.html:195 msgctxt "page:faq/index.html" msgid "REA FAQ." msgstr "REA 常見問題。" -#: website/public/faq/index.html:192 +#: website/public/faq/index.html:196 msgctxt "page:faq/index.html" msgid "Setup, updates, analysis and troubleshooting." msgstr "安裝、更新、分析和故障排查。" -#: website/public/faq/index.html:196 +#: website/public/faq/index.html:200 msgctxt "page:faq/index.html" msgid "Topics" msgstr "主題" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/faq/index.html:198 +#: website/public/faq/index.html:202 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Setup and updates{ph1}" @@ -1989,7 +1997,7 @@ msgstr "{ph0}安裝與更新{ph1}" #. {ph0}: <a href="#analysis"> #. {ph1}: </a> -#: website/public/faq/index.html:199 +#: website/public/faq/index.html:203 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Analysis{ph1}" @@ -1997,7 +2005,7 @@ msgstr "{ph0}分析{ph1}" #. {ph0}: <a href="#troubleshooting"> #. {ph1}: </a> -#: website/public/faq/index.html:200 +#: website/public/faq/index.html:204 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Troubleshooting{ph1}" @@ -2005,31 +2013,31 @@ msgstr "{ph0}故障排除{ph1}" #. {ph0}: <a href="#sharing"> #. {ph1}: </a> -#: website/public/faq/index.html:201 +#: website/public/faq/index.html:205 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Data and sharing{ph1}" msgstr "{ph0}資料與分享{ph1}" -#: website/public/faq/index.html:210 +#: website/public/faq/index.html:214 msgctxt "page:faq/index.html" msgid "Setup and updates" msgstr "安裝與更新" -#: website/public/faq/index.html:213 +#: website/public/faq/index.html:217 msgctxt "page:faq/index.html" msgid "How do I install REA?" msgstr "如何安裝 REA?" -#: website/public/faq/index.html:221 +#: website/public/faq/index.html:225 msgctxt "page:faq/index.html" msgid "Terminal · agent setup" msgstr "終端 · 配置程式設計助手" -#: website/public/faq/index.html:222 website/public/faq/index.html:263 -#: website/public/faq/index.html:281 website/public/faq/index.html:365 -#: website/public/faq/index.html:412 website/public/faq/index.html:452 -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:226 website/public/faq/index.html:267 +#: website/public/faq/index.html:285 website/public/faq/index.html:369 +#: website/public/faq/index.html:416 website/public/faq/index.html:456 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy" msgstr "複製" @@ -2037,7 +2045,7 @@ msgstr "複製" # Reviewed for readable setup and analysis terminology. #. {ph0}: <a href="../get-started/"> #. {ph1}: </a> -#: website/public/faq/index.html:233 +#: website/public/faq/index.html:237 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2049,12 +2057,12 @@ msgstr "" "setup 會註冊 REA 的 MCP " "連線,並安裝配套的調查技能。完成後重啟助手,再提供目標路徑和問題。{ph0}檢視安裝指南{ph1},瞭解前置條件和第一次分析的步驟。" -#: website/public/faq/index.html:242 +#: website/public/faq/index.html:246 msgctxt "page:faq/index.html" msgid "Which coding agents can use REA?" msgstr "哪些程式設計助手能使用 REA?" -#: website/public/faq/index.html:243 +#: website/public/faq/index.html:247 msgctxt "page:faq/index.html" msgid "" "Any agent that supports local MCP servers. Setup includes Claude Code, " @@ -2068,31 +2076,31 @@ msgstr "" #. {ph0}: <a href="../get-started/#agent"> #. {ph1}: </a> -#: website/public/faq/index.html:250 +#: website/public/faq/index.html:254 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Connect your coding agent{ph1}." msgstr "{ph0}連線程式設計助手{ph1}。" -#: website/public/faq/index.html:255 +#: website/public/faq/index.html:259 msgctxt "page:faq/index.html" msgid "How do I update REA?" msgstr "如何更新 REA?" -#: website/public/faq/index.html:256 +#: website/public/faq/index.html:260 msgctxt "page:faq/index.html" msgid "" "REA releases frequently, including bug fixes. If you installed the CLI with " "npm:" msgstr "REA 更新很頻繁,也會持續修復 bug。如果你透過 npm 安裝了 CLI:" -#: website/public/faq/index.html:262 +#: website/public/faq/index.html:266 msgctxt "page:faq/index.html" msgid "Terminal · installed CLI" msgstr "終端 · 已安裝的 CLI" #. {ph0}: <code>npx</code> -#: website/public/faq/index.html:274 +#: website/public/faq/index.html:278 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2100,14 +2108,14 @@ msgid "" "agent through {ph0}, run:" msgstr "更新後,按照輸出中的命令重新整理配置。如果之前透過 {ph0} 配置助手,執行:" -#: website/public/faq/index.html:280 +#: website/public/faq/index.html:284 msgctxt "page:faq/index.html" msgid "Terminal · refresh agent setup" msgstr "終端 · 重新整理助手配置" # Reviewed for readable setup and analysis terminology. #. {ph0}: <code>npx -y rea-agents@latest</code> -#: website/public/faq/index.html:292 +#: website/public/faq/index.html:296 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2118,14 +2126,14 @@ msgstr "" "檢查變更後,重啟程式設計助手。REA 的連線配置指定了包版本,重新執行 setup 才會讓助手使用新版本。臨時執行 CLI 命令時,在 {ph0} " "後面接具體命令即可。" -#: website/public/faq/index.html:300 +#: website/public/faq/index.html:304 msgctxt "page:faq/index.html" msgid "Is installing the skill from skills.sh enough?" msgstr "只從 skills.sh 安裝技能就夠了嗎?" #. {ph0}: <a href="#install"> #. {ph1}: </a> -#: website/public/faq/index.html:303 +#: website/public/faq/index.html:307 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2135,24 +2143,24 @@ msgid "" msgstr "" "技能告訴助手如何開展調查。還需要執行 {ph0}REA setup{ph1},連線 MCP 伺服器並安裝配套技能。隨後重啟助手,它才能呼叫工具。" -#: website/public/faq/index.html:314 +#: website/public/faq/index.html:318 msgctxt "page:faq/index.html" msgid "Analysis" msgstr "分析" -#: website/public/faq/index.html:317 +#: website/public/faq/index.html:321 msgctxt "page:faq/index.html" msgid "What can I analyze with REA?" msgstr "REA 可以分析什麼?" -#: website/public/faq/index.html:318 +#: website/public/faq/index.html:322 msgctxt "page:faq/index.html" msgid "Start with the kind of software you have:" msgstr "根據手裡的軟體型別選擇:" #. {ph0}: <a href="../guides/native/" > #. {ph1}: </a > -#: website/public/faq/index.html:320 +#: website/public/faq/index.html:324 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2162,7 +2170,7 @@ msgstr "{ph0}原生可執行檔案和庫{ph1}:函式、彙編、虛擬碼和 #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/faq/index.html:325 +#: website/public/faq/index.html:329 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2172,7 +2180,7 @@ msgstr "{ph0}JavaScript 和 Electron 應用{ph1}:模組、匯入、IPC 和原 #. {ph0}: <a href="../guides/browser/"> #. {ph1}: </a> -#: website/public/faq/index.html:330 +#: website/public/faq/index.html:334 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}Browser pages{ph1}: scripts, requests and runtime observations." @@ -2180,7 +2188,7 @@ msgstr "{ph0}瀏覽器頁面{ph1}:指令碼、請求和執行時觀察。" #. {ph0}: <a href="../showcase/"> #. {ph1}: </a> -#: website/public/faq/index.html:335 +#: website/public/faq/index.html:339 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2189,12 +2197,12 @@ msgid "" "investigations." msgstr "REA 也提供託管程式集、Android APK、韌體和打包資源的分析流程。{ph0}檢視案例{ph1},瞭解完整的調查過程。" -#: website/public/faq/index.html:343 +#: website/public/faq/index.html:347 msgctxt "page:faq/index.html" msgid "Do I need Hopper, Ghidra or IDA?" msgstr "需要 Hopper、Ghidra 或 IDA 嗎?" -#: website/public/faq/index.html:344 +#: website/public/faq/index.html:348 msgctxt "page:faq/index.html" msgid "" "Deep native analysis uses one of them. Static JavaScript and .NET inspection" @@ -2203,7 +2211,7 @@ msgstr "深度原生分析需要其中一個工具。靜態 JavaScript 和 .NET #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a> -#: website/public/faq/index.html:349 +#: website/public/faq/index.html:353 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2214,26 +2222,26 @@ msgstr "" "連線已有的 Ghidra 或 IDA 安裝,或讓 setup 檢測 Hopper " "並提出安裝計劃。可用的分析後端取決於你的系統和分析目標。{ph0}配置原生分析{ph1}。" -#: website/public/faq/index.html:357 +#: website/public/faq/index.html:361 msgctxt "page:faq/index.html" msgid "Can I use REA without a coding agent?" msgstr "不用程式設計助手,也能用 REA 嗎?" -#: website/public/faq/index.html:358 +#: website/public/faq/index.html:362 msgctxt "page:faq/index.html" msgid "" "Yes. The CLI uses the same analysis workflows. For a local JavaScript or " "Electron app:" msgstr "可以。CLI 使用同一套分析流程。對於本地 JavaScript 或 Electron 應用:" -#: website/public/faq/index.html:364 +#: website/public/faq/index.html:368 msgctxt "page:faq/index.html" msgid "Terminal · static application analysis" msgstr "終端 · 靜態應用分析" #. {ph0}: <a href="../get-started/#terminal"> #. {ph1}: </a> -#: website/public/faq/index.html:377 +#: website/public/faq/index.html:381 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2242,13 +2250,13 @@ msgid "" msgstr "把路徑換成解包後的應用目錄或 ASAR 檔案。{ph0}檢視 CLI 的安裝方式{ph1}。" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:384 +#: website/public/faq/index.html:388 msgctxt "page:faq/index.html" msgid "What code does REA return?" msgstr "REA 會返回什麼程式碼?" # Reviewed for readable setup and analysis terminology. -#: website/public/faq/index.html:385 +#: website/public/faq/index.html:389 msgctxt "page:faq/index.html" msgid "" "Native analysis returns assembly and pseudocode, with calls, references and " @@ -2260,7 +2268,7 @@ msgstr "原生程式分析返回彙編、虛擬碼、函式呼叫、引用和相 #. {ph1}: </a > #. {ph2}: <a href="../showcase/ctf/"> #. {ph3}: </a> -#: website/public/faq/index.html:390 +#: website/public/faq/index.html:394 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2270,12 +2278,12 @@ msgid "" msgstr "" "助手根據這些結果解釋行為,或編寫實現並測試。{ph0}DX-Ball 計算規則{ph1}和{ph2}CTF flag 檢查器{ph3}展示了這個過程。" -#: website/public/faq/index.html:401 +#: website/public/faq/index.html:405 msgctxt "page:faq/index.html" msgid "What should I ask my agent?" msgstr "應該向助手提什麼問題?" -#: website/public/faq/index.html:402 +#: website/public/faq/index.html:406 msgctxt "page:faq/index.html" msgid "" "Give it a local target and one behavior to investigate. For a JavaScript or " @@ -2290,7 +2298,7 @@ msgstr "提供一個本地目標,以及一個想調查的行為。比如 JavaS #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/faq/index.html:408 +#: website/public/faq/index.html:412 #, python-brace-format msgctxt "page:faq/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -2298,7 +2306,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" #. {ph0}: <a href="../guides/"> #. {ph1}: </a> -#: website/public/faq/index.html:431 +#: website/public/faq/index.html:435 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2306,18 +2314,18 @@ msgid "" "native, Electron and browser examples." msgstr "把路徑換成自己的目標。{ph0}指南{ph1}提供了原生、Electron 和瀏覽器示例的 prompt。" -#: website/public/faq/index.html:441 +#: website/public/faq/index.html:445 msgctxt "page:faq/index.html" msgid "Troubleshooting" msgstr "故障排除" -#: website/public/faq/index.html:444 +#: website/public/faq/index.html:448 msgctxt "page:faq/index.html" msgid "Why can't my agent see the REA tools?" msgstr "為什麼助手看不到 REA 工具?" #. {ph0}: <code>doctor</code> -#: website/public/faq/index.html:445 +#: website/public/faq/index.html:449 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2325,7 +2333,7 @@ msgid "" " {ph0}; for Codex:" msgstr "安裝後重啟或重新連線助手。用 {ph0} 檢查 REA 註冊情況。以 Codex 為例:" -#: website/public/faq/index.html:451 +#: website/public/faq/index.html:455 msgctxt "page:faq/index.html" msgid "Terminal · check one client" msgstr "終端 · 檢查一個客戶端" @@ -2333,7 +2341,7 @@ msgstr "終端 · 檢查一個客戶端" #. {ph0}: <code>codex</code> #. {ph1}: <code>claude_code</code> #. {ph2}: <code>cursor</code> -#: website/public/faq/index.html:463 +#: website/public/faq/index.html:467 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2341,14 +2349,14 @@ msgid "" "shows a missing or stale registration, run setup for that client:" msgstr "把 {ph0} 換成客戶端 ID,例如 {ph1} 或 {ph2}。如果報告顯示註冊缺失或過期,為這個客戶端執行 setup:" -#: website/public/faq/index.html:471 +#: website/public/faq/index.html:475 msgctxt "page:faq/index.html" msgid "Terminal · repair one client's setup" msgstr "終端 · 修復一個客戶端的配置" #. {ph0}: <a href="../get-started/#help"> #. {ph1}: </a> -#: website/public/faq/index.html:483 +#: website/public/faq/index.html:487 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2357,14 +2365,14 @@ msgid "" "diagnostics{ph1}." msgstr "確認計劃後重啟客戶端。如果註冊正常但工具仍未出現,檢查客戶端的 MCP 連線錯誤。{ph0}檢視更多配置診斷{ph1}。" -#: website/public/faq/index.html:491 +#: website/public/faq/index.html:495 msgctxt "page:faq/index.html" msgid "Do I need to start Hopper first?" msgstr "需要先啟動 Hopper 嗎?" #. {ph0}: <a href="../get-started/#native"> #. {ph1}: </a > -#: website/public/faq/index.html:492 +#: website/public/faq/index.html:496 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2375,14 +2383,14 @@ msgstr "" "REA 會在操作需要時啟動 Hopper。在 macOS " "上,首次使用時先完成演示模式或許可證啟用的選擇,再進行無人值守分析。{ph0}檢視原生分析配置{ph1}。" -#: website/public/faq/index.html:501 +#: website/public/faq/index.html:505 msgctxt "page:faq/index.html" msgid "What should I do if I hit a bug?" msgstr "遇到 bug 怎麼辦?" #. {ph0}: <a href="#update"> #. {ph1}: </a> -#: website/public/faq/index.html:502 +#: website/public/faq/index.html:506 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2392,7 +2400,7 @@ msgstr "先{ph0}更新 REA{ph1},重啟助手,再試一次相同任務。新 #. {ph0}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph1}: </a > -#: website/public/faq/index.html:506 +#: website/public/faq/index.html:510 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2402,24 +2410,24 @@ msgid "" msgstr "" "如果問題仍然存在,{ph0}提交 issue{ph1},附上 REA 版本、作業系統、目標型別、復現步驟和錯誤輸出。涉及原生分析時,也寫明分析後端。" -#: website/public/faq/index.html:520 +#: website/public/faq/index.html:524 msgctxt "page:faq/index.html" msgid "Data and sharing" msgstr "資料與分享" -#: website/public/faq/index.html:523 +#: website/public/faq/index.html:527 msgctxt "page:faq/index.html" msgid "Does REA upload my app?" msgstr "REA 會上傳我的應用嗎?" -#: website/public/faq/index.html:524 +#: website/public/faq/index.html:528 msgctxt "page:faq/index.html" msgid "" "REA analyzes targets on your machine. Your agent receives the results, and " "its model provider's data policy applies to those results." msgstr "REA 在你的機器上分析目標。助手會收到分析結果,這些結果受其模型服務商的資料政策約束。" -#: website/public/faq/index.html:531 +#: website/public/faq/index.html:535 msgctxt "page:faq/index.html" msgid "How can I share an example or contribute?" msgstr "如何分享案例或參與貢獻?" @@ -2428,7 +2436,7 @@ msgstr "如何分享案例或參與貢獻?" #. {ph1}: </a > #. {ph2}: <a href="https://github.com/morluto/rea/pulls"> #. {ph3}: </a > -#: website/public/faq/index.html:532 +#: website/public/faq/index.html:536 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2442,7 +2450,7 @@ msgstr "" #. {ph0}: <a href="https://discord.gg/GkcryMnJDM"> #. {ph1}: </a> -#: website/public/faq/index.html:544 +#: website/public/faq/index.html:548 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -2462,91 +2470,91 @@ msgid "" "coding agents, troubleshooting and sharing examples." msgstr "解答 REA 的常見問題:安裝、更新、分析工具、程式設計助手、故障排查和分享案例。" -#: website/public/faq/index.html:195 +#: website/public/faq/index.html:199 msgctxt "page:faq/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/faq/index.html:204 +#: website/public/faq/index.html:208 msgctxt "page:faq/index.html" msgid "Frequently asked questions about REA" msgstr "REA 常見問題" -#: website/public/faq/index.html:222 +#: website/public/faq/index.html:226 msgctxt "page:faq/index.html" msgid "Copy REA setup command" msgstr "複製REA設定命令" -#: website/public/faq/index.html:263 +#: website/public/faq/index.html:267 msgctxt "page:faq/index.html" msgid "Copy REA update command" msgstr "複製REA更新命令" -#: website/public/faq/index.html:281 +#: website/public/faq/index.html:285 msgctxt "page:faq/index.html" msgid "Copy agent setup refresh command" msgstr "複製程式設計助手設定重新整理命令" -#: website/public/faq/index.html:365 +#: website/public/faq/index.html:369 msgctxt "page:faq/index.html" msgid "Copy REA CLI analysis command" msgstr "複製REA CLI分析命令" -#: website/public/faq/index.html:412 +#: website/public/faq/index.html:416 msgctxt "page:faq/index.html" msgid "Copy example analysis prompt" msgstr "複製示例分析提示" -#: website/public/faq/index.html:452 +#: website/public/faq/index.html:456 msgctxt "page:faq/index.html" msgid "Copy client diagnosis command" msgstr "複製客戶端診斷命令" -#: website/public/faq/index.html:472 +#: website/public/faq/index.html:476 msgctxt "page:faq/index.html" msgid "Copy scoped setup command" msgstr "複製作用域設定命令" -#: website/public/faq/index.html:569 +#: website/public/faq/index.html:573 msgctxt "page:faq/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/first-investigation/index.html:108 +#: website/public/first-investigation/index.html:103 msgctxt "page:first-investigation/index.html" msgid "Skip to content" msgstr "跳轉到內容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:190 +#: website/public/first-investigation/index.html:194 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Home{ph1} / Your first investigation" msgstr "{ph0}首頁{ph1} / 第一次調查" #. {ph0}: <br /> -#: website/public/first-investigation/index.html:193 +#: website/public/first-investigation/index.html:197 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Find out where{ph0}exported notes go." msgstr "弄清楚{ph0}匯出的筆記寫到哪裡。" -#: website/public/first-investigation/index.html:194 +#: website/public/first-investigation/index.html:198 msgctxt "page:first-investigation/index.html" msgid "" "Use REA to inspect a small app, follow its Export notes button and check one" " detail yourself." msgstr "用 REA 檢查一個小應用,追蹤 Export notes 按鈕,再親自驗證一個細節。" -#: website/public/first-investigation/index.html:205 +#: website/public/first-investigation/index.html:209 msgctxt "page:first-investigation/index.html" msgid "In this exercise" msgstr "在這個練習中" #. {ph0}: <a href="#setup"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:207 +#: website/public/first-investigation/index.html:211 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}1. Set up{ph1}" @@ -2554,7 +2562,7 @@ msgstr "{ph0}1. 配置{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:208 +#: website/public/first-investigation/index.html:212 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}2. Ask about export{ph1}" @@ -2562,7 +2570,7 @@ msgstr "{ph0}2. 詢問匯出過程{ph1}" #. {ph0}: <a href="#answer"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:209 +#: website/public/first-investigation/index.html:213 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}3. Follow the answer{ph1}" @@ -2570,7 +2578,7 @@ msgstr "{ph0}3. 追蹤回答{ph1}" #. {ph0}: <a href="#check"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:210 +#: website/public/first-investigation/index.html:214 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}4. Check a prediction{ph1}" @@ -2578,13 +2586,13 @@ msgstr "{ph0}4. 檢查預測{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/first-investigation/index.html:211 +#: website/public/first-investigation/index.html:215 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}5. Ask another question{ph1}" msgstr "{ph0}5. 再問一個問題{ph1}" -#: website/public/first-investigation/index.html:216 +#: website/public/first-investigation/index.html:220 msgctxt "page:first-investigation/index.html" msgid "1. Connect your agent to REA" msgstr "1. 把助手連線到 REA" @@ -2597,43 +2605,43 @@ msgstr "1. 把助手連線到 REA" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/first-investigation/index.html:225 -#: website/public/first-investigation/index.html:275 -#: website/public/first-investigation/index.html:397 +#: website/public/first-investigation/index.html:229 +#: website/public/first-investigation/index.html:279 +#: website/public/first-investigation/index.html:401 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/first-investigation/index.html:230 -#: website/public/first-investigation/index.html:252 -#: website/public/first-investigation/index.html:280 -#: website/public/first-investigation/index.html:402 -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:234 +#: website/public/first-investigation/index.html:256 +#: website/public/first-investigation/index.html:284 +#: website/public/first-investigation/index.html:406 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy" msgstr "複製" -#: website/public/first-investigation/index.html:249 +#: website/public/first-investigation/index.html:253 msgctxt "page:first-investigation/index.html" msgid "Or run this command in your terminal:" msgstr "或者在終端中執行此命令:" -#: website/public/first-investigation/index.html:261 +#: website/public/first-investigation/index.html:265 msgctxt "page:first-investigation/index.html" msgid "" "Review the plan, approve the setup, then restart your agent. Already " "connected? Continue below." msgstr "檢視計劃,確認配置後重啟助手。如果已經連線,直接繼續。" -#: website/public/first-investigation/index.html:267 +#: website/public/first-investigation/index.html:271 msgctxt "page:first-investigation/index.html" msgid "2. Ask where the CSV is written" msgstr "2. 問清 CSV 寫到哪裡" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/first-investigation/index.html:268 +#: website/public/first-investigation/index.html:272 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2644,7 +2652,7 @@ msgstr "" "示例是一個包含六個檔案的 Electron 應用,帶有{ph0}Export notes(匯出筆記){ph1}按鈕。助手無需安裝或啟動 Electron" " 就能檢查程式碼。" -#: website/public/first-investigation/index.html:303 +#: website/public/first-investigation/index.html:307 msgctxt "page:first-investigation/index.html" msgid "" "Your agent downloads the files and gives the unpacked folder to REA for " @@ -2654,14 +2662,14 @@ msgstr "助手會下載並解壓檔案,再把目錄交給 REA 檢查。" #. {ph0}: <a class="button" href="../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:307 +#: website/public/first-investigation/index.html:311 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}下載示例ZIP{ph1}" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:315 +#: website/public/first-investigation/index.html:319 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2669,12 +2677,12 @@ msgid "" " path to the {ph0} folder and the same export question." msgstr "如果助手不能下載檔案,你也可以手動解壓。把 {ph0} 資料夾的路徑交給它,再問同一個匯出問題。" -#: website/public/first-investigation/index.html:322 +#: website/public/first-investigation/index.html:326 msgctxt "page:first-investigation/index.html" msgid "3. Follow the answer back to the code" msgstr "3. 從回答追蹤到程式碼" -#: website/public/first-investigation/index.html:323 +#: website/public/first-investigation/index.html:327 msgctxt "page:first-investigation/index.html" msgid "Look for a short explanation with file and line references:" msgstr "尋找帶檔案和行號的簡短解釋:" @@ -2683,7 +2691,7 @@ msgstr "尋找帶檔案和行號的簡短解釋:" #. {ph1}: <code>notes.csv</code> #. {ph2}: <code>id</code> #. {ph3}: <code>title</code> -#: website/public/first-investigation/index.html:325 +#: website/public/first-investigation/index.html:329 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2692,19 +2700,19 @@ msgid "" "{ph3}." msgstr "按鈕傳送 {ph0} 訊息。主程序把筆記轉換為 CSV,並將 {ph1} 寫到使用者的下載資料夾。列名為 {ph2} 和 {ph3}。" -#: website/public/first-investigation/index.html:333 +#: website/public/first-investigation/index.html:337 msgctxt "page:first-investigation/index.html" msgid "From the button to the file writer" msgstr "從按鈕到檔案寫入" -#: website/public/first-investigation/index.html:362 +#: website/public/first-investigation/index.html:366 msgctxt "page:first-investigation/index.html" msgid "" "REA’s static analysis pairs the message with its handler. The destination is" " read from code." msgstr "REA 的靜態分析把訊息和處理函式關聯起來。匯出位置是從程式碼中讀到的。" -#: website/public/first-investigation/index.html:378 +#: website/public/first-investigation/index.html:382 msgctxt "page:first-investigation/index.html" msgid "" "The file path, formatter and write call are together in this handler. Ask " @@ -2713,37 +2721,37 @@ msgstr "檔案路徑、格式化函式和寫入呼叫都在這個處理函式中 #. {ph0}: <a href="../guides/javascript/#follow" > #. {ph1}: </a > -#: website/public/first-investigation/index.html:383 +#: website/public/first-investigation/index.html:387 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}See the full code trace and recorded REA result{ph1}." msgstr "{ph0}檢視完整的程式碼追蹤和記錄的 REA 結果{ph1}。" -#: website/public/first-investigation/index.html:390 +#: website/public/first-investigation/index.html:394 msgctxt "page:first-investigation/index.html" msgid "4. Check a prediction" msgstr "4. 檢查預測" -#: website/public/first-investigation/index.html:391 +#: website/public/first-investigation/index.html:395 msgctxt "page:first-investigation/index.html" msgid "" "A comma separates CSV columns. What happens when a note title itself " "contains a comma or quotation marks?" msgstr "CSV 用逗號分隔各列。如果筆記標題本身包含逗號或引號,會發生什麼?" -#: website/public/first-investigation/index.html:435 +#: website/public/first-investigation/index.html:439 msgctxt "page:first-investigation/index.html" msgid "Run the check yourself" msgstr "自己檢查一下" #. {ph0}: <code>notes-example</code> -#: website/public/first-investigation/index.html:436 +#: website/public/first-investigation/index.html:440 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "Open a terminal in the unpacked {ph0} folder:" msgstr "在解壓後的 {ph0} 資料夾裡開啟終端:" -#: website/public/first-investigation/index.html:458 +#: website/public/first-investigation/index.html:462 msgctxt "page:first-investigation/index.html" msgid "" "This command uses a shell with here-document support, such as Bash or Zsh. " @@ -2752,24 +2760,24 @@ msgstr "" "這條命令需要 Bash、Zsh 等支援 here-document 的 shell。助手也可以在你的系統 shell 中執行同樣的 " "JavaScript。" -#: website/public/first-investigation/index.html:466 +#: website/public/first-investigation/index.html:470 msgctxt "page:first-investigation/index.html" msgid "5. Ask another question" msgstr "5. 再問一個問題" -#: website/public/first-investigation/index.html:467 +#: website/public/first-investigation/index.html:471 msgctxt "page:first-investigation/index.html" msgid "Try a follow-up in the same conversation:" msgstr "在同一段對話中繼續提問:" -#: website/public/first-investigation/index.html:469 +#: website/public/first-investigation/index.html:473 msgctxt "page:first-investigation/index.html" msgid "" "What happens if the file can’t be written? Follow the error back to the " "page." msgstr "如果檔案無法寫入,會發生什麼?沿著錯誤處理追蹤回頁面。" -#: website/public/first-investigation/index.html:474 +#: website/public/first-investigation/index.html:478 msgctxt "page:first-investigation/index.html" msgid "" "Or give your agent an app of your own and ask about one button, file or " @@ -2780,7 +2788,7 @@ msgstr "也可以提供自己的應用,詢問其中一個按鈕、檔案或行 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:479 +#: website/public/first-investigation/index.html:483 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2792,7 +2800,7 @@ msgstr "{ph0}Notion 如何複製文字和 HTML{ph1}{ph2}追蹤打包 Electron #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:485 +#: website/public/first-investigation/index.html:489 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2804,7 +2812,7 @@ msgstr "{ph0}DX-Ball 如何計算聲音左右位置{ph1}{ph2}檢視原始指令 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/first-investigation/index.html:493 +#: website/public/first-investigation/index.html:497 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -2824,109 +2832,109 @@ msgid "" "go, and check the CSV formatter with a sample title." msgstr "用小型 Notes 應用嘗試 REA。配置助手,詢問匯出的筆記寫到哪裡,再用一個示例標題驗證 CSV 格式化函式。" -#: website/public/first-investigation/index.html:204 +#: website/public/first-investigation/index.html:208 msgctxt "page:first-investigation/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/first-investigation/index.html:214 +#: website/public/first-investigation/index.html:218 msgctxt "page:first-investigation/index.html" msgid "Your first REA investigation" msgstr "你的第一次REA調查" -#: website/public/first-investigation/index.html:230 +#: website/public/first-investigation/index.html:234 msgctxt "page:first-investigation/index.html" msgid "Copy REA installation prompt" msgstr "複製REA安裝提示" -#: website/public/first-investigation/index.html:252 +#: website/public/first-investigation/index.html:256 msgctxt "page:first-investigation/index.html" msgid "Copy setup command" msgstr "複製安裝命令" -#: website/public/first-investigation/index.html:280 +#: website/public/first-investigation/index.html:284 msgctxt "page:first-investigation/index.html" msgid "Copy Notes investigation prompt" msgstr "複製筆記調查提示" -#: website/public/first-investigation/index.html:402 +#: website/public/first-investigation/index.html:406 msgctxt "page:first-investigation/index.html" msgid "Copy CSV check prompt" msgstr "複製CSV檢查提示" -#: website/public/first-investigation/index.html:444 +#: website/public/first-investigation/index.html:448 msgctxt "page:first-investigation/index.html" msgid "Copy formatter check command" msgstr "複製格式化程式檢查命令" -#: website/public/first-investigation/index.html:519 +#: website/public/first-investigation/index.html:523 msgctxt "page:first-investigation/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/get-started/index.html:108 +#: website/public/get-started/index.html:103 msgctxt "page:get-started/index.html" msgid "Skip to content" msgstr "跳轉到內容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/get-started/index.html:190 +#: website/public/get-started/index.html:194 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Home{ph1} / Get started" msgstr "{ph0}首頁{ph1} / 開始使用" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:191 +#: website/public/get-started/index.html:195 msgctxt "page:get-started/index.html" msgid "Set up REA." msgstr "設定 REA。" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:192 +#: website/public/get-started/index.html:196 msgctxt "page:get-started/index.html" msgid "" "Connect REA to your coding agent, or inspect a local app from your terminal." msgstr "將 REA 連接到你的程式設計助手,或在終端機中檢查本機應用程式。" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:204 +#: website/public/get-started/index.html:208 msgctxt "page:get-started/index.html" msgid "Open a terminal and check:" msgstr "開啟終端機並檢查:" -#: website/public/get-started/index.html:207 -#: website/public/get-started/index.html:464 +#: website/public/get-started/index.html:211 +#: website/public/get-started/index.html:468 msgctxt "page:get-started/index.html" msgid "Terminal" msgstr "終端機" -#: website/public/get-started/index.html:208 -#: website/public/get-started/index.html:229 -#: website/public/get-started/index.html:252 -#: website/public/get-started/index.html:268 -#: website/public/get-started/index.html:283 -#: website/public/get-started/index.html:298 -#: website/public/get-started/index.html:314 -#: website/public/get-started/index.html:333 -#: website/public/get-started/index.html:419 -#: website/public/get-started/index.html:465 -#: website/public/get-started/index.html:541 -#: website/public/get-started/index.html:600 -#: website/public/get-started/index.html:641 -#: website/public/get-started/index.html:673 -#: website/public/get-started/index.html:730 -#: website/public/get-started/index.html:771 -#: website/public/get-started/index.html:811 -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:212 +#: website/public/get-started/index.html:233 +#: website/public/get-started/index.html:256 +#: website/public/get-started/index.html:272 +#: website/public/get-started/index.html:287 +#: website/public/get-started/index.html:302 +#: website/public/get-started/index.html:318 +#: website/public/get-started/index.html:337 +#: website/public/get-started/index.html:423 +#: website/public/get-started/index.html:469 +#: website/public/get-started/index.html:545 +#: website/public/get-started/index.html:604 +#: website/public/get-started/index.html:645 +#: website/public/get-started/index.html:677 +#: website/public/get-started/index.html:734 +#: website/public/get-started/index.html:775 +#: website/public/get-started/index.html:815 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy" msgstr "複製" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:225 +#: website/public/get-started/index.html:229 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows (PowerShell){ph1}" @@ -2934,7 +2942,7 @@ msgstr "{ph0}Windows(PowerShell){ph1}" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. #. {ph0}: <code>node -v</code> -#: website/public/get-started/index.html:240 +#: website/public/get-started/index.html:244 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2945,7 +2953,7 @@ msgstr "如果要求你接受條款,請輸入 Y。關閉 PowerShell 後重新 #. {ph0}: <em> #. {ph1}: </em> #. {ph2}: <code>npx</code> -#: website/public/get-started/index.html:244 +#: website/public/get-started/index.html:248 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2955,17 +2963,17 @@ msgstr "" "如果之後執行 {ph2} 時,PowerShell 提示{ph0}“running scripts is disabled on this " "system”{ph1}(系統禁止執行指令碼),執行下面的命令一次,再重試:" -#: website/public/get-started/index.html:264 +#: website/public/get-started/index.html:268 msgctxt "page:get-started/index.html" msgid "If you use Homebrew:" msgstr "如果你使用 Homebrew:" -#: website/public/get-started/index.html:279 +#: website/public/get-started/index.html:283 msgctxt "page:get-started/index.html" msgid "Otherwise:" msgstr "其他情況:" -#: website/public/get-started/index.html:294 +#: website/public/get-started/index.html:298 msgctxt "page:get-started/index.html" msgid "Close Terminal, open it again, then:" msgstr "關閉終端,重新開啟,然後執行:" @@ -2973,7 +2981,7 @@ msgstr "關閉終端,重新開啟,然後執行:" #. {ph0}: <code>curl</code> #. {ph1}: <code>unzip</code> #. {ph2}: <code>sudo apt install curl unzip</code> -#: website/public/get-started/index.html:325 +#: website/public/get-started/index.html:329 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2984,7 +2992,7 @@ msgstr "安裝程式需要 {ph0} 和 {ph1}(Debian/Ubuntu 上用 {ph2} 安裝 # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. #. {ph0}: <code>nodejs</code> #. {ph1}: <code>node -v</code> -#: website/public/get-started/index.html:345 +#: website/public/get-started/index.html:349 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -2995,7 +3003,7 @@ msgstr "發行版提供的 {ph0} 套件通常早於 22.19。如果使用它, # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. #. {ph0}: <a href="https://nodejs.org/en/download"> #. {ph1}: </a> -#: website/public/get-started/index.html:349 +#: website/public/get-started/index.html:353 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3003,14 +3011,14 @@ msgid "" "{ph0}nodejs.org{ph1}." msgstr "偏好一般的安裝程式?到 {ph0}nodejs.org{ph1} 下載 LTS 版本。" -#: website/public/get-started/index.html:357 +#: website/public/get-started/index.html:361 msgctxt "page:get-started/index.html" msgid "Setup options" msgstr "配置方式" #. {ph0}: <a href="#agent"> #. {ph1}: </a> -#: website/public/get-started/index.html:359 +#: website/public/get-started/index.html:363 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Connect your coding agent{ph1}" @@ -3018,7 +3026,7 @@ msgstr "{ph0}連線程式設計助手{ph1}" #. {ph0}: <a href="#terminal"> #. {ph1}: </a> -#: website/public/get-started/index.html:360 +#: website/public/get-started/index.html:364 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Use the CLI{ph1}" @@ -3026,7 +3034,7 @@ msgstr "{ph0}使用CLI {ph1}" #. {ph0}: <a href="#native"> #. {ph1}: </a> -#: website/public/get-started/index.html:361 +#: website/public/get-started/index.html:365 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Set up native analysis{ph1}" @@ -3034,19 +3042,19 @@ msgstr "{ph0}配置原生分析{ph1}" #. {ph0}: <a href="#help"> #. {ph1}: </a> -#: website/public/get-started/index.html:362 +#: website/public/get-started/index.html:366 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Getting help{ph1}" msgstr "{ph0}尋求幫助{ph1}" -#: website/public/get-started/index.html:367 +#: website/public/get-started/index.html:371 msgctxt "page:get-started/index.html" msgid "Connect your coding agent" msgstr "連線程式設計助手" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:368 +#: website/public/get-started/index.html:372 msgctxt "page:get-started/index.html" msgid "" "Run setup to connect REA to your coding agent. Client choices include Claude" @@ -3056,12 +3064,12 @@ msgstr "" "執行設定流程,將 REA 連接到你的程式設計助手。可選擇的用戶端包括 Claude Code、Codex、Cursor、Gemini " "CLI、Windsurf、Grok Build 和其他支援的 MCP 用戶端。Grok Bot 的連接器要從它的聊天介面新增。" -#: website/public/get-started/index.html:375 +#: website/public/get-started/index.html:379 msgctxt "page:get-started/index.html" msgid "New to coding agents?" msgstr "第一次使用程式設計助手?" -#: website/public/get-started/index.html:376 +#: website/public/get-started/index.html:380 msgctxt "page:get-started/index.html" msgid "" "A coding agent is an AI assistant that works on your computer instead of in " @@ -3070,7 +3078,7 @@ msgid "" msgstr "" "程式設計助手是一種在你的電腦上工作、而不只待在瀏覽器頁面裡的 AI 助手。它能讀取檔案、執行命令,並在修改前徵求確認。REA 為它提供逆向工程工具。" -#: website/public/get-started/index.html:382 +#: website/public/get-started/index.html:386 msgctxt "page:get-started/index.html" msgid "" "If you don't have one yet, pick one, follow its install page and sign in:" @@ -3080,7 +3088,7 @@ msgstr "如果還沒有助手,選擇一個,按照其安裝頁面操作並登 #. {ph1}: <a href="https://code.claude.com/docs/en/setup" > #. {ph2}: </a > #. {ph3}: </strong > -#: website/public/get-started/index.html:387 +#: website/public/get-started/index.html:391 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3091,7 +3099,7 @@ msgstr "{ph0}{ph1}Claude Code{ph2}{ph3},由 Anthropic 開發,需要付費 Cl #. {ph1}: <a href="https://github.com/openai/codex"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:395 +#: website/public/get-started/index.html:399 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3102,7 +3110,7 @@ msgstr "{ph0}{ph1}Codex{ph2}{ph3},由 OpenAI 開發,用 ChatGPT 賬號登入 #. {ph1}: <a href="https://opencode.ai/docs"> #. {ph2}: </a> #. {ph3}: </strong > -#: website/public/get-started/index.html:401 +#: website/public/get-started/index.html:405 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3110,7 +3118,7 @@ msgid "" "your choice." msgstr "{ph0}{ph1}OpenCode{ph2}{ph3},開源,可以連線你選擇的模型服務商。" -#: website/public/get-started/index.html:407 +#: website/public/get-started/index.html:411 msgctxt "page:get-started/index.html" msgid "" "Then open it and copy the prompt below into it. The agent runs REA's setup " @@ -3125,18 +3133,18 @@ msgstr "開啟助手,把下面的 prompt 複製進去。助手會執行 REA se #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/get-started/index.html:414 +#: website/public/get-started/index.html:418 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/get-started/index.html:439 +#: website/public/get-started/index.html:443 msgctxt "page:get-started/index.html" msgid "Or run setup yourself" msgstr "也可以自己執行 setup" -#: website/public/get-started/index.html:441 +#: website/public/get-started/index.html:445 msgctxt "page:get-started/index.html" msgid "How do I open a terminal?" msgstr "怎麼開啟終端?" @@ -3146,7 +3154,7 @@ msgstr "怎麼開啟終端?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:443 +#: website/public/get-started/index.html:447 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3160,7 +3168,7 @@ msgstr "{ph0}Windows:{ph1}開啟「開始」功能表,輸入 {ph2}PowerShell #. {ph3}: <kbd>Space</kbd> #. {ph4}: <em> #. {ph5}: </em> -#: website/public/get-started/index.html:447 +#: website/public/get-started/index.html:451 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3172,7 +3180,7 @@ msgstr "{ph0}macOS:{ph1}按 {ph2} {ph3},輸入 {ph4}Terminal{ph5},按 Ente #. {ph2}: <kbd>Ctrl</kbd> #. {ph3}: <kbd>Alt</kbd> #. {ph4}: <kbd>T</kbd> -#: website/public/get-started/index.html:451 +#: website/public/get-started/index.html:455 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} press {ph2} {ph3} {ph4} on most desktops." @@ -3185,7 +3193,7 @@ msgstr "{ph0}Linux:{ph1}多數桌面環境可以按 {ph2} {ph3} {ph4}。" #. {ph4}: <kbd>Ctrl</kbd> #. {ph5}: <kbd>Shift</kbd> #. {ph6}: <kbd>V</kbd> -#: website/public/get-started/index.html:456 +#: website/public/get-started/index.html:460 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3195,7 +3203,7 @@ msgstr "" "用 {ph0} {ph1} 貼上命令(macOS:{ph2} {ph3};Linux 終端:{ph4} {ph5} {ph6}),再按 Enter。" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:477 +#: website/public/get-started/index.html:481 msgctxt "page:get-started/index.html" msgid "" "Choose your client and review the setup plan. REA adds its MCP connection " @@ -3203,12 +3211,12 @@ msgid "" "configuration. It asks before applying the changes." msgstr "選擇你的用戶端並檢查設定計畫。REA 會加入它的 MCP 連線和對應的調查 skill,並備份現有的設定。套用變更前,它會先詢問你。" -#: website/public/get-started/index.html:482 +#: website/public/get-started/index.html:486 msgctxt "page:get-started/index.html" msgid "Restart your client when setup finishes." msgstr "配置完成後重啟客戶端。" -#: website/public/get-started/index.html:484 +#: website/public/get-started/index.html:488 msgctxt "page:get-started/index.html" msgid "How do I restart my client?" msgstr "如何重啟客戶端?" @@ -3217,7 +3225,7 @@ msgstr "如何重啟客戶端?" #. {ph1}: </strong> #. {ph2}: <kbd>⌘</kbd> #. {ph3}: <kbd>Q</kbd> -#: website/public/get-started/index.html:485 +#: website/public/get-started/index.html:489 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3231,7 +3239,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:492 +#: website/public/get-started/index.html:496 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3239,7 +3247,7 @@ msgid "" " and start it again." msgstr "{ph0}終端助手{ph1}(Claude Code、Codex、Gemini CLI):退出當前會話,再啟動一次。" -#: website/public/get-started/index.html:497 +#: website/public/get-started/index.html:501 msgctxt "page:get-started/index.html" msgid "" "Give your agent a target path and a specific question. For a JavaScript or " @@ -3247,7 +3255,7 @@ msgid "" msgstr "給助手目標路徑和一個具體問題。比如 JavaScript 或 Electron 應用,可以這樣開始:" #. {ph0}: <code>/absolute/path/to/app</code> -#: website/public/get-started/index.html:502 +#: website/public/get-started/index.html:506 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3255,12 +3263,12 @@ msgid "" " dependencies involved, with the source locations for your findings." msgstr "檢查 {ph0},找出它如何匯出資料。展示涉及的入口點、函式呼叫和依賴,並給出分析結果對應的原始碼位置。" -#: website/public/get-started/index.html:508 +#: website/public/get-started/index.html:512 msgctxt "page:get-started/index.html" msgid "Replace the path with your local target." msgstr "把路徑換成自己的本地目標。" -#: website/public/get-started/index.html:510 +#: website/public/get-started/index.html:514 msgctxt "page:get-started/index.html" msgid "How do I get a folder's full path?" msgstr "怎麼取得資料夾的完整路徑?" @@ -3269,7 +3277,7 @@ msgstr "怎麼取得資料夾的完整路徑?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:512 +#: website/public/get-started/index.html:516 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3283,7 +3291,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/get-started/index.html:517 +#: website/public/get-started/index.html:521 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3293,7 +3301,7 @@ msgstr "{ph0}macOS:{ph1}在 Finder 中右鍵資料夾,按住 Option,選擇 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/get-started/index.html:521 +#: website/public/get-started/index.html:525 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3301,31 +3309,31 @@ msgid "" "appears." msgstr "{ph0}所有系統:{ph1}把資料夾拖進終端視窗,也能顯示路徑。" -#: website/public/get-started/index.html:526 +#: website/public/get-started/index.html:530 msgctxt "page:get-started/index.html" msgid "In a terminal, put quotes around a path that contains spaces." msgstr "在終端裡,包含空格的路徑需要加引號。" -#: website/public/get-started/index.html:533 +#: website/public/get-started/index.html:537 msgctxt "page:get-started/index.html" msgid "Use the CLI" msgstr "使用CLI" -#: website/public/get-started/index.html:534 +#: website/public/get-started/index.html:538 msgctxt "page:get-started/index.html" msgid "" "Analyze a JavaScript or Electron application folder or ASAR archive without " "running the app:" msgstr "靜態分析 JavaScript 或 Electron 應用目錄、ASAR 檔案,無需啟動應用:" -#: website/public/get-started/index.html:540 +#: website/public/get-started/index.html:544 msgctxt "page:get-started/index.html" msgid "Static application analysis" msgstr "靜態應用分析" #. {ph0}: <code>.asar</code> #. {ph1}: <code>"D:/apps/example"</code> -#: website/public/get-started/index.html:553 +#: website/public/get-started/index.html:557 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3333,13 +3341,13 @@ msgid "" "Windows, a path such as {ph1} works here." msgstr "把路徑換成解包後的應用目錄或 {ph0} 檔案。Windows 上也可以使用 {ph1} 這樣的路徑。" -#: website/public/get-started/index.html:559 +#: website/public/get-started/index.html:563 msgctxt "page:get-started/index.html" msgid "Where do I find an app's .asar file?" msgstr "在哪裡找到應用的 .asar 檔案?" #. {ph0}: <code>resources</code> -#: website/public/get-started/index.html:560 +#: website/public/get-started/index.html:564 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Electron apps usually keep it in a {ph0} folder:" @@ -3350,7 +3358,7 @@ msgstr "Electron 應用通常把它放在 {ph0} 資料夾中:" #. {ph2}: <code #. >C:\Users\<you>\AppData\Local\Programs\<App>\resources\app.asar</code #. > -#: website/public/get-started/index.html:565 +#: website/public/get-started/index.html:569 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Windows:{ph1} {ph2}" @@ -3362,7 +3370,7 @@ msgstr "{ph0} Windows :{ph1} {ph2}" #. >/Applications/<App>.app/Contents/Resources/app.asar</code > #. {ph3}: <em> #. {ph4}: </em> -#: website/public/get-started/index.html:571 +#: website/public/get-started/index.html:575 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3373,20 +3381,20 @@ msgstr "{ph0}macOS:{ph1}{ph2}(右鍵應用,選擇{ph3}“顯示包內容 #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>/opt/<App>/resources/app.asar</code> -#: website/public/get-started/index.html:579 +#: website/public/get-started/index.html:583 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Linux:{ph1} often {ph2}" msgstr "{ph0}Linux:{ph1}通常位於 {ph2}" #. {ph0}: <code>app.asar</code> -#: website/public/get-started/index.html:584 +#: website/public/get-started/index.html:588 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Some apps install elsewhere. Search the app's folder for {ph0}." msgstr "有些應用安裝在其他位置。在應用目錄裡搜尋 {ph0}。" -#: website/public/get-started/index.html:589 +#: website/public/get-started/index.html:593 msgctxt "page:get-started/index.html" msgid "" "The result identifies the app, shows connections between modules and gives " @@ -3395,43 +3403,43 @@ msgid "" msgstr "結果會識別應用,展示模組之間的關係,並給出原始碼位置。REA 無法解析的關係會在結果中註明。" #. {ph0}: <code>rea</code> -#: website/public/get-started/index.html:594 +#: website/public/get-started/index.html:598 #, python-brace-format msgctxt "page:get-started/index.html" msgid "If you'd like a permanent {ph0} command in your shell:" msgstr "如果希望在 shell 中直接使用 {ph0} 命令:" -#: website/public/get-started/index.html:599 +#: website/public/get-started/index.html:603 msgctxt "page:get-started/index.html" msgid "Install the CLI" msgstr "安裝CLI" #. {ph0}: <a href="../guides/javascript/" > #. {ph1}: </a > -#: website/public/get-started/index.html:611 +#: website/public/get-started/index.html:615 #, python-brace-format msgctxt "page:get-started/index.html" msgid "{ph0}Continue with the JavaScript application guide{ph1}" msgstr "{ph0}繼續看 JavaScript 應用指南{ph1}" -#: website/public/get-started/index.html:619 +#: website/public/get-started/index.html:623 msgctxt "page:get-started/index.html" msgid "Set up native analysis" msgstr "配置原生分析" -#: website/public/get-started/index.html:620 +#: website/public/get-started/index.html:624 msgctxt "page:get-started/index.html" msgid "" "Native binaries need a local analysis tool. Choose and configure one below, " "then give REA your executable or library." msgstr "原生二進位制需要本地分析工具。在下面選擇並配置一個工具,再提供可執行檔案或庫。" -#: website/public/get-started/index.html:625 +#: website/public/get-started/index.html:629 msgctxt "page:get-started/index.html" msgid "Choose a tool: Ghidra, Hopper or IDA" msgstr "選擇工具:Ghidra、Hopper 或 IDA" -#: website/public/get-started/index.html:630 +#: website/public/get-started/index.html:634 msgctxt "page:get-started/index.html" msgid "" "Use an existing Ghidra 12.1.x installation and a 64-bit JDK 21 or newer on " @@ -3441,17 +3449,17 @@ msgstr "" "在 Linux 或 macOS 的 x64、arm64 上,使用已有的 Ghidra 12.1.x 和 64 位 JDK 21 或更新版本。Ghidra" " 需要對應主機架構的原生反編譯器。執行 setup 前先設定路徑:" -#: website/public/get-started/index.html:637 +#: website/public/get-started/index.html:641 msgctxt "page:get-started/index.html" msgid "Connect your Ghidra installation" msgstr "連線已有的 Ghidra" -#: website/public/get-started/index.html:640 +#: website/public/get-started/index.html:644 msgctxt "page:get-started/index.html" msgid "Ghidra connection · macOS / Linux" msgstr "Ghidra 連線 · macOS / Linux" -#: website/public/get-started/index.html:655 +#: website/public/get-started/index.html:659 msgctxt "page:get-started/index.html" msgid "" "Replace both paths with your existing installations. Setup checks them and " @@ -3461,12 +3469,12 @@ msgstr "" "把兩個路徑換成自己的安裝位置。setup 會檢查路徑,併為選定客戶端儲存有效配置。Linux arm64 上可能需要另行構建 Ghidra " "原生反編譯器。" -#: website/public/get-started/index.html:663 +#: website/public/get-started/index.html:667 msgctxt "page:get-started/index.html" msgid "Connect Ghidra on Windows" msgstr "在 Windows 上連線 Ghidra" -#: website/public/get-started/index.html:664 +#: website/public/get-started/index.html:668 msgctxt "page:get-started/index.html" msgid "" "Windows x64 has experimental, read-only support for native x86 and x64 PE " @@ -3476,32 +3484,32 @@ msgstr "" "Windows x64 提供實驗性的只讀支援:分析固定本地 NTFS 驅動器上的原生 x86、x64 PE 應用和 DLL。使用已有的 Ghidra " "12.1.x 和 64 位 JDK 21 或更新版本:" -#: website/public/get-started/index.html:672 +#: website/public/get-started/index.html:676 msgctxt "page:get-started/index.html" msgid "Ghidra connection · Windows PowerShell" msgstr "Ghidra 連線 · Windows PowerShell" -#: website/public/get-started/index.html:687 +#: website/public/get-started/index.html:691 msgctxt "page:get-started/index.html" msgid "" "Replace the two paths with your installations, then review setup's plan." msgstr "把兩個路徑換成安裝位置,再檢視 setup 計劃。" -#: website/public/get-started/index.html:697 +#: website/public/get-started/index.html:701 msgctxt "page:get-started/index.html" msgid "" "Connect Hopper on macOS or Linux. Run the setup command above; it detects an" " existing installation or offers an installation plan for your approval." msgstr "在 macOS 或 Linux 上連線 Hopper。執行上面的 setup 命令,它會檢測已有安裝,或提出安裝計劃供你確認。" -#: website/public/get-started/index.html:702 +#: website/public/get-started/index.html:706 msgctxt "page:get-started/index.html" msgid "" "On macOS, complete Hopper's first-run choice of demo mode or license " "activation before an unattended analysis." msgstr "在 macOS 上,首次使用 Hopper 時先完成演示模式或許可證啟用的選擇,再做無人值守分析。" -#: website/public/get-started/index.html:711 +#: website/public/get-started/index.html:715 msgctxt "page:get-started/index.html" msgid "" "The verified IDA setups use Windows, with an existing MCP registration for " @@ -3511,7 +3519,7 @@ msgstr "" "已驗證的 IDA 配置使用 Windows,連線已有的 MCP 註冊,可附加到 GUI,也可使用無介面資料庫。Linux 和 macOS " "的無介面分析仍未驗證。" -#: website/public/get-started/index.html:717 +#: website/public/get-started/index.html:721 msgctxt "page:get-started/index.html" msgid "Connect an existing IDA MCP registration" msgstr "連線已有的 IDA MCP 註冊" @@ -3521,7 +3529,7 @@ msgstr "連線已有的 IDA MCP 註冊" #. {ph2}: <code>env</code> #. {ph3}: <code>mcpServers</code> #. {ph4}: <code>ida-pro-mcp</code> -#: website/public/get-started/index.html:720 +#: website/public/get-started/index.html:724 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3532,13 +3540,13 @@ msgstr "" "把上游伺服器可用的 {ph0}、{ph1} 和可選的 {ph2} 儲存在 JSON 檔案中。已有的 {ph3} 物件中包含 {ph4} 條目也可以。執行" " setup 前讓 REA 指向這個檔案:" -#: website/public/get-started/index.html:729 +#: website/public/get-started/index.html:733 msgctxt "page:get-started/index.html" msgid "IDA connection · Windows PowerShell" msgstr "IDA 連線 · Windows PowerShell" #. {ph0}: <code>"mode": "headless"</code> -#: website/public/get-started/index.html:744 +#: website/public/get-started/index.html:748 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3554,7 +3562,7 @@ msgstr "" #. {ph0}: <code>--provider ida</code> #. {ph1}: <code>REA_IDA_MCP_CONFIG</code> -#: website/public/get-started/index.html:753 +#: website/public/get-started/index.html:757 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3565,29 +3573,29 @@ msgstr "" "給 REA 原始可執行檔案的路徑,在 CLI 查詢中加入 {ph0}。使用程式設計助手時,把 {ph1} 加入 REA " "註冊的環境配置,並在開啟二進位制時選擇 IDA。" -#: website/public/get-started/index.html:765 +#: website/public/get-started/index.html:769 msgctxt "page:get-started/index.html" msgid "For an existing Ghidra setup, inspect a function with:" msgstr "已配置 Ghidra 時,可以這樣檢查函式:" -#: website/public/get-started/index.html:770 +#: website/public/get-started/index.html:774 msgctxt "page:get-started/index.html" msgid "Function analysis" msgstr "函式分析" #. {ph0}: <code>main</code> -#: website/public/get-started/index.html:783 +#: website/public/get-started/index.html:787 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Replace {ph0} with the function name or address you want to inspect." msgstr "把 {ph0} 換成要檢查的函式名或地址。" -#: website/public/get-started/index.html:788 +#: website/public/get-started/index.html:792 msgctxt "page:get-started/index.html" msgid "How native analysis sessions work" msgstr "原生分析會話如何工作" -#: website/public/get-started/index.html:789 +#: website/public/get-started/index.html:793 msgctxt "page:get-started/index.html" msgid "" "Each CLI command imports and analyzes the binary, then closes its session. " @@ -3597,7 +3605,7 @@ msgstr "每條 CLI 命令匯入並分析二進位制檔案,完成後關閉會 #. {ph0}: <a href="../guides/native/"> #. {ph1}: </a> -#: website/public/get-started/index.html:795 +#: website/public/get-started/index.html:799 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3605,18 +3613,18 @@ msgid "" "leads to a recovered calculation." msgstr "{ph0}跟著原生分析示例{ph1},看看函式結果如何幫助還原計算規則。" -#: website/public/get-started/index.html:802 +#: website/public/get-started/index.html:806 msgctxt "page:get-started/index.html" msgid "Getting help" msgstr "尋求幫助" -#: website/public/get-started/index.html:803 +#: website/public/get-started/index.html:807 msgctxt "page:get-started/index.html" msgid "If your agent doesn't see REA" msgstr "助手看不到 REA 工具時" #. {ph0}: <code>doctor</code> -#: website/public/get-started/index.html:804 +#: website/public/get-started/index.html:808 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3624,27 +3632,27 @@ msgid "" "{ph0}; for Codex:" msgstr "配置後重啟或重新連線客戶端。用 {ph0} 檢查 REA 連線。以 Codex 為例:" -#: website/public/get-started/index.html:810 +#: website/public/get-started/index.html:814 msgctxt "page:get-started/index.html" msgid "Check one client" msgstr "檢查一個客戶端" -#: website/public/get-started/index.html:822 +#: website/public/get-started/index.html:826 msgctxt "page:get-started/index.html" msgid "If a provider needs attention" msgstr "分析後端出現問題時" -#: website/public/get-started/index.html:823 +#: website/public/get-started/index.html:827 msgctxt "page:get-started/index.html" msgid "Check the provider you're using. For Ghidra:" msgstr "檢查正在使用的分析後端。以 Ghidra 為例:" -#: website/public/get-started/index.html:826 +#: website/public/get-started/index.html:830 msgctxt "page:get-started/index.html" msgid "Check one provider" msgstr "檢查一個分析後端" -#: website/public/get-started/index.html:838 +#: website/public/get-started/index.html:842 msgctxt "page:get-started/index.html" msgid "The report gives the failed check and a suggested next step." msgstr "報告會列出失敗的檢查和建議的下一步。" @@ -3653,7 +3661,7 @@ msgstr "報告會列出失敗的檢查和建議的下一步。" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:840 +#: website/public/get-started/index.html:844 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3664,7 +3672,7 @@ msgstr "{ph0}REA FAQ{ph1}{ph2}關於更新、助手和分析的常見解答。{p #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/get-started/index.html:844 +#: website/public/get-started/index.html:848 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3676,7 +3684,7 @@ msgstr "{ph0}選擇調查指南{ph1}{ph2}二進位制、Electron 應用和瀏覽 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:851 +#: website/public/get-started/index.html:855 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3688,7 +3696,7 @@ msgstr "{ph0}GitHub issues{ph1}{ph2}附上命令與診斷結果,反饋問題 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/get-started/index.html:855 +#: website/public/get-started/index.html:859 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -3709,114 +3717,114 @@ msgid "" msgstr "把 REA 連線到程式設計助手,或用終端檢查本地 JavaScript、Electron 應用。包含配置、首次提問和原生分析後端指南。" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:208 +#: website/public/get-started/index.html:212 msgctxt "page:get-started/index.html" msgid "Copy Node.js version check" msgstr "複製 Node.js 版本檢查命令" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:229 +#: website/public/get-started/index.html:233 msgctxt "page:get-started/index.html" msgid "Copy Node.js installation command for Windows" msgstr "複製 Windows 的 Node.js 安裝命令" # Adapted from Kaoru0822's Traditional Chinese draft in PR #1737. -#: website/public/get-started/index.html:252 +#: website/public/get-started/index.html:256 msgctxt "page:get-started/index.html" msgid "Copy PowerShell execution policy command" msgstr "複製 PowerShell 執行原則命令" -#: website/public/get-started/index.html:268 +#: website/public/get-started/index.html:272 msgctxt "page:get-started/index.html" msgid "Copy Homebrew Node.js installation command" msgstr "複製 Homebrew Node.js 安裝命令" -#: website/public/get-started/index.html:283 +#: website/public/get-started/index.html:287 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for macOS" msgstr "複製macOS的fnm安裝命令" -#: website/public/get-started/index.html:298 +#: website/public/get-started/index.html:302 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for macOS" msgstr "複製 Node.js 24命令 macOS" -#: website/public/get-started/index.html:314 +#: website/public/get-started/index.html:318 msgctxt "page:get-started/index.html" msgid "Copy fnm installation command for Linux" msgstr "複製Linux的fnm安裝命令" -#: website/public/get-started/index.html:333 +#: website/public/get-started/index.html:337 msgctxt "page:get-started/index.html" msgid "Copy Node.js 24 commands for Linux" msgstr "複製 Node.js 24命令 Linux" -#: website/public/get-started/index.html:356 +#: website/public/get-started/index.html:360 msgctxt "page:get-started/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/get-started/index.html:365 +#: website/public/get-started/index.html:369 msgctxt "page:get-started/index.html" msgid "REA getting started guide" msgstr "REA入門指南" -#: website/public/get-started/index.html:419 +#: website/public/get-started/index.html:423 msgctxt "page:get-started/index.html" msgid "Copy REA installation prompt" msgstr "複製REA安裝提示" -#: website/public/get-started/index.html:465 +#: website/public/get-started/index.html:469 msgctxt "page:get-started/index.html" msgid "Copy agent setup command" msgstr "複製程式設計助手設定命令" -#: website/public/get-started/index.html:541 +#: website/public/get-started/index.html:545 msgctxt "page:get-started/index.html" msgid "Copy JavaScript analysis command" msgstr "複製JavaScript分析命令" -#: website/public/get-started/index.html:600 +#: website/public/get-started/index.html:604 msgctxt "page:get-started/index.html" msgid "Copy CLI installation command" msgstr "複製CLI安裝命令" -#: website/public/get-started/index.html:641 +#: website/public/get-started/index.html:645 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for macOS and Linux" msgstr "複製 macOS 和 Linux 的 Ghidra 連線命令" -#: website/public/get-started/index.html:673 +#: website/public/get-started/index.html:677 msgctxt "page:get-started/index.html" msgid "Copy Ghidra connection for Windows PowerShell" msgstr "複製 Ghidra 連線 Windows PowerShell的" -#: website/public/get-started/index.html:730 +#: website/public/get-started/index.html:734 msgctxt "page:get-started/index.html" msgid "Copy IDA connection for Windows PowerShell" msgstr "複製 IDA 連線 Windows PowerShell的" -#: website/public/get-started/index.html:771 +#: website/public/get-started/index.html:775 msgctxt "page:get-started/index.html" msgid "Copy native function analysis command" msgstr "複製原生函式分析命令" -#: website/public/get-started/index.html:811 +#: website/public/get-started/index.html:815 msgctxt "page:get-started/index.html" msgid "Copy client diagnosis command" msgstr "複製客戶端診斷命令" -#: website/public/get-started/index.html:827 +#: website/public/get-started/index.html:831 msgctxt "page:get-started/index.html" msgid "Copy provider diagnosis command" msgstr "複製提供者診斷命令" -#: website/public/get-started/index.html:878 +#: website/public/get-started/index.html:882 msgctxt "page:get-started/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/guides/browser/index.html:108 +#: website/public/guides/browser/index.html:103 msgctxt "page:guides/browser/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -3825,34 +3833,34 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/browser/index.html:190 +#: website/public/guides/browser/index.html:194 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Browser observation" msgstr "{ph0}首頁{ph1} / {ph2}指南{ph3} /瀏覽器觀察" #. {ph0}: <br /> -#: website/public/guides/browser/index.html:194 +#: website/public/guides/browser/index.html:198 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "See what happens{ph0}when you click." msgstr "看看會發生什麼{ph0}當你點選。" -#: website/public/guides/browser/index.html:195 +#: website/public/guides/browser/index.html:199 msgctxt "page:guides/browser/index.html" msgid "" "Use a small browser app to connect an action, its network request and the " "JavaScript that builds a download." msgstr "使用小型瀏覽器應用程式連線操作,其網路請求和構建下載的JavaScript。" -#: website/public/guides/browser/index.html:202 +#: website/public/guides/browser/index.html:206 msgctxt "page:guides/browser/index.html" msgid "In this guide" msgstr "在本指南中" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:204 +#: website/public/guides/browser/index.html:208 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}The example{ph1}" @@ -3860,7 +3868,7 @@ msgstr "{ph0}例子{ph1}" #. {ph0}: <a href="#prepare"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:205 +#: website/public/guides/browser/index.html:209 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Open the browser{ph1}" @@ -3868,7 +3876,7 @@ msgstr "{ph0}開啟瀏覽器{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:206 +#: website/public/guides/browser/index.html:210 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -3876,7 +3884,7 @@ msgstr "{ph0}問問你的程式設計助手{ph1}" #. {ph0}: <a href="#capture"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:207 +#: website/public/guides/browser/index.html:211 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Capture from CLI{ph1}" @@ -3884,13 +3892,13 @@ msgstr "{ph0}從CLI捕獲 {ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:208 +#: website/public/guides/browser/index.html:212 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}Read the request and script{ph1}" msgstr "{ph0}閱讀請求和指令碼{ph1}" -#: website/public/guides/browser/index.html:213 +#: website/public/guides/browser/index.html:217 msgctxt "page:guides/browser/index.html" msgid "What happens when you click Export?" msgstr "單擊匯出時會發生什麼?" @@ -3900,7 +3908,7 @@ msgstr "單擊匯出時會發生什麼?" #. {ph2}: <strong> #. {ph3}: </strong> #. {ph4}: <code>notes.json</code> -#: website/public/guides/browser/index.html:214 +#: website/public/guides/browser/index.html:218 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3911,7 +3919,7 @@ msgstr "" "{ph0}Notes 瀏覽器示例{ph1}有一個{ph2}Export notes(匯出筆記){ph3}按鈕。點選後載入 {ph4},把兩條筆記格式化為" " CSV,再開始下載。" -#: website/public/guides/browser/index.html:222 +#: website/public/guides/browser/index.html:226 msgctxt "page:guides/browser/index.html" msgid "From the click to the CSV download" msgstr "從點選到CSV下載" @@ -3922,7 +3930,7 @@ msgstr "從點選到CSV下載" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:224 +#: website/public/guides/browser/index.html:228 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3936,7 +3944,7 @@ msgstr "{ph0}01 · 你{ph1}{ph2}點選 Export notes{ph3}{ph4}在捕獲進行時 #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/browser/index.html:232 +#: website/public/guides/browser/index.html:236 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3952,7 +3960,7 @@ msgstr "{ph0}02*REA {ph1}{ph2}記錄請求{ph3}{ph4}從所選頁面捕獲請求U #. {ph5}: <code>fetch("./notes.json")</code> #. {ph6}: <code>export.js</code> #. {ph7}: </span > -#: website/public/guides/browser/index.html:240 +#: website/public/guides/browser/index.html:244 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -3962,52 +3970,52 @@ msgstr "" "{ph0}03 · 程式設計助手{ph1}{ph2}讀取匯出程式碼{ph3}{ph4}把觀察到的請求與 {ph6} 中的 {ph5} " "關聯起來。{ph7}" -#: website/public/guides/browser/index.html:253 +#: website/public/guides/browser/index.html:257 msgctxt "page:guides/browser/index.html" msgid "Start the capture before clicking Export notes." msgstr "在單擊匯出註釋之前開始捕獲。" -#: website/public/guides/browser/index.html:259 +#: website/public/guides/browser/index.html:263 msgctxt "page:guides/browser/index.html" msgid "Open Chrome with remote debugging" msgstr "使用遠端除錯開啟Chrome" -#: website/public/guides/browser/index.html:260 +#: website/public/guides/browser/index.html:264 msgctxt "page:guides/browser/index.html" msgid "" "Open the hosted Notes example with a separate browser profile and a local " "debugging port. On Linux:" msgstr "用獨立的瀏覽器配置和本地除錯埠開啟線上 Notes 示例。Linux 上:" -#: website/public/guides/browser/index.html:266 +#: website/public/guides/browser/index.html:270 msgctxt "page:guides/browser/index.html" msgid "Start the example browser" msgstr "啟動示例瀏覽器" -#: website/public/guides/browser/index.html:267 -#: website/public/guides/browser/index.html:299 -#: website/public/guides/browser/index.html:333 -#: website/public/guides/browser/index.html:352 -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:271 +#: website/public/guides/browser/index.html:303 +#: website/public/guides/browser/index.html:337 +#: website/public/guides/browser/index.html:356 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy" msgstr "複製" -#: website/public/guides/browser/index.html:281 +#: website/public/guides/browser/index.html:285 msgctxt "page:guides/browser/index.html" msgid "" "Use your installed browser's executable path on macOS or Windows. You can " "replace the page URL with another page you want to inspect." msgstr "在macOS或Windows上使用已安裝的瀏覽器的可執行路徑。 你可以將頁面URL替換為要檢查的其他頁面。" -#: website/public/guides/browser/index.html:286 +#: website/public/guides/browser/index.html:290 msgctxt "page:guides/browser/index.html" msgid "" "REA connects to this existing browser. You keep control of the page, perform" " the action, and close the browser when finished." msgstr "REA連線到這個現有的瀏覽器。 你可以控制頁面,執行操作,並在完成後關閉瀏覽器。" -#: website/public/guides/browser/index.html:292 +#: website/public/guides/browser/index.html:296 msgctxt "page:guides/browser/index.html" msgid "Ask your agent to watch one action" msgstr "讓你的程式設計助手看一個動作" @@ -4020,7 +4028,7 @@ msgstr "讓你的程式設計助手看一個動作" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/browser/index.html:295 +#: website/public/guides/browser/index.html:299 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" @@ -4032,7 +4040,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/browser/index.html:308 +#: website/public/guides/browser/index.html:312 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4043,7 +4051,7 @@ msgstr "" "是怎樣生成的?{ph3}{ph4}{ph5}" #. {ph0}: <code>http://127.0.0.1:9222</code> -#: website/public/guides/browser/index.html:316 +#: website/public/guides/browser/index.html:320 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4051,7 +4059,7 @@ msgid "" "URL. Let it start the capture before you click." msgstr "示例 prompt。把除錯地址 {ph0} 和頁面網址交給助手。等它開始捕獲,再點選按鈕。" -#: website/public/guides/browser/index.html:321 +#: website/public/guides/browser/index.html:325 msgctxt "page:guides/browser/index.html" msgid "" "Your agent discovers the page target, starts an observation window, and " @@ -4059,23 +4067,23 @@ msgid "" "export." msgstr "你的程式設計助手發現頁面目標,啟動觀察視窗,並讀取生成的證據。 然後,它可以檢查匯出後面的指令碼。" -#: website/public/guides/browser/index.html:328 +#: website/public/guides/browser/index.html:332 msgctxt "page:guides/browser/index.html" msgid "Or capture from the terminal" msgstr "或從終端捕獲" -#: website/public/guides/browser/index.html:329 +#: website/public/guides/browser/index.html:333 msgctxt "page:guides/browser/index.html" msgid "Find the page's target ID:" msgstr "查詢頁面的目標ID:" -#: website/public/guides/browser/index.html:332 +#: website/public/guides/browser/index.html:336 msgctxt "page:guides/browser/index.html" msgid "Find the page" msgstr "查詢頁面" #. {ph0}: <code>TARGET_ID</code> -#: website/public/guides/browser/index.html:345 +#: website/public/guides/browser/index.html:349 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4083,14 +4091,14 @@ msgid "" "ID, then run:" msgstr "選擇網址為 Notes 示例的目標,把下面的 {ph0} 換成目標 ID,再執行:" -#: website/public/guides/browser/index.html:351 +#: website/public/guides/browser/index.html:355 msgctxt "page:guides/browser/index.html" msgid "Capture the next ten seconds" msgstr "捕捉接下來的十秒" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/browser/index.html:367 +#: website/public/guides/browser/index.html:371 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4098,7 +4106,7 @@ msgid "" " in that browser. The result arrives after the observation window ends." msgstr "讓命令連線幾秒鐘,再在瀏覽器中點選{ph0}Export notes{ph1}。觀察時間視窗結束後會返回結果。" -#: website/public/guides/browser/index.html:372 +#: website/public/guides/browser/index.html:376 msgctxt "page:guides/browser/index.html" msgid "" "The captured result includes the selected page, network activity during that" @@ -4106,49 +4114,49 @@ msgid "" "this capture." msgstr "捕獲的結果包括所選頁面、該視窗期間的網路活動以及JSON響應的形狀。 較早的請求在此捕獲之外。" -#: website/public/guides/browser/index.html:379 +#: website/public/guides/browser/index.html:383 msgctxt "page:guides/browser/index.html" msgid "Read the request and export script" msgstr "讀取請求和匯出指令碼" -#: website/public/guides/browser/index.html:382 +#: website/public/guides/browser/index.html:386 msgctxt "page:guides/browser/index.html" msgid "Recorded with REA 4.1.0 on the local Notes example" msgstr "在本地筆記示例中用REA4.1.0記錄" -#: website/public/guides/browser/index.html:387 +#: website/public/guides/browser/index.html:391 msgctxt "page:guides/browser/index.html" msgid "Captured fact" msgstr "捕獲的事實" -#: website/public/guides/browser/index.html:388 +#: website/public/guides/browser/index.html:392 msgctxt "page:guides/browser/index.html" msgid "Value" msgstr "數值" -#: website/public/guides/browser/index.html:393 +#: website/public/guides/browser/index.html:397 msgctxt "page:guides/browser/index.html" msgid "Request" msgstr "請求" -#: website/public/guides/browser/index.html:397 +#: website/public/guides/browser/index.html:401 msgctxt "page:guides/browser/index.html" msgid "Response" msgstr "回應" -#: website/public/guides/browser/index.html:401 +#: website/public/guides/browser/index.html:405 msgctxt "page:guides/browser/index.html" msgid "Request initiator" msgstr "請求發起者" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:402 +#: website/public/guides/browser/index.html:406 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · script" msgstr "{ph0} · 指令碼" -#: website/public/guides/browser/index.html:405 +#: website/public/guides/browser/index.html:409 msgctxt "page:guides/browser/index.html" msgid "Response structure" msgstr "響應結構" @@ -4156,19 +4164,19 @@ msgstr "響應結構" #. {ph0}: <code>notes[]</code> #. {ph1}: <code>id</code> #. {ph2}: <code>title</code> -#: website/public/guides/browser/index.html:406 +#: website/public/guides/browser/index.html:410 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} with {ph1} and {ph2} fields" msgstr "{ph0} 與 {ph1} 和 {ph2} 欄位" -#: website/public/guides/browser/index.html:416 +#: website/public/guides/browser/index.html:420 msgctxt "page:guides/browser/index.html" msgid "Read the loaded scripts" msgstr "閱讀載入的指令碼" #. {ph0}: <code>export.js</code> -#: website/public/guides/browser/index.html:430 +#: website/public/guides/browser/index.html:434 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4177,7 +4185,7 @@ msgid "" msgstr "請求指出了資料來源,REA 記錄的請求發起方是 {ph0}。讀取捕獲的指令碼原始碼,看看它如何使用資料:" #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:450 +#: website/public/guides/browser/index.html:454 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4187,7 +4195,7 @@ msgid "" msgstr "下載是使用JSON響應在頁面中構建的。 CSV格式化步驟來自指令碼;網路捕獲建立此單擊請求 {ph0}." #. {ph0}: <code>notes.json</code> -#: website/public/guides/browser/index.html:466 +#: website/public/guides/browser/index.html:470 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4197,7 +4205,7 @@ msgstr "查詢請求的指令碼 {ph0}. 它如何轉義包含逗號或引號的 #. {ph0}: <a href="../javascript/"> #. {ph1}: </a> -#: website/public/guides/browser/index.html:471 +#: website/public/guides/browser/index.html:475 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -4217,161 +4225,161 @@ msgid "" "inspect the request and follow the export script." msgstr "觀察一個筆記匯出與 REA:選擇瀏覽器頁面,捕獲單擊,檢查請求並遵循匯出指令碼。" -#: website/public/guides/browser/index.html:201 +#: website/public/guides/browser/index.html:205 msgctxt "page:guides/browser/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/guides/browser/index.html:211 +#: website/public/guides/browser/index.html:215 msgctxt "page:guides/browser/index.html" msgid "Browser observation" msgstr "瀏覽器觀察" -#: website/public/guides/browser/index.html:267 +#: website/public/guides/browser/index.html:271 msgctxt "page:guides/browser/index.html" msgid "Copy start the example browser" msgstr "複製啟動示例瀏覽器" -#: website/public/guides/browser/index.html:299 +#: website/public/guides/browser/index.html:303 msgctxt "page:guides/browser/index.html" msgid "Copy example prompt" msgstr "複製示例提示" -#: website/public/guides/browser/index.html:333 +#: website/public/guides/browser/index.html:337 msgctxt "page:guides/browser/index.html" msgid "Copy find the page" msgstr "複製查詢頁面" -#: website/public/guides/browser/index.html:352 +#: website/public/guides/browser/index.html:356 msgctxt "page:guides/browser/index.html" msgid "Copy capture the next ten seconds" msgstr "複製捕獲接下來的十秒鐘" -#: website/public/guides/browser/index.html:417 +#: website/public/guides/browser/index.html:421 msgctxt "page:guides/browser/index.html" msgid "Copy read the loaded scripts" msgstr "複製讀取載入的指令碼" -#: website/public/guides/browser/index.html:494 +#: website/public/guides/browser/index.html:507 msgctxt "page:guides/browser/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/guides/index.html:108 +#: website/public/guides/index.html:103 msgctxt "page:guides/index.html" msgid "Skip to content" msgstr "跳轉到內容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/guides/index.html:190 +#: website/public/guides/index.html:194 #, python-brace-format msgctxt "page:guides/index.html" msgid "{ph0}Home{ph1} / Guides" msgstr "{ph0}首頁{ph1} /指南" -#: website/public/guides/index.html:191 +#: website/public/guides/index.html:195 msgctxt "page:guides/index.html" msgid "REA guides." msgstr "REA 分析指南。" -#: website/public/guides/index.html:192 +#: website/public/guides/index.html:196 msgctxt "page:guides/index.html" msgid "" "Analyze a native function, an Electron export or a browser request. Each " "guide includes a prompt, code and results." msgstr "分析本機函式、Electron匯出或瀏覽器請求。 每個指南包括提示,程式碼和結果。" -#: website/public/guides/index.html:199 +#: website/public/guides/index.html:203 msgctxt "page:guides/index.html" msgid "First investigation" msgstr "第一次調查" -#: website/public/guides/index.html:201 +#: website/public/guides/index.html:205 msgctxt "page:guides/index.html" msgid "Set up REA" msgstr "設定REA" -#: website/public/guides/index.html:202 +#: website/public/guides/index.html:206 msgctxt "page:guides/index.html" msgid "Connect your coding agent or use REA from the terminal." msgstr "連線你的程式設計助手或使用 REA 從終端。" -#: website/public/guides/index.html:203 +#: website/public/guides/index.html:207 msgctxt "page:guides/index.html" msgid "Get started with REA" msgstr "開始使用 REA" -#: website/public/guides/index.html:207 +#: website/public/guides/index.html:211 msgctxt "page:guides/index.html" msgid "Native binaries" msgstr "原生二進位制" -#: website/public/guides/index.html:209 +#: website/public/guides/index.html:213 msgctxt "page:guides/index.html" msgid "Recover a sound-pan calculation" msgstr "恢復左/右聲音位置的計算" -#: website/public/guides/index.html:210 +#: website/public/guides/index.html:214 msgctxt "page:guides/index.html" msgid "" "Start with a Windows game executable. Inspect instructions, follow a caller," " read numeric constants and check the recovered C." msgstr "從Windows遊戲可執行檔案開始。 檢查指令,跟隨呼叫者,讀取數字常量並檢查恢復的C。" -#: website/public/guides/index.html:220 +#: website/public/guides/index.html:224 msgctxt "page:guides/index.html" msgid "Native analysis guide" msgstr "原生分析指南" -#: website/public/guides/index.html:224 +#: website/public/guides/index.html:228 msgctxt "page:guides/index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/guides/index.html:226 +#: website/public/guides/index.html:230 msgctxt "page:guides/index.html" msgid "Follow a CSV export" msgstr "追蹤 CSV 匯出" -#: website/public/guides/index.html:227 +#: website/public/guides/index.html:231 msgctxt "page:guides/index.html" msgid "" "A small Notes app spreads one feature across the renderer, preload and main " "process. Use REA to connect the API, IPC channel and file writer." msgstr "一個小Notes應用程式在渲染器,預載入和主程序中傳播一個功能。 使用REA連線API,IPC通道和檔案編寫器。" -#: website/public/guides/index.html:237 +#: website/public/guides/index.html:241 msgctxt "page:guides/index.html" msgid "JavaScript & Electron guide" msgstr "JavaScript&Electron指南" #. {ph0}: <a href="../showcase/notion/"> #. {ph1}: </a> -#: website/public/guides/index.html:240 +#: website/public/guides/index.html:244 #, python-brace-format msgctxt "page:guides/index.html" msgid "For a larger packaged app, follow {ph0}Notion's clipboard bridge{ph1}." msgstr "對於更大的打包應用程式,請遵循 {ph0} Notion的剪貼簿橋{ph1}." -#: website/public/guides/index.html:247 +#: website/public/guides/index.html:251 msgctxt "page:guides/index.html" msgid "Browser behavior" msgstr "瀏覽器行為" -#: website/public/guides/index.html:249 +#: website/public/guides/index.html:253 msgctxt "page:guides/index.html" msgid "Observe a click" msgstr "觀察點選" -#: website/public/guides/index.html:250 +#: website/public/guides/index.html:254 msgctxt "page:guides/index.html" msgid "" "Open a working Notes example, capture an export request and find the code " "that turns its response into a download." msgstr "開啟工作筆記示例,捕獲匯出請求並找到將其響應轉換為下載的程式碼。" -#: website/public/guides/index.html:259 +#: website/public/guides/index.html:263 msgctxt "page:guides/index.html" msgid "Browser observation guide" msgstr "瀏覽器觀察指南" @@ -4388,12 +4396,12 @@ msgid "" "CSV export and a browser request." msgstr "透過簡短的示例學習REA:本機計算,Electron CSV匯出和瀏覽器請求。" -#: website/public/guides/index.html:278 +#: website/public/guides/index.html:282 msgctxt "page:guides/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/guides/javascript/index.html:108 +#: website/public/guides/javascript/index.html:103 msgctxt "page:guides/javascript/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -4402,34 +4410,34 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/javascript/index.html:190 +#: website/public/guides/javascript/index.html:194 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / JavaScript & Electron" msgstr "{ph0}首頁{ph1} / {ph2}指南{ph3} / JavaScript & Electron" #. {ph0}: <br /> -#: website/public/guides/javascript/index.html:194 +#: website/public/guides/javascript/index.html:198 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "Trace an Electron{ph0}CSV export." msgstr "追蹤安 Electron{ph0}CSV 匯出。" -#: website/public/guides/javascript/index.html:195 +#: website/public/guides/javascript/index.html:199 msgctxt "page:guides/javascript/index.html" msgid "" "Follow a button click from the page API, through Electron IPC, to the CSV " "file writer." msgstr "按照一個按鈕點選從頁面API,透過Electron IPC,到CSV檔案編寫器。" -#: website/public/guides/javascript/index.html:202 +#: website/public/guides/javascript/index.html:206 msgctxt "page:guides/javascript/index.html" msgid "In this guide" msgstr "在本指南中" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:204 +#: website/public/guides/javascript/index.html:208 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}The example{ph1}" @@ -4437,7 +4445,7 @@ msgstr "{ph0}例子{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:205 +#: website/public/guides/javascript/index.html:209 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4445,7 +4453,7 @@ msgstr "{ph0}問問你的程式設計助手{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:206 +#: website/public/guides/javascript/index.html:210 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Trace the export code{ph1}" @@ -4453,7 +4461,7 @@ msgstr "{ph0}跟蹤匯出程式碼{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:207 +#: website/public/guides/javascript/index.html:211 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Try the example{ph1}" @@ -4461,20 +4469,20 @@ msgstr "{ph0}試試這個例子{ph1}" #. {ph0}: <a href="#next"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:208 +#: website/public/guides/javascript/index.html:212 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Inspect the CSV writer{ph1}" msgstr "{ph0}檢查CSV寫入器{ph1}" -#: website/public/guides/javascript/index.html:213 +#: website/public/guides/javascript/index.html:217 msgctxt "page:guides/javascript/index.html" msgid "Where does “Export notes” go?" msgstr "\"Export notes(匯出筆記)\"去哪兒了?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/javascript/index.html:214 +#: website/public/guides/javascript/index.html:218 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4485,7 +4493,7 @@ msgstr "" "本指南使用一個小型 Electron 應用。點選{ph0}Export notes(匯出筆記){ph1}後,頁面呼叫 " "API,透過程序邊界進入主程序,最後寫出 CSV。這個行為分散在幾個檔案中。" -#: website/public/guides/javascript/index.html:221 +#: website/public/guides/javascript/index.html:225 msgctxt "page:guides/javascript/index.html" msgid "The CSV export across Electron processes" msgstr "該 CSV 跨匯出 Electron 過程" @@ -4499,7 +4507,7 @@ msgstr "該 CSV 跨匯出 Electron 過程" #. {ph6}: <code>renderer.js</code> #. {ph7}: <code>preload.js</code> #. {ph8}: </span > -#: website/public/guides/javascript/index.html:225 +#: website/public/guides/javascript/index.html:229 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4514,7 +4522,7 @@ msgstr "{ph0}渲染器→預載入{ph1}{ph2}{ph3}{ph4}{ph5}{ph6} 呼叫由 {ph7} #. {ph4}: </span > #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/guides/javascript/index.html:233 +#: website/public/guides/javascript/index.html:237 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4529,7 +4537,7 @@ msgstr "{ph0}程序之間{ph1}{ph2}{ph3}{ph4}{ph5}預載入呼叫IPC通道:主 #. {ph4}: <span class="flow-note" > #. {ph5}: <code>main.js</code> #. {ph6}: </span > -#: website/public/guides/javascript/index.html:241 +#: website/public/guides/javascript/index.html:245 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4540,13 +4548,13 @@ msgstr "{ph0}主程序{ph1}{ph2}匯出處理函式{ph3}{ph4}{ph5}處理這個通 #. {ph0}: <code>csv.js</code> #. {ph1}: <code>main.js</code> #. {ph2}: <code>downloads/notes.csv</code> -#: website/public/guides/javascript/index.html:250 +#: website/public/guides/javascript/index.html:254 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} formats the notes → {ph1} writes {ph2}." msgstr "{ph0} 格式化註釋→ {ph1} 寫道 {ph2}." -#: website/public/guides/javascript/index.html:254 +#: website/public/guides/javascript/index.html:258 msgctxt "page:guides/javascript/index.html" msgid "" "REA matches the literal IPC call to its handler and identifies the exposed " @@ -4554,14 +4562,14 @@ msgid "" "executes." msgstr "REA將字面IPC呼叫與其處理程式相匹配,並標識公開的API。 路徑是從程式碼中推斷出來的;執行時捕獲可以檢查執行的內容。" -#: website/public/guides/javascript/index.html:262 +#: website/public/guides/javascript/index.html:266 msgctxt "page:guides/javascript/index.html" msgid "Ask about the CSV export" msgstr "詢問有關 CSV 匯出" #. {ph0}: <a href="../../get-started/#agent"> #. {ph1}: </a> -#: website/public/guides/javascript/index.html:263 +#: website/public/guides/javascript/index.html:267 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4577,14 +4585,14 @@ msgstr "{ph0}將你的程式設計助手連線到 REA{ph1} 並給它的應用程 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/javascript/index.html:269 +#: website/public/guides/javascript/index.html:273 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/guides/javascript/index.html:273 -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:277 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy" msgstr "複製" @@ -4595,7 +4603,7 @@ msgstr "複製" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/javascript/index.html:282 +#: website/public/guides/javascript/index.html:286 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4604,7 +4612,7 @@ msgid "" msgstr "{ph0}›{ph1}{ph2}用 REA 找出這個應用匯出筆記時發生了什麼。CSV 檔案在哪裡建立?{ph3}{ph4}{ph5}" #. {ph0}: <code>app.asar</code> -#: website/public/guides/javascript/index.html:290 +#: website/public/guides/javascript/index.html:294 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4612,7 +4620,7 @@ msgid "" "{ph0}." msgstr "示例提示。 包括應用程式資料夾的絕對路徑或 {ph0}." -#: website/public/guides/javascript/index.html:294 +#: website/public/guides/javascript/index.html:298 msgctxt "page:guides/javascript/index.html" msgid "" "REA reads the application files and builds a map of entrypoints, modules and" @@ -4620,17 +4628,17 @@ msgid "" " the export feature." msgstr "REA讀取應用程式檔案並構建入口點,模組和流程邊界的對映。 你的程式設計助手使用該對映將調查範圍縮小到匯出功能。" -#: website/public/guides/javascript/index.html:301 +#: website/public/guides/javascript/index.html:305 msgctxt "page:guides/javascript/index.html" msgid "Trace the export code" msgstr "跟蹤匯出程式碼" -#: website/public/guides/javascript/index.html:302 +#: website/public/guides/javascript/index.html:306 msgctxt "page:guides/javascript/index.html" msgid "The page calls a small API" msgstr "頁面呼叫一個小API" -#: website/public/guides/javascript/index.html:315 +#: website/public/guides/javascript/index.html:319 msgctxt "page:guides/javascript/index.html" msgid "" "The page knows the method name. The implementation lives in the preload, " @@ -4639,7 +4647,7 @@ msgstr "頁面知道方法名稱。 實現存在於預載入中,預載入將 #. {ph0}: <code>notes.exportCsv</code> #. {ph1}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:329 +#: website/public/guides/javascript/index.html:333 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4649,7 +4657,7 @@ msgstr "REA 記錄 {ph0} 和直接寫在程式碼中的通道名 {ph1},並將 #. {ph0}: <code>csv.js</code> #. {ph1}: <code>notes.csv</code> -#: website/public/guides/javascript/index.html:346 +#: website/public/guides/javascript/index.html:350 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4657,14 +4665,14 @@ msgid "" "and the main process writes {ph1} into the user's Downloads folder." msgstr "讀取處理函式就能回答最初的問題:{ph0} 格式化筆記,主程序將 {ph1} 寫入使用者的下載資料夾。" -#: website/public/guides/javascript/index.html:363 +#: website/public/guides/javascript/index.html:367 msgctxt "page:guides/javascript/index.html" msgid "" "Recorded by REA 4.1.0 on the downloadable example below. Source locations " "accompany the API, channel and handler findings." msgstr "使用 REA 4.1.0 分析下面可下載的示例。API、通道和處理函式的結果均附有原始碼位置。" -#: website/public/guides/javascript/index.html:369 +#: website/public/guides/javascript/index.html:373 msgctxt "page:guides/javascript/index.html" msgid "Analyze the example yourself" msgstr "自己分析例子" @@ -4672,25 +4680,25 @@ msgstr "自己分析例子" #. {ph0}: <a class="button" href="../../examples/notes-example.zip" #. download="notes-example.zip" > #. {ph1}: </a > -#: website/public/guides/javascript/index.html:376 +#: website/public/guides/javascript/index.html:380 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0}Download example ZIP{ph1}" msgstr "{ph0}下載示例ZIP{ph1}" -#: website/public/guides/javascript/index.html:385 +#: website/public/guides/javascript/index.html:389 msgctxt "page:guides/javascript/index.html" msgid "Browse the six source files" msgstr "瀏覽六個原始檔" -#: website/public/guides/javascript/index.html:421 +#: website/public/guides/javascript/index.html:425 msgctxt "page:guides/javascript/index.html" msgid "Static application analysis" msgstr "靜態應用分析" #. {ph0}: <code>normalized_result.summary.ipc</code> #. {ph1}: <code>normalized_result.graph</code> -#: website/public/guides/javascript/index.html:434 +#: website/public/guides/javascript/index.html:438 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4698,7 +4706,7 @@ msgid "" "channel and one matching handler in {ph0}. Source locations are in {ph1}." msgstr "將路徑替換為你解壓縮的資料夾。 你應該在以下位置找到一個IPC通道和一個匹配的處理程式 {ph0}. 源位置在 {ph1}." -#: website/public/guides/javascript/index.html:440 +#: website/public/guides/javascript/index.html:444 msgctxt "page:guides/javascript/index.html" msgid "" "For your own app, use the same command with its directory or ASAR path. An " @@ -4707,13 +4715,13 @@ msgid "" msgstr "" "對於你自己的應用程式,請對其目錄或ASARpath使用相同的命令。 程式設計助手可以使用REA的功能跟蹤工具跟隨文字字串,API名稱或IPC通道。" -#: website/public/guides/javascript/index.html:447 +#: website/public/guides/javascript/index.html:451 msgctxt "page:guides/javascript/index.html" msgid "Inspect the CSV writer" msgstr "檢查CSV寫入器" #. {ph0}: <code>notes:export</code> -#: website/public/guides/javascript/index.html:449 +#: website/public/guides/javascript/index.html:453 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4721,7 +4729,7 @@ msgid "" "happens if writing the file fails?" msgstr "追蹤 {ph0} 到處理函式。哪些輸入傳給 CSV 寫入函式?如果寫入失敗,會怎樣?" -#: website/public/guides/javascript/index.html:455 +#: website/public/guides/javascript/index.html:459 msgctxt "page:guides/javascript/index.html" msgid "" "Use the source locations to inspect those details. Computed channel names " @@ -4733,7 +4741,7 @@ msgstr "使用源位置檢查這些詳細資訊。 計算的通道名稱和不 #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/guides/javascript/index.html:461 +#: website/public/guides/javascript/index.html:465 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4745,7 +4753,7 @@ msgstr "{ph0}追蹤 Notion 剪貼簿橋接程式碼{ph1}{ph2}把同樣的方法 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:467 +#: website/public/guides/javascript/index.html:471 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4757,7 +4765,7 @@ msgstr "{ph0}觀察瀏覽器匯出{ph1}{ph2}捕獲一個真正的點選,看看 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/guides/javascript/index.html:473 +#: website/public/guides/javascript/index.html:477 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -4778,32 +4786,32 @@ msgid "" "result." msgstr "透過具有REA的渲染器API,預載入和IPC處理程式跟蹤Notes CSV匯出。 包括可下載的示例檔案和經過驗證的分析結果。" -#: website/public/guides/javascript/index.html:201 +#: website/public/guides/javascript/index.html:205 msgctxt "page:guides/javascript/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/guides/javascript/index.html:211 +#: website/public/guides/javascript/index.html:215 msgctxt "page:guides/javascript/index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/guides/javascript/index.html:273 +#: website/public/guides/javascript/index.html:277 msgctxt "page:guides/javascript/index.html" msgid "Copy example prompt" msgstr "複製示例提示" -#: website/public/guides/javascript/index.html:422 +#: website/public/guides/javascript/index.html:426 msgctxt "page:guides/javascript/index.html" msgid "Copy static application analysis" msgstr "複製靜態應用程式分析" -#: website/public/guides/javascript/index.html:499 +#: website/public/guides/javascript/index.html:503 msgctxt "page:guides/javascript/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/guides/native/index.html:108 +#: website/public/guides/native/index.html:103 msgctxt "page:guides/native/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -4812,34 +4820,34 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/guides/native/index.html:190 +#: website/public/guides/native/index.html:194 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Home{ph1} / {ph2}Guides{ph3} / Native analysis" msgstr "{ph0}首頁{ph1} / {ph2}指南{ph3} /原生分析" #. {ph0}: <br /> -#: website/public/guides/native/index.html:193 +#: website/public/guides/native/index.html:197 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "Recover DX-Ball's{ph0}sound-pan calculation." msgstr "恢復DX-Ball的{ph0}左/右聲音位置的計算。" -#: website/public/guides/native/index.html:194 +#: website/public/guides/native/index.html:198 msgctxt "page:guides/native/index.html" msgid "" "Inspect the original instructions, identify the input and constants, then " "check the recovered C." msgstr "檢查原始指令,識別輸入和常量,然後檢查恢復的C。" -#: website/public/guides/native/index.html:201 +#: website/public/guides/native/index.html:205 msgctxt "page:guides/native/index.html" msgid "In this guide" msgstr "在本指南中" #. {ph0}: <a href="#example"> #. {ph1}: </a> -#: website/public/guides/native/index.html:203 +#: website/public/guides/native/index.html:207 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}The example{ph1}" @@ -4847,7 +4855,7 @@ msgstr "{ph0}例子{ph1}" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/guides/native/index.html:204 +#: website/public/guides/native/index.html:208 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -4855,7 +4863,7 @@ msgstr "{ph0}問問你的程式設計助手{ph1}" #. {ph0}: <a href="#follow"> #. {ph1}: </a> -#: website/public/guides/native/index.html:205 +#: website/public/guides/native/index.html:209 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Read the REA results{ph1}" @@ -4863,7 +4871,7 @@ msgstr "{ph0}閱讀REA結果{ph1}" #. {ph0}: <a href="#result"> #. {ph1}: </a> -#: website/public/guides/native/index.html:206 +#: website/public/guides/native/index.html:210 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Recover and check{ph1}" @@ -4871,18 +4879,18 @@ msgstr "{ph0}恢復和檢查{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/guides/native/index.html:207 +#: website/public/guides/native/index.html:211 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}Use your own binary{ph1}" msgstr "{ph0}使用你自己的二進位制檔案{ph1}" -#: website/public/guides/native/index.html:212 +#: website/public/guides/native/index.html:216 msgctxt "page:guides/native/index.html" msgid "Calculate left/right sound panning" msgstr "計算左/右立體聲聲音定位" -#: website/public/guides/native/index.html:213 +#: website/public/guides/native/index.html:217 msgctxt "page:guides/native/index.html" msgid "" "In DX-Ball, a brick hit supplies a horizontal screen position. The sound " @@ -4891,7 +4899,7 @@ msgstr "在DX-Ball中,磚擊提供水平螢幕位置。 聲音程式碼將其 #. {ph0}: <code>0x00406400</code> #. {ph1}: <code>__ftol()</code> -#: website/public/guides/native/index.html:217 +#: website/public/guides/native/index.html:221 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4901,7 +4909,7 @@ msgid "" msgstr "" "啟動函式, {ph0},有一個簡短的反編譯器結果:呼叫 {ph1}. REA 還返回其指令和呼叫者,這給程式設計助手一種方法來調查丟失的算術。" -#: website/public/guides/native/index.html:224 +#: website/public/guides/native/index.html:228 msgctxt "page:guides/native/index.html" msgid "New to these terms?" msgstr "新的這些條款?" @@ -4910,7 +4918,7 @@ msgstr "新的這些條款?" #. {ph1}: </strong> #. {ph2}: <code>MOV</code> #. {ph3}: <code>ADD</code> -#: website/public/guides/native/index.html:226 +#: website/public/guides/native/index.html:230 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4920,7 +4928,7 @@ msgstr "{ph0}指令:{ph1}處理器執行的步驟,以 {ph2}、{ph3} 這樣 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:231 +#: website/public/guides/native/index.html:235 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4930,7 +4938,7 @@ msgstr "{ph0}反編譯器結果/虛擬碼:{ph1} 分析工具試圖將指令轉 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:236 +#: website/public/guides/native/index.html:240 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4941,7 +4949,7 @@ msgstr "{ph0}呼叫方:{ph1}呼叫當前函式的函式,可以看出傳入 #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>0x00406400</code> -#: website/public/guides/native/index.html:240 +#: website/public/guides/native/index.html:244 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4951,7 +4959,7 @@ msgstr "{ph0}地址:{ph1} 程式中的一個位置,用十六進位制編寫, #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:244 +#: website/public/guides/native/index.html:248 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4959,7 +4967,7 @@ msgid "" "and decoded." msgstr "{ph0}常量:{ph1} 固定數字儲存在程式中,讀取為原始位元組和解碼。" -#: website/public/guides/native/index.html:251 +#: website/public/guides/native/index.html:255 msgctxt "page:guides/native/index.html" msgid "Three pieces of evidence, one calculation" msgstr "三件證據,一個計算" @@ -4970,7 +4978,7 @@ msgstr "三件證據,一個計算" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/guides/native/index.html:255 +#: website/public/guides/native/index.html:259 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -4985,7 +4993,7 @@ msgstr "{ph0}01 · 指令{ph1}{ph2}整數輸入{ph3}{ph4}從棧讀取一個值 #. {ph4}: <span class="flow-note" > #. {ph5}: <code>20 + 30 × tile_x</code> #. {ph6}: </span > -#: website/public/guides/native/index.html:263 +#: website/public/guides/native/index.html:267 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5001,7 +5009,7 @@ msgstr "{ph0}02 · 呼叫方{ph1}{ph2}螢幕座標{ph3}{ph4}磚塊碰撞處理 #. {ph5}: <code>1.5625</code> #. {ph6}: <code>500.0</code> #. {ph7}: </span > -#: website/public/guides/native/index.html:271 +#: website/public/guides/native/index.html:275 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5010,14 +5018,14 @@ msgid "" msgstr "" "{ph0}03 · 資料位元組{ph1}{ph2}數值常量{ph3}{ph4}引用的位元組解碼為 {ph5}、{ph6} 和一個縮放係數。{ph7}" -#: website/public/guides/native/index.html:283 +#: website/public/guides/native/index.html:287 msgctxt "page:guides/native/index.html" msgid "" "REA supplies the instructions, call relationship and bytes. The agent " "interprets them together." msgstr "REA提供指令,呼叫關係和位元組。 程式設計助手一起解釋它們。" -#: website/public/guides/native/index.html:290 +#: website/public/guides/native/index.html:294 msgctxt "page:guides/native/index.html" msgid "Ask about the behavior" msgstr "詢問行為" @@ -5026,7 +5034,7 @@ msgstr "詢問行為" #. {ph1}: </a > #. {ph2}: <a href="../../get-started/#native" > #. {ph3}: </a > -#: website/public/guides/native/index.html:291 +#: website/public/guides/native/index.html:295 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5034,19 +5042,19 @@ msgid "" "analysis tool{ph3}, provide the local executable and a question:" msgstr "{ph0}將 REA 連線到助手{ph1}並{ph2}配置原生分析工具{ph3}後,提供本地可執行檔案和一個問題:" -#: website/public/guides/native/index.html:302 +#: website/public/guides/native/index.html:306 msgctxt "page:guides/native/index.html" msgid "Which analysis tool should I use?" msgstr "我應該使用哪種分析工具?" -#: website/public/guides/native/index.html:303 +#: website/public/guides/native/index.html:307 msgctxt "page:guides/native/index.html" msgid "REA needs one of these to read native programs:" msgstr "REA需要其中一個來閱讀原生程式:" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:305 +#: website/public/guides/native/index.html:309 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5059,7 +5067,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:311 +#: website/public/guides/native/index.html:315 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5071,7 +5079,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:316 +#: website/public/guides/native/index.html:320 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5080,7 +5088,7 @@ msgstr "{ph0} IDA {ph1} (Windows):用於具有MCP註冊的現有IDA設定。" #. {ph0}: <a href="../../get-started/#native"> #. {ph1}: </a> -#: website/public/guides/native/index.html:321 +#: website/public/guides/native/index.html:325 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "See {ph0}Set up native analysis{ph1} for the steps." @@ -5094,14 +5102,14 @@ msgstr "見 {ph0}設定原生分析{ph1} 為步驟。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/guides/native/index.html:329 +#: website/public/guides/native/index.html:333 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/guides/native/index.html:333 -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:337 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy" msgstr "複製" @@ -5112,7 +5120,7 @@ msgstr "複製" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/guides/native/index.html:342 +#: website/public/guides/native/index.html:346 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5121,7 +5129,7 @@ msgid "" msgstr "" "{ph0}›{ph1}{ph2}用 REA 找出 DX-Ball 如何計算聲音的左右位置。解釋計算過程,並展示程式碼。{ph3}{ph4}{ph5}" -#: website/public/guides/native/index.html:350 +#: website/public/guides/native/index.html:354 msgctxt "page:guides/native/index.html" msgid "" "Example prompt. Give your agent the path to your local DX-Ball 1.07 " @@ -5131,7 +5139,7 @@ msgstr "" "示例 prompt。把本地 DX-Ball 1.07 可執行檔案的路徑交給助手。REA 不附帶遊戲,需要用自己的副本,也可以換成手裡的其他小型 " "Windows 程式,問同類問題。" -#: website/public/guides/native/index.html:357 +#: website/public/guides/native/index.html:361 msgctxt "page:guides/native/index.html" msgid "How do I get a file's full path?" msgstr "如何獲取檔案的完整路徑?" @@ -5140,7 +5148,7 @@ msgstr "如何獲取檔案的完整路徑?" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:359 +#: website/public/guides/native/index.html:363 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5154,7 +5162,7 @@ msgstr "" #. {ph1}: </strong> #. {ph2}: <em> #. {ph3}: </em> -#: website/public/guides/native/index.html:364 +#: website/public/guides/native/index.html:368 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5164,7 +5172,7 @@ msgstr "{ph0} macOS :{ph1} 在Finder中,右鍵單擊檔案,按住選項並 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/guides/native/index.html:368 +#: website/public/guides/native/index.html:372 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5172,30 +5180,30 @@ msgid "" "appears." msgstr "{ph0}任何系統:{ph1} 將檔案拖到終端視窗中並顯示其路徑。" -#: website/public/guides/native/index.html:376 +#: website/public/guides/native/index.html:380 msgctxt "page:guides/native/index.html" msgid "Read the REA results" msgstr "閱讀REA結果" -#: website/public/guides/native/index.html:377 +#: website/public/guides/native/index.html:381 msgctxt "page:guides/native/index.html" msgid "Read the input" msgstr "閱讀輸入" -#: website/public/guides/native/index.html:386 +#: website/public/guides/native/index.html:390 msgctxt "page:guides/native/index.html" msgid "" "The instructions load an integer argument and convert it for floating-point " "arithmetic. This is the input absent from the first pseudocode view." msgstr "指令載入一個整數引數並將其轉換為浮點算術。 這是第一個虛擬碼檢視中沒有的輸入。" -#: website/public/guides/native/index.html:391 +#: website/public/guides/native/index.html:395 msgctxt "page:guides/native/index.html" msgid "Follow the caller" msgstr "跟隨呼叫方" #. {ph0}: <code>0x14</code> -#: website/public/guides/native/index.html:400 +#: website/public/guides/native/index.html:404 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5203,24 +5211,24 @@ msgid "" "tile coordinate by 30; adding {ph0} (20) gives the brick's screen position." msgstr "REA 找到磚塊碰撞處理函式。它先把磚塊橫座標乘以 30,再加上 {ph0}(20),得到磚塊的螢幕位置。" -#: website/public/guides/native/index.html:405 +#: website/public/guides/native/index.html:409 msgctxt "page:guides/native/index.html" msgid "Read the referenced constants" msgstr "讀取引用的常量" -#: website/public/guides/native/index.html:416 +#: website/public/guides/native/index.html:420 msgctxt "page:guides/native/index.html" msgid "" "The arithmetic references these addresses. Reading the bytes supplies the " "actual values; the instruction order tells the agent how they are used." msgstr "算術引用這些地址。 讀取位元組提供實際值;指令順序告訴程式設計助手如何使用它們。" -#: website/public/guides/native/index.html:423 +#: website/public/guides/native/index.html:427 msgctxt "page:guides/native/index.html" msgid "Write and check the recovered function" msgstr "寫入並檢查恢復的函式" -#: website/public/guides/native/index.html:432 +#: website/public/guides/native/index.html:436 msgctxt "page:guides/native/index.html" msgid "" "With a scale of 1.0, screen positions 0, 320 and 640 map to −500, 0 and 500 " @@ -5228,7 +5236,7 @@ msgid "" "the center of the stereo field." msgstr "比例為1.0時,螢幕位置0、320和640在整數轉換之前對映到-500、0和500。 計算將螢幕的中心置於立體場的中心。" -#: website/public/guides/native/index.html:437 +#: website/public/guides/native/index.html:441 msgctxt "page:guides/native/index.html" msgid "" "The agent used REA's findings to write the C. Separate checks compared 3,205" @@ -5238,20 +5246,20 @@ msgstr "程式設計助手使用REA的發現來編寫C.單獨的檢查將3,205 #. {ph0}: <a href="../../showcase/dx-ball/#sound-pan" > #. {ph1}: </a > -#: website/public/guides/native/index.html:442 +#: website/public/guides/native/index.html:446 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "{ph0}See the full investigation and assembly-to-C comparison{ph1}" msgstr "{ph0}檢視完整的調查和組裝到C的比較{ph1}" -#: website/public/guides/native/index.html:449 +#: website/public/guides/native/index.html:453 msgctxt "page:guides/native/index.html" msgid "Try it with your own binary" msgstr "用你自己的二進位制檔案試試" #. {ph0}: <a href="../../get-started/#native" > #. {ph1}: </a > -#: website/public/guides/native/index.html:450 +#: website/public/guides/native/index.html:454 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5263,20 +5271,20 @@ msgstr "" "{ph0}連線原生分析提供程式{ph1},然後給你的程式設計助手一個本地可執行檔案或庫和一個要調查的函式。 " "有用的起始問題包括\"如何解析此檔案?\"或\"哪個函式處理此選單操作?”" -#: website/public/guides/native/index.html:457 +#: website/public/guides/native/index.html:461 msgctxt "page:guides/native/index.html" msgid "" "If you already know a function name or address, you can query it from the " "terminal. For a configured Ghidra installation:" msgstr "如果你已經知道函式名稱或地址,則可以從終端查詢它。 對於已配置的Ghidra安裝:" -#: website/public/guides/native/index.html:463 +#: website/public/guides/native/index.html:467 msgctxt "page:guides/native/index.html" msgid "Function analysis" msgstr "函式分析" #. {ph0}: <code>main</code> -#: website/public/guides/native/index.html:476 +#: website/public/guides/native/index.html:480 #, python-brace-format msgctxt "page:guides/native/index.html" msgid "" @@ -5288,7 +5296,7 @@ msgstr "" "替換目標路徑和 {ph0} 使用你自己的函式名稱或地址。 每個 CLI 呼叫匯入並分析二進位制檔案,然後關閉其會話。 你的程式設計助手 MCP " "查詢在該會話開啟時重用匯入的二進位制檔案。" -#: website/public/guides/native/index.html:482 +#: website/public/guides/native/index.html:486 msgctxt "page:guides/native/index.html" msgid "" "Read the pseudocode alongside instructions and references. When a result " @@ -5307,50 +5315,50 @@ msgid "" "caller, read constants and check reconstructed C." msgstr "使用REA恢復本機計算:檢查指令,遵循呼叫者,讀取常量並檢查重構的C。" -#: website/public/guides/native/index.html:200 +#: website/public/guides/native/index.html:204 msgctxt "page:guides/native/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/guides/native/index.html:210 +#: website/public/guides/native/index.html:214 msgctxt "page:guides/native/index.html" msgid "Native analysis" msgstr "機器程式碼程式分析" -#: website/public/guides/native/index.html:333 +#: website/public/guides/native/index.html:337 msgctxt "page:guides/native/index.html" msgid "Copy example prompt" msgstr "複製示例提示" -#: website/public/guides/native/index.html:464 +#: website/public/guides/native/index.html:468 msgctxt "page:guides/native/index.html" msgid "Copy function analysis" msgstr "複製函式分析" -#: website/public/guides/native/index.html:505 +#: website/public/guides/native/index.html:509 msgctxt "page:guides/native/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/index.html:110 +#: website/public/index.html:105 msgctxt "page:index.html" msgid "Skip to content" msgstr "跳轉到內容" -#: website/public/index.html:192 website/public/index.html:202 -#: website/public/index.html:200 +#: website/public/index.html:196 website/public/index.html:206 +#: website/public/index.html:204 msgctxt "page:index.html" msgid "On this page" msgstr "在本頁" -#: website/public/index.html:193 website/public/index.html:247 +#: website/public/index.html:197 website/public/index.html:251 msgctxt "page:index.html" msgid "Set up REA" msgstr "安裝與配置 REA" #. {ph0}: <a href="#setup" aria-current="location"> #. {ph1}: </a> -#: website/public/index.html:204 +#: website/public/index.html:208 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Set up REA{ph1}" @@ -5358,7 +5366,7 @@ msgstr "{ph0}安裝與配置 REA{ph1}" #. {ph0}: <a href="#what-is-re"> #. {ph1}: </a> -#: website/public/index.html:205 +#: website/public/index.html:209 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}What is RE?{ph1}" @@ -5366,7 +5374,7 @@ msgstr "{ph0}什麼是RE?{ph1}" #. {ph0}: <a href="#how-rea-helps"> #. {ph1}: </a> -#: website/public/index.html:206 +#: website/public/index.html:210 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}How REA helps{ph1}" @@ -5374,7 +5382,7 @@ msgstr "{ph0}REA 如何幫忙{ph1}" #. {ph0}: <a href="#dinosaur"> #. {ph1}: </a> -#: website/public/index.html:207 +#: website/public/index.html:211 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Dinosaur game{ph1}" @@ -5382,7 +5390,7 @@ msgstr "{ph0}恐龍游戲{ph1}" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:208 +#: website/public/index.html:212 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Calculator{ph1}" @@ -5390,7 +5398,7 @@ msgstr "{ph0}計算器{ph1}" #. {ph0}: <a href="#try-rea"> #. {ph1}: </a> -#: website/public/index.html:209 +#: website/public/index.html:213 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Try REA{ph1}" @@ -5398,7 +5406,7 @@ msgstr "{ph0}試試REA {ph1}" #. {ph0}: <a href="#analyze"> #. {ph1}: </a> -#: website/public/index.html:210 +#: website/public/index.html:214 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Go deeper{ph1}" @@ -5406,7 +5414,7 @@ msgstr "{ph0}更深入{ph1}" #. {ph0}: <a href="#questions"> #. {ph1}: </a> -#: website/public/index.html:211 +#: website/public/index.html:215 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Help & feedback{ph1}" @@ -5414,25 +5422,25 @@ msgstr "{ph0}幫助和反饋{ph1}" #. {ph0}: <a href="#community"> #. {ph1}: </a> -#: website/public/index.html:212 +#: website/public/index.html:216 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Community{ph1}" msgstr "{ph0}社群{ph1}" -#: website/public/index.html:221 +#: website/public/index.html:225 msgctxt "page:index.html" msgid "Reverse engineering, with your coding agent" msgstr "和程式設計助手一起做逆向工程" #. {ph0}: <br /> -#: website/public/index.html:222 +#: website/public/index.html:226 #, python-brace-format msgctxt "page:index.html" msgid "Find out how{ph0}software works." msgstr "弄清楚{ph0}軟體如何工作。" -#: website/public/index.html:223 +#: website/public/index.html:227 msgctxt "page:index.html" msgid "" "REA gives your agent the tools to inspect a program and explain what it " @@ -5441,7 +5449,7 @@ msgstr "REA 為程式設計助手提供分析工具,讓它檢查程式並解 #. {ph0}: <a href="#analysis-guides"> #. {ph1}: </a> -#: website/public/index.html:237 +#: website/public/index.html:241 #, python-brace-format msgctxt "page:index.html" msgid "Already know RE? {ph0}Skip to analysis guides →{ph1}" @@ -5449,13 +5457,13 @@ msgstr "已經瞭解逆向工程?{ph0}直接看分析指南 →{ph1}" #. {ph0}: <a href="blog/"> #. {ph1}: </a> -#: website/public/index.html:241 +#: website/public/index.html:245 #, python-brace-format msgctxt "page:index.html" msgid "Want to go deeper? {ph0}Read the Blog →{ph1}" msgstr "想深入瞭解?{ph0}閱讀部落格 →{ph1}" -#: website/public/index.html:248 +#: website/public/index.html:252 msgctxt "page:index.html" msgid "Copy this into your coding agent:" msgstr "把這段話複製給程式設計助手:" @@ -5468,38 +5476,38 @@ msgstr "把這段話複製給程式設計助手:" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:251 +#: website/public/index.html:255 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/index.html:256 website/public/index.html:278 -#: website/public/index.html:493 website/public/index.html:661 -#: website/public/index.html:897 website/public/index.html:1059 -#: website/public/index.html:1087 +#: website/public/index.html:260 website/public/index.html:282 +#: website/public/index.html:497 website/public/index.html:665 +#: website/public/index.html:901 website/public/index.html:1063 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy" msgstr "複製" -#: website/public/index.html:275 +#: website/public/index.html:279 msgctxt "page:index.html" msgid "Or run this in your terminal:" msgstr "也可以在終端執行:" -#: website/public/index.html:287 +#: website/public/index.html:291 msgctxt "page:index.html" msgid "Approve the setup plan, then restart your agent." msgstr "確認安裝計劃後,重啟程式設計助手。" -#: website/public/index.html:302 +#: website/public/index.html:306 msgctxt "page:index.html" msgid "What is reverse engineering?" msgstr "什麼是逆向工程?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:303 +#: website/public/index.html:307 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5512,7 +5520,7 @@ msgstr "透過{ph0}檢查程式本身{ph1},弄清軟體如何工作。" #. {ph3}: </mark> #. {ph4}: <mark class="prose-highlight"> #. {ph5}: </mark> -#: website/public/index.html:308 +#: website/public/index.html:312 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5522,7 +5530,7 @@ msgstr "目標是理解一項功能,從而能{ph0}解釋它{ph1}、{ph2}修改 #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:326 +#: website/public/index.html:330 #, python-brace-format msgctxt "page:index.html" msgid "Before REA · You investigate it {ph0}yourself{ph1}" @@ -5530,7 +5538,7 @@ msgstr "使用 REA 之前 · 你要{ph0}親自調查{ph1}" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:335 +#: website/public/index.html:339 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}01{ph1} Decode branches" @@ -5538,7 +5546,7 @@ msgstr "{ph0}01{ph1} 分析分支" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:343 +#: website/public/index.html:347 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}02{ph1} Trace calls" @@ -5546,7 +5554,7 @@ msgstr "{ph0}02{ph1} 追蹤函式呼叫" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/index.html:351 +#: website/public/index.html:355 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}03{ph1} Recover the rule" @@ -5556,20 +5564,20 @@ msgstr "{ph0}03{ph1} 還原計算規則" #. {ph1}: </span> #. {ph2}: <span class="assembly-disclosure" aria-hidden="true"> #. {ph3}: </span> -#: website/public/index.html:366 +#: website/public/index.html:370 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Original x64 · selected instructions{ph1} {ph2}{ph3}" msgstr "{ph0}原始 x64 指令節選{ph1} {ph2}{ph3}" -#: website/public/index.html:405 +#: website/public/index.html:409 msgctxt "page:index.html" msgid "01 · Which branch?" msgstr "01 · 走哪個分支?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:406 +#: website/public/index.html:410 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5577,29 +5585,29 @@ msgid "" "these?”" msgstr "“{ph0}0x5b?0x5c?{ph1}兩個跳轉去了同一個位置。它們對應哪些運算子?”" -#: website/public/index.html:410 +#: website/public/index.html:414 msgctxt "page:index.html" msgid "Look up the command IDs, then label the branch." msgstr "查詢命令 ID,再標明分支含義。" -#: website/public/index.html:416 +#: website/public/index.html:420 msgctxt "page:index.html" msgid "Divide ÷" msgstr "除÷" -#: website/public/index.html:420 +#: website/public/index.html:424 msgctxt "page:index.html" msgid "Multiply ×" msgstr "乘×" -#: website/public/index.html:425 +#: website/public/index.html:429 msgctxt "page:index.html" msgid "02 · What do the calls do?" msgstr "02 · 這些函式呼叫做什麼?" #. {ph0}: <strong> #. {ph1}: </strong > -#: website/public/index.html:426 +#: website/public/index.html:430 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5607,24 +5615,24 @@ msgid "" "value goes in?{ph1}”" msgstr "“100 很明確,但函式呼叫只有地址。{ph0}哪個負責除法?傳進去的是哪個值?{ph1}”" -#: website/public/index.html:431 +#: website/public/index.html:435 msgctxt "page:index.html" msgid "Inspect the helpers and trace the stored values." msgstr "檢查輔助函式,追蹤儲存的數值。" -#: website/public/index.html:441 +#: website/public/index.html:445 msgctxt "page:index.html" msgid "Divide" msgstr "除法" -#: website/public/index.html:446 +#: website/public/index.html:450 msgctxt "page:index.html" msgid "03 · What is the rule?" msgstr "03 · 規則是什麼?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:447 +#: website/public/index.html:451 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5632,19 +5640,19 @@ msgid "" "after +.”" msgstr "“這個分支乘上了另一個輸入。所以在 + 之後,{ph0}10% 表示 200 的 10%{ph1}。”" -#: website/public/index.html:451 +#: website/public/index.html:455 msgctxt "page:index.html" msgid "Name the operands and check both operator paths." msgstr "確定運算元的含義,並檢查兩條運算路徑。" -#: website/public/index.html:467 website/public/index.html:395 +#: website/public/index.html:471 website/public/index.html:399 msgctxt "page:index.html" msgid "Illustrative expert reasoning" msgstr "專家思考過程示意" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:470 +#: website/public/index.html:474 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5654,20 +5662,20 @@ msgstr "{ph0}你需要讀懂指令、追蹤呼叫,再還原計算過程。{ph1 #. {ph0}: <strong class="prose-highlight"> #. {ph1}: </strong> -#: website/public/index.html:478 +#: website/public/index.html:482 #, python-brace-format msgctxt "page:index.html" msgid "With REA · You ask {ph0}your agent{ph1}" msgstr "使用 REA · 你只需問{ph0}程式設計助手{ph1}" -#: website/public/index.html:482 +#: website/public/index.html:486 msgctxt "page:index.html" msgid "One prompt." msgstr "一句話即可。" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:483 +#: website/public/index.html:487 #, python-brace-format msgctxt "page:index.html" msgid "Ask your agent {ph0}in plain English.{ph1}" @@ -5681,49 +5689,49 @@ msgstr "{ph0}用日常語言{ph1}告訴助手你的問題。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:488 +#: website/public/index.html:492 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Calculator" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 計算器" -#: website/public/index.html:510 +#: website/public/index.html:514 msgctxt "page:index.html" msgid "Example answer · based on the findings" msgstr "示例回答 · 根據分析結果" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:513 +#: website/public/index.html:517 #, python-brace-format msgctxt "page:index.html" msgid "" "After +, the % button takes {ph0}a percentage of the first number.{ph1}" msgstr "在 + 之後,% 按鈕計算的是{ph0}第一個數的百分比。{ph1}" -#: website/public/index.html:525 +#: website/public/index.html:529 msgctxt "page:index.html" msgid "REA supplies" msgstr "REA 提供" -#: website/public/index.html:526 +#: website/public/index.html:530 msgctxt "page:index.html" msgid "The handler’s instructions, decompiled code and calls." msgstr "處理函式的指令、反編譯程式碼和呼叫關係。" -#: website/public/index.html:531 +#: website/public/index.html:535 msgctxt "page:index.html" msgid "Your agent explains" msgstr "程式設計助手解釋" -#: website/public/index.html:532 +#: website/public/index.html:536 msgctxt "page:index.html" msgid "Which branch applies, what it calculates and how to rebuild it." msgstr "走哪個分支、怎樣計算,以及如何重新實現。" #. {ph0}: <a href="#calculator"> #. {ph1}: </a> -#: website/public/index.html:539 +#: website/public/index.html:543 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5733,7 +5741,7 @@ msgstr "彙編節選自已安裝的計算器 DLL。思考過程和回答用於 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:550 +#: website/public/index.html:554 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5741,37 +5749,37 @@ msgid "" "Calculator and rebuild its % button." msgstr "{ph0}來試兩個例子。{ph1}先調整遊戲速度,再回到計算器,重新實現 % 按鈕。" -#: website/public/index.html:556 +#: website/public/index.html:560 msgctxt "page:index.html" msgid "Example 01 · Chrome’s dinosaur game" msgstr "示例 01 · Chrome 小恐龍游戲" -#: website/public/index.html:557 +#: website/public/index.html:561 msgctxt "page:index.html" msgid "Why does the dinosaur get faster?" msgstr "為什麼恐龍變得更快?" -#: website/public/index.html:561 website/public/index.html:799 +#: website/public/index.html:565 website/public/index.html:803 msgctxt "page:index.html" msgid "Goal" msgstr "目標" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:562 +#: website/public/index.html:566 #, python-brace-format msgctxt "page:index.html" msgid "Rebuild the game with {ph0}adjustable speed.{ph1}" msgstr "重建一個{ph0}速度可調{ph1}的遊戲。" -#: website/public/index.html:568 website/public/index.html:806 +#: website/public/index.html:572 website/public/index.html:810 msgctxt "page:index.html" msgid "Why reverse engineer it?" msgstr "為什麼逆向工程?" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:569 +#: website/public/index.html:573 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5779,61 +5787,61 @@ msgid "" "game{ph1}: how fast it starts, how much it increases and when it stops." msgstr "要復現加速過程,得先找到{ph0}實際執行的遊戲中的規則{ph1}:起始速度是多少、每次增加多少、何時停止加速。" -#: website/public/index.html:578 +#: website/public/index.html:582 msgctxt "page:index.html" msgid "Play the reconstruction" msgstr "試玩重建版" -#: website/public/index.html:610 +#: website/public/index.html:614 msgctxt "page:index.html" msgid "Play" msgstr "開始" -#: website/public/index.html:613 +#: website/public/index.html:617 msgctxt "page:index.html" msgid "Jump ↑" msgstr "跳躍 ↑" -#: website/public/index.html:614 +#: website/public/index.html:618 msgctxt "page:index.html" msgid "Restart" msgstr "重新開始" -#: website/public/index.html:617 +#: website/public/index.html:621 msgctxt "page:index.html" msgid "Speed" msgstr "速度" -#: website/public/index.html:627 +#: website/public/index.html:631 msgctxt "page:index.html" msgid "Use the recovered acceleration rule" msgstr "使用還原的加速規則" -#: website/public/index.html:631 +#: website/public/index.html:635 msgctxt "page:index.html" msgid "Original rule: start at 6, then increase toward 13." msgstr "原版規則:速度從 6 開始,逐漸增加到 13。" -#: website/public/index.html:634 +#: website/public/index.html:638 msgctxt "page:index.html" msgid "Move the slider to set your own speed. Space or Jump clears a cactus." msgstr "拖動滑塊,選擇自己的速度。按空格鍵或“跳躍”越過仙人掌。" -#: website/public/index.html:639 +#: website/public/index.html:643 msgctxt "page:index.html" msgid "" "Enable JavaScript to play the reconstruction. The code and explanation above" " remain readable." msgstr "啟用 JavaScript 即可試玩。上面的程式碼和說明無需 JavaScript 也能閱讀。" -#: website/public/index.html:647 website/public/index.html:877 +#: website/public/index.html:651 website/public/index.html:881 msgctxt "page:index.html" msgid "REA returned" msgstr "REA 返回" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:648 +#: website/public/index.html:652 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5849,7 +5857,7 @@ msgstr "{ph0}頁面實際執行的指令碼。{ph1}助手讀取更新函式和 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:656 +#: website/public/index.html:660 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Dinosaur game" @@ -5861,7 +5869,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 小恐龍游戲 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:670 +#: website/public/index.html:674 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5874,7 +5882,7 @@ msgstr "" #. {ph0}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph1}: </a > -#: website/public/index.html:679 +#: website/public/index.html:683 #, python-brace-format msgctxt "page:index.html" msgid "Inspected target: {ph0}wayou’s Chromium-derived browser edition{ph1}." @@ -5886,7 +5894,7 @@ msgstr "分析目標:{ph0}wayou 基於 Chromium 製作的瀏覽器版本{ph1} #. {ph3}: </strong> #. {ph4}: <strong> #. {ph5}: </strong> -#: website/public/index.html:696 +#: website/public/index.html:700 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5894,12 +5902,12 @@ msgid "" "while speed is below {ph4}13{ph5}." msgstr "{ph0}起始速度為 6。{ph1}速度低於 {ph4}13{ph5} 時,每次沒有發生碰撞的更新增加 {ph2}0.001{ph3}。" -#: website/public/index.html:701 +#: website/public/index.html:705 msgctxt "page:index.html" msgid "Open the speed lab →" msgstr "開啟速度實驗室 →" -#: website/public/index.html:707 +#: website/public/index.html:711 msgctxt "page:index.html" msgid "What each part does" msgstr "各部分負責什麼" @@ -5910,7 +5918,7 @@ msgstr "各部分負責什麼" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:709 +#: website/public/index.html:713 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5924,7 +5932,7 @@ msgstr "{ph0}01 · REA{ph1}{ph2}讀取正在執行的遊戲指令碼{ph3}{ph4} #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:716 +#: website/public/index.html:720 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5939,7 +5947,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:724 +#: website/public/index.html:728 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5947,13 +5955,13 @@ msgid "" "acceleration, then choose your own pace.{ph5}" msgstr "{ph0}03 · 你{ph1}{ph2}調整速度,親自試玩{ph3}{ph4}先體驗原版加速,再選擇自己的節奏。{ph5}" -#: website/public/index.html:735 +#: website/public/index.html:739 msgctxt "page:index.html" msgid "See the script, checks and how to try the analysis" msgstr "檢視指令碼、驗證過程和分析步驟" #. {ph0}: <code>index.js</code> -#: website/public/index.html:738 +#: website/public/index.html:742 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5961,7 +5969,7 @@ msgid "" "and returned the loaded {ph0}, including its source and digest." msgstr "REA 透過本地除錯連線檢查 HTTP 瀏覽器版本,返回了已載入的 {ph0},包含原始碼和摘要。" -#: website/public/index.html:751 +#: website/public/index.html:755 msgctxt "page:index.html" msgid "" "We called the original game’s update function in a controlled browser check," @@ -5973,7 +5981,7 @@ msgstr "" #. {ph0}: <a href="examples/dino-lab/"> #. {ph1}: </a> -#: website/public/index.html:757 +#: website/public/index.html:761 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -5986,7 +5994,7 @@ msgstr "新小遊戲保留了這條速度規則。繪圖、跳躍和碰撞程式 #. {ph1}: </a> #. {ph2}: <a href="https://wayou.github.io/t-rex-runner/" > #. {ph3}: </a > -#: website/public/index.html:763 +#: website/public/index.html:767 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6001,26 +6009,26 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <a href="assets/licenses/dinosaur.txt" > #. {ph3}: </a > -#: website/public/index.html:772 +#: website/public/index.html:776 #, python-brace-format msgctxt "page:index.html" msgid "" "{ph0}Inspected speed code{ph1} · {ph2}Chromium Authors · BSD license{ph3}" msgstr "{ph0}分析的速度程式碼{ph1} · {ph2}Chromium Authors · BSD 許可證{ph3}" -#: website/public/index.html:789 +#: website/public/index.html:793 msgctxt "page:index.html" msgid "Example 02 · Windows Calculator" msgstr "示例 02 · Windows 計算器" -#: website/public/index.html:790 +#: website/public/index.html:794 msgctxt "page:index.html" msgid "Rebuild Calculator’s % button." msgstr "重新實現計算器的 % 按鈕。" #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/index.html:800 +#: website/public/index.html:804 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6029,7 +6037,7 @@ msgstr "做一個小計算器,能{ph0}正確處理 + 和 × 兩種情況。{ph #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/index.html:807 +#: website/public/index.html:811 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6037,29 +6045,29 @@ msgid "" " installed app to find which number the percentage is applied to." msgstr "同一個按鈕,在{ph0}+ 和 × 後採用不同規則。{ph1}我們檢查已安裝的應用,弄清百分比究竟作用於哪個數。" -#: website/public/index.html:816 +#: website/public/index.html:820 msgctxt "page:index.html" msgid "Try the calculation" msgstr "試試計算" -#: website/public/index.html:860 +#: website/public/index.html:864 msgctxt "page:index.html" msgid "Reset" msgstr "重置" -#: website/public/index.html:868 +#: website/public/index.html:872 msgctxt "page:index.html" msgid "10% of 200 = 20. Then 200 + 20 = 220." msgstr "200的10%=20. 則200+20=220。" -#: website/public/index.html:871 +#: website/public/index.html:875 msgctxt "page:index.html" msgid "Interactive illustration of the inspected percentage rule." msgstr "根據實際分析得到的百分比規則製作的互動示例。" #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/index.html:878 +#: website/public/index.html:882 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6069,7 +6077,7 @@ msgstr "{ph0}一個分支除以 100;另一個還要乘上第一個數。{ph1} #. {ph0}: <code>previous = 200</code> #. {ph1}: <code>current = 10</code> -#: website/public/index.html:886 +#: website/public/index.html:890 #, python-brace-format msgctxt "page:index.html" msgid "For this example, {ph0} and {ph1}." @@ -6083,7 +6091,7 @@ msgstr "對於這個例子, {ph0} 和 {ph1}." #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:892 +#: website/public/index.html:896 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6097,7 +6105,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 重建 % 按鈕 #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:906 +#: website/public/index.html:910 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6108,7 +6116,7 @@ msgstr "" "{ph0}›{ph1}{ph2}用 REA 檢查 Windows 計算器的 % 按鈕。還原 + 和 × " "後的規則,再做一個同時採用這兩條規則的小計算器。{ph3}{ph4}{ph5}" -#: website/public/index.html:927 +#: website/public/index.html:931 msgctxt "page:index.html" msgid "With +" msgstr "在 + 之後" @@ -6116,13 +6124,13 @@ msgstr "在 + 之後" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>10% of 200 = 20 → 200 + 20 = 220</code> -#: website/public/index.html:928 +#: website/public/index.html:932 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Take 10% of the first number.{ph1}{ph2}" msgstr "{ph0}取第一個數字的10%。{ph1}{ph2}" -#: website/public/index.html:934 +#: website/public/index.html:938 msgctxt "page:index.html" msgid "With ×" msgstr "在 × 之後" @@ -6130,13 +6138,13 @@ msgstr "在 × 之後" #. {ph0}: <strong> #. {ph1}: </strong > #. {ph2}: <code>200 × 0.1 = 20</code> -#: website/public/index.html:935 +#: website/public/index.html:939 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}Turn 10% into 0.1.{ph1}{ph2}" msgstr "{ph0}把10%變成0.1。{ph1}{ph2}" -#: website/public/index.html:944 +#: website/public/index.html:948 msgctxt "page:index.html" msgid "From the installed app to a working % button" msgstr "從已安裝的應用,到能執行的 % 按鈕" @@ -6148,7 +6156,7 @@ msgstr "從已安裝的應用,到能執行的 % 按鈕" #. {ph4}: <span class="flow-note" > #. {ph5}: <code>100</code> #. {ph6}: </span > -#: website/public/index.html:957 +#: website/public/index.html:961 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6164,7 +6172,7 @@ msgstr "" #. {ph3}: </span > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/index.html:965 +#: website/public/index.html:969 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6175,12 +6183,12 @@ msgstr "" "{ph0}03 · 程式設計助手解釋{ph1}{ph2}解釋並復現規則{ph3}{ph4}對照 Microsoft 的原始碼核實分支,再試試上面的 + " "和 ×。{ph5}" -#: website/public/index.html:976 +#: website/public/index.html:980 msgctxt "page:index.html" msgid "See the real code and how the answer was checked" msgstr "檢視實際程式碼和驗證方式" -#: website/public/index.html:1002 +#: website/public/index.html:1006 msgctxt "page:index.html" msgid "" "Inspected with REA 4.1.0: Windows Calculator 11.2508.4.0, x64. The readable " @@ -6200,7 +6208,7 @@ msgstr "" #. {ph3}: </a > #. {ph4}: <a href="guides/native/"> #. {ph5}: </a> -#: website/public/index.html:1007 +#: website/public/index.html:1011 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6208,29 +6216,29 @@ msgid "" "{ph4}Native setup guide{ph5}" msgstr "{ph0}百分比實現{ph1} · {ph2}Microsoft 測試用例{ph3} · {ph4}原生分析配置指南{ph5}" -#: website/public/index.html:1026 +#: website/public/index.html:1030 msgctxt "page:index.html" msgid "Your first investigation" msgstr "第一次調查" -#: website/public/index.html:1027 +#: website/public/index.html:1031 msgctxt "page:index.html" msgid "Try REA on a small app." msgstr "用一個小應用試試 REA。" -#: website/public/index.html:1028 +#: website/public/index.html:1032 msgctxt "page:index.html" msgid "" "Download our Notes example, trace its CSV export, and check one changed " "input." msgstr "下載 Notes 示例,追蹤 CSV 匯出,再修改一個輸入來驗證。" -#: website/public/index.html:1033 +#: website/public/index.html:1037 msgctxt "page:index.html" msgid "Try the guided example" msgstr "跟著示例開始" -#: website/public/index.html:1042 +#: website/public/index.html:1046 msgctxt "page:index.html" msgid "Want to go deeper?" msgstr "想更深入嗎?" @@ -6239,7 +6247,7 @@ msgstr "想更深入嗎?" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/index.html:1043 +#: website/public/index.html:1047 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6257,13 +6265,13 @@ msgstr "" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1054 +#: website/public/index.html:1058 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Example prompt · Website" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 網站" -#: website/public/index.html:1077 +#: website/public/index.html:1081 msgctxt "page:index.html" msgid "Yes, this one." msgstr "對,就是這個網站。" @@ -6276,7 +6284,7 @@ msgstr "對,就是這個網站。" #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/index.html:1082 +#: website/public/index.html:1086 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6289,7 +6297,7 @@ msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}示例 prompt · 遊戲重建" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/index.html:1096 +#: website/public/index.html:1100 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6301,69 +6309,69 @@ msgstr "" #. {ph0}: <a href="showcase/dx-ball/"> #. {ph1}: </a> -#: website/public/index.html:1105 +#: website/public/index.html:1109 #, python-brace-format msgctxt "page:index.html" msgid "{ph0}See the DX-Ball case study →{ph1}" msgstr "{ph0}檢視 DX-Ball 案例 →{ph1}" -#: website/public/index.html:1110 +#: website/public/index.html:1114 msgctxt "page:index.html" msgid "For setup and analysis steps, choose your target:" msgstr "根據目標選擇配置和分析指南:" -#: website/public/index.html:1115 +#: website/public/index.html:1119 msgctxt "page:index.html" msgid "Native binaries" msgstr "原生二進位制" -#: website/public/index.html:1116 +#: website/public/index.html:1120 msgctxt "page:index.html" msgid "" "Inspect functions, strings, references and call relationships in executables" " and libraries." msgstr "檢查可執行檔案和庫中的函式、字串、引用和函式呼叫關係。" -#: website/public/index.html:1120 +#: website/public/index.html:1124 msgctxt "page:index.html" msgid "Native analysis guide" msgstr "原生分析指南" -#: website/public/index.html:1123 +#: website/public/index.html:1127 msgctxt "page:index.html" msgid "JavaScript & Electron" msgstr "JavaScript&Electron" -#: website/public/index.html:1124 +#: website/public/index.html:1128 msgctxt "page:index.html" msgid "" "Map modules, routes, IPC and native dependencies from an application folder " "or ASAR archive." msgstr "從應用目錄或 ASAR 檔案中分析模組、路由、IPC 和原生依賴。" -#: website/public/index.html:1128 +#: website/public/index.html:1132 msgctxt "page:index.html" msgid "Application workflows" msgstr "應用分析流程" -#: website/public/index.html:1131 +#: website/public/index.html:1135 msgctxt "page:index.html" msgid "Browser & runtime activity" msgstr "瀏覽器與執行時活動" -#: website/public/index.html:1132 +#: website/public/index.html:1136 msgctxt "page:index.html" msgid "" "Capture selected browser or process activity, then compare the results " "across runs." msgstr "記錄指定的瀏覽器或程序活動,再比較不同執行的結果。" -#: website/public/index.html:1136 +#: website/public/index.html:1140 msgctxt "page:index.html" msgid "Browser observation guide" msgstr "瀏覽器觀察指南" -#: website/public/index.html:1143 +#: website/public/index.html:1147 msgctxt "page:index.html" msgid "Any questions?" msgstr "有什麼問題嗎?" @@ -6374,7 +6382,7 @@ msgstr "有什麼問題嗎?" #. {ph3}: </a> #. {ph4}: <a href="https://github.com/morluto/rea/issues/new/choose" > #. {ph5}: </a > -#: website/public/index.html:1144 +#: website/public/index.html:1148 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -6384,12 +6392,12 @@ msgstr "" "{ph0}閱讀 FAQ{ph1}、{ph2}在 Discord 和我們聊聊{ph3},或{ph4}提交 GitHub issue{ph5}反饋 bug " "和功能需求。" -#: website/public/index.html:1157 website/public/index.html:1163 +#: website/public/index.html:1161 website/public/index.html:1167 msgctxt "page:index.html" msgid "Join the community" msgstr "加入社群" -#: website/public/index.html:1158 +#: website/public/index.html:1162 msgctxt "page:index.html" msgid "" "Share investigations and get help from other REA users on Discord. Follow " @@ -6408,64 +6416,64 @@ msgid "" " Follow clear guides and try interactive examples with REA." msgstr "和程式設計助手一起分析應用、二進位制檔案和瀏覽器行為。跟著清晰的指南,體驗 REA 的互動示例。" -#: website/public/index.html:256 +#: website/public/index.html:260 msgctxt "page:index.html" msgid "Copy REA installation prompt" msgstr "複製REA安裝提示" -#: website/public/index.html:278 +#: website/public/index.html:282 msgctxt "page:index.html" msgid "Copy setup command" msgstr "複製安裝命令" -#: website/public/index.html:330 +#: website/public/index.html:334 msgctxt "page:index.html" msgid "Follow the manual Calculator analysis" msgstr "按照手動計算器分析" -#: website/public/index.html:493 +#: website/public/index.html:497 msgctxt "page:index.html" msgid "Copy Calculator percentage question" msgstr "複製計算器百分比問題" -#: website/public/index.html:600 +#: website/public/index.html:604 msgctxt "page:index.html" msgid "" "Dinosaur mini-game. Use the Jump button or press Space while the game is " "focused." msgstr "小恐龍游戲。點選“跳躍”,或在遊戲獲得焦點後按空格鍵。" -#: website/public/index.html:661 +#: website/public/index.html:665 msgctxt "page:index.html" msgid "Copy dinosaur analysis prompt" msgstr "複製恐龍分析提示" -#: website/public/index.html:817 +#: website/public/index.html:821 msgctxt "page:index.html" msgid "Choose the calculation" msgstr "選擇計算" -#: website/public/index.html:897 +#: website/public/index.html:901 msgctxt "page:index.html" msgid "Copy Calculator analysis prompt" msgstr "複製計算器分析提示" -#: website/public/index.html:1059 +#: website/public/index.html:1063 msgctxt "page:index.html" msgid "Copy website project prompt" msgstr "複製網站專案提示" -#: website/public/index.html:1087 +#: website/public/index.html:1091 msgctxt "page:index.html" msgid "Copy game reconstruction prompt" msgstr "複製遊戲重建提示" -#: website/public/index.html:1187 +#: website/public/index.html:1191 msgctxt "page:index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/showcase/aegis/index.html:109 +#: website/public/showcase/aegis/index.html:104 msgctxt "page:showcase/aegis/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -6474,43 +6482,43 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:191 +#: website/public/showcase/aegis/index.html:195 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Android" msgstr "{ph0}首頁{ph1} / {ph2}案例展示{ph3} /安卓" -#: website/public/showcase/aegis/index.html:194 +#: website/public/showcase/aegis/index.html:198 msgctxt "page:showcase/aegis/index.html" msgid "Case study · Aegis Authenticator" msgstr "案例研究 · Aegis驗證器" #. {ph0}: <br /> -#: website/public/showcase/aegis/index.html:195 +#: website/public/showcase/aegis/index.html:199 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "How does an authenticator{ph0}generate a login code?" msgstr "身份驗證器如何{ph0}生成登入程式碼?" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/aegis/index.html:196 +#: website/public/showcase/aegis/index.html:200 msgctxt "page:showcase/aegis/index.html" msgid "" "A six-digit code changes every 30 seconds. Use REA to find the calculation " "in an Android APK, then rebuild it with a clock you can control." msgstr "六位驗證碼每 30 秒變化一次。用 REA 在 Android APK 中找出計算方法,再重建一個可調節時鐘的演示。" -#: website/public/showcase/aegis/index.html:201 +#: website/public/showcase/aegis/index.html:205 msgctxt "page:showcase/aegis/index.html" msgid "Aegis 3.4.3 · Android · Official release APK · 6.9 MB" msgstr "Aegis 3.4.3 · Android · 正式釋出 APK ·6.9MB" -#: website/public/showcase/aegis/index.html:204 +#: website/public/showcase/aegis/index.html:208 msgctxt "page:showcase/aegis/index.html" msgid "View Aegis on GitHub" msgstr "在GitHub上檢視Aegis" -#: website/public/showcase/aegis/index.html:210 +#: website/public/showcase/aegis/index.html:214 msgctxt "page:showcase/aegis/index.html" msgid "From an APK to a code you can reproduce" msgstr "從 APK 還原可復現的驗證碼" @@ -6522,7 +6530,7 @@ msgstr "從 APK 還原可復現的驗證碼" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:212 +#: website/public/showcase/aegis/index.html:216 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6540,7 +6548,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:221 +#: website/public/showcase/aegis/index.html:225 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6558,7 +6566,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/aegis/index.html:229 +#: website/public/showcase/aegis/index.html:233 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6568,14 +6576,14 @@ msgid "" msgstr "" "{ph0}03 · 重建並驗證{ph1}{ph2}調整時鐘,檢視驗證碼。{ph3}{ph4}新的瀏覽器演示覆現規則,再用公開對照用例檢查。{ph5}" -#: website/public/showcase/aegis/index.html:242 +#: website/public/showcase/aegis/index.html:246 msgctxt "page:showcase/aegis/index.html" msgid "In this case study" msgstr "在本個案研究中" #. {ph0}: <a href="#ask"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:244 +#: website/public/showcase/aegis/index.html:248 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Ask your agent{ph1}" @@ -6583,7 +6591,7 @@ msgstr "{ph0}問問你的程式設計助手{ph1}" #. {ph0}: <a href="#demo"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:245 +#: website/public/showcase/aegis/index.html:249 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Try the code generator{ph1}" @@ -6591,7 +6599,7 @@ msgstr "{ph0}試試程式碼生成器{ph1}" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:246 +#: website/public/showcase/aegis/index.html:250 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Find the code with REA{ph1}" @@ -6599,7 +6607,7 @@ msgstr "{ph0}用REA查詢程式碼 {ph1}" #. {ph0}: <a href="#calculation"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:247 +#: website/public/showcase/aegis/index.html:251 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Read the calculation{ph1}" @@ -6607,7 +6615,7 @@ msgstr "{ph0}閱讀計算{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:248 +#: website/public/showcase/aegis/index.html:252 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Check the reconstruction{ph1}" @@ -6615,20 +6623,20 @@ msgstr "{ph0}檢查重建{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:249 +#: website/public/showcase/aegis/index.html:253 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Inspect the APK yourself{ph1}" msgstr "{ph0}親自檢查APK{ph1}" -#: website/public/showcase/aegis/index.html:254 +#: website/public/showcase/aegis/index.html:258 msgctxt "page:showcase/aegis/index.html" msgid "Ask your agent" msgstr "問問你的程式設計助手" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:255 +#: website/public/showcase/aegis/index.html:259 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6644,14 +6652,14 @@ msgstr "該應用程式顯示更改的登入程式碼。 我們想找到 {ph0} #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/aegis/index.html:261 +#: website/public/showcase/aegis/index.html:265 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/showcase/aegis/index.html:265 -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:269 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy" msgstr "複製" @@ -6659,7 +6667,7 @@ msgstr "複製" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:285 +#: website/public/showcase/aegis/index.html:289 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6668,7 +6676,7 @@ msgid "" msgstr "" "這是用於下載的 APK 的示例 prompt,需要先配置 REA 的 Android 分析後端。{ph0}獲取 APK 和分析配置 ↓{ph1}" -#: website/public/showcase/aegis/index.html:293 +#: website/public/showcase/aegis/index.html:297 msgctxt "page:showcase/aegis/index.html" msgid "Try the code generator" msgstr "試試程式碼生成器" @@ -6676,7 +6684,7 @@ msgstr "試試程式碼生成器" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <mark class="prose-highlight"> #. {ph1}: </mark> -#: website/public/showcase/aegis/index.html:294 +#: website/public/showcase/aegis/index.html:298 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6685,33 +6693,33 @@ msgid "" "produce the same code." msgstr "應用把時間劃分為{ph0}每塊 30 秒{ph1},再結合時間塊編號和賬戶金鑰生成驗證碼。同樣的金鑰和時間塊,會得到同樣的驗證碼。" -#: website/public/showcase/aegis/index.html:301 +#: website/public/showcase/aegis/index.html:305 msgctxt "page:showcase/aegis/index.html" msgid "Move the clock across 60 seconds" msgstr "將時鐘移動60秒" -#: website/public/showcase/aegis/index.html:304 +#: website/public/showcase/aegis/index.html:308 msgctxt "page:showcase/aegis/index.html" msgid "Time" msgstr "時間" -#: website/public/showcase/aegis/index.html:306 +#: website/public/showcase/aegis/index.html:310 msgctxt "page:showcase/aegis/index.html" msgid "seconds" msgstr "秒數" -#: website/public/showcase/aegis/index.html:307 +#: website/public/showcase/aegis/index.html:311 msgctxt "page:showcase/aegis/index.html" msgid "Our adjustable example clock" msgstr "我們的可調節示例時鐘" -#: website/public/showcase/aegis/index.html:310 +#: website/public/showcase/aegis/index.html:314 msgctxt "page:showcase/aegis/index.html" msgid "30-second block" msgstr "30秒區塊" -#: website/public/showcase/aegis/index.html:312 -#: website/public/showcase/aegis/index.html:639 +#: website/public/showcase/aegis/index.html:316 +#: website/public/showcase/aegis/index.html:643 msgctxt "page:showcase/aegis/index.html" msgid "Block" msgstr "時間塊" @@ -6720,35 +6728,35 @@ msgstr "時間塊" #. {ph1}: <br /> #. {ph2}: <span data-aegis-window > #. {ph3}: </span > -#: website/public/showcase/aegis/index.html:313 +#: website/public/showcase/aegis/index.html:317 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}{ph1}{ph2}30–59 seconds{ph3}" msgstr "{ph0}{ph1}{ph2}30-59秒{ph3}" -#: website/public/showcase/aegis/index.html:321 +#: website/public/showcase/aegis/index.html:325 msgctxt "page:showcase/aegis/index.html" msgid "Generated code" msgstr "生成的驗證碼" -#: website/public/showcase/aegis/index.html:329 +#: website/public/showcase/aegis/index.html:333 msgctxt "page:showcase/aegis/index.html" msgid "Account key + block → six digits" msgstr "帳戶金鑰+區塊→六位數字" -#: website/public/showcase/aegis/index.html:335 +#: website/public/showcase/aegis/index.html:339 msgctxt "page:showcase/aegis/index.html" msgid "Example time, in seconds" msgstr "示例時間,以秒為單位" -#: website/public/showcase/aegis/index.html:350 -#: website/public/showcase/aegis/index.html:650 +#: website/public/showcase/aegis/index.html:354 +#: website/public/showcase/aegis/index.html:654 msgctxt "page:showcase/aegis/index.html" msgid "59 seconds" msgstr "59秒" -#: website/public/showcase/aegis/index.html:357 -#: website/public/showcase/aegis/index.html:655 +#: website/public/showcase/aegis/index.html:361 +#: website/public/showcase/aegis/index.html:659 msgctxt "page:showcase/aegis/index.html" msgid "60 seconds" msgstr "60秒" @@ -6757,7 +6765,7 @@ msgstr "60秒" #. {ph1}: </strong> #. {ph2}: <strong> #. {ph3}: </strong> -#: website/public/showcase/aegis/index.html:366 +#: website/public/showcase/aegis/index.html:370 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6767,7 +6775,7 @@ msgstr "在59秒: {ph0}287082.{ph1} 在60秒: {ph2}359152.{ph3} 在一個塊內 #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:373 +#: website/public/showcase/aegis/index.html:377 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6775,26 +6783,26 @@ msgid "" "the calculation recovered from the APK." msgstr "金鑰是固定的,公開的 {ph0}RFC6238測試資料{ph1}. 該演示實現了從APK恢復的計算。" -#: website/public/showcase/aegis/index.html:380 +#: website/public/showcase/aegis/index.html:384 msgctxt "page:showcase/aegis/index.html" msgid "" "The diagram shows the result at 59 seconds. Enable JavaScript to change the " "clock." msgstr "該圖顯示了59秒時的結果。 啟用JavaScript以更改時鐘。" -#: website/public/showcase/aegis/index.html:389 +#: website/public/showcase/aegis/index.html:393 msgctxt "page:showcase/aegis/index.html" msgid "Find the code with REA" msgstr "用REA查詢程式碼" -#: website/public/showcase/aegis/index.html:392 +#: website/public/showcase/aegis/index.html:396 msgctxt "page:showcase/aegis/index.html" msgid "Narrow the APK to three classes" msgstr "將APK縮小到三個類" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>TotpInfo</code> -#: website/public/showcase/aegis/index.html:417 +#: website/public/showcase/aegis/index.html:421 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6802,7 +6810,7 @@ msgid "" "and imported accounts. TOTP means a time-based one-time password." msgstr "{ph0} 是計算邏輯的候選方法;另外兩個涉及進度條和匯入的賬戶。TOTP 指基於時間的一次性密碼。" -#: website/public/showcase/aegis/index.html:424 +#: website/public/showcase/aegis/index.html:428 msgctxt "page:showcase/aegis/index.html" msgid "Connect the generator to the app's display" msgstr "將生成器連線到應用程式的顯示器" @@ -6810,7 +6818,7 @@ msgstr "將生成器連線到應用程式的顯示器" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>EntryHolder.getOtp</code> #. {ph1}: <code>TotpInfo.getOtp(timestamp)</code> -#: website/public/showcase/aegis/index.html:452 +#: website/public/showcase/aegis/index.html:456 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6819,7 +6827,7 @@ msgid "" msgstr "REA 找到接受時間戳的方法過載,並定位基礎方法的呼叫方。繼續檢查 {ph0},就能看到顯示邏輯呼叫了 {ph1}。" #. {ph0}: <code>com.beemdevelopment.aegis</code> -#: website/public/showcase/aegis/index.html:460 +#: website/public/showcase/aegis/index.html:464 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6827,7 +6835,7 @@ msgid "" "{ph0} prefix." msgstr "請求顯示縮短的輸入路徑。 結果類名省略常用 {ph0} 字首。" -#: website/public/showcase/aegis/index.html:467 +#: website/public/showcase/aegis/index.html:471 msgctxt "page:showcase/aegis/index.html" msgid "Read the calculation" msgstr "閱讀計算" @@ -6835,7 +6843,7 @@ msgstr "閱讀計算" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:468 +#: website/public/showcase/aegis/index.html:472 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6847,7 +6855,7 @@ msgstr "" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:483 +#: website/public/showcase/aegis/index.html:487 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}01{ph1} Time block" @@ -6855,7 +6863,7 @@ msgstr "{ph0}01{ph1} 時間塊" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:491 +#: website/public/showcase/aegis/index.html:495 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}02{ph1} Key + block" @@ -6863,7 +6871,7 @@ msgstr "{ph0}02{ph1} 鍵+塊" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/aegis/index.html:499 +#: website/public/showcase/aegis/index.html:503 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}03{ph1} Six digits" @@ -6871,7 +6879,7 @@ msgstr "{ph0}03{ph1} 六位數" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:558 +#: website/public/showcase/aegis/index.html:562 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6882,7 +6890,7 @@ msgstr "{ph0}時間選擇塊。{ph1} 秒30到59都給塊1。 在60秒時,塊 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:564 +#: website/public/showcase/aegis/index.html:568 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6894,7 +6902,7 @@ msgstr "{ph0}金鑰也會影響結果。{ph1} 生成函式把賬戶金鑰和時 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:571 +#: website/public/showcase/aegis/index.html:575 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6907,7 +6915,7 @@ msgstr "{ph0}保留六位數字。{ph1} 取除以 1,000,000 的餘數,位數 #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:578 +#: website/public/showcase/aegis/index.html:582 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6915,7 +6923,7 @@ msgid "" " right panel is an explanatory summary. {ph0}Aegis code is GPL-3.0.{ph1}" msgstr "這些節選來自多個檢查過的方法,為便於顯示增加了換行。右側是解釋性摘要。{ph0}Aegis 原始碼採用 GPL-3.0 許可。{ph1}" -#: website/public/showcase/aegis/index.html:587 +#: website/public/showcase/aegis/index.html:591 msgctxt "page:showcase/aegis/index.html" msgid "Inside the generator" msgstr "驗證碼生成函式內部" @@ -6925,7 +6933,7 @@ msgstr "驗證碼生成函式內部" #. {ph1}: <code>kotlin.ExceptionsKt</code> #. {ph2}: <code>TotpInfo</code> #. {ph3}: <code>HOTP</code> -#: website/public/showcase/aegis/index.html:588 +#: website/public/showcase/aegis/index.html:592 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6935,7 +6943,7 @@ msgstr "" "釋出的 APK 將 {ph0} 放在 {ph1} 中。REA 從 {ph2} 追蹤呼叫,並返回這個函式體;原始原始碼把輔助函式命名為 {ph3}。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/aegis/index.html:610 +#: website/public/showcase/aegis/index.html:614 msgctxt "page:showcase/aegis/index.html" msgid "" "The last hash byte selects a position. Four bytes at that position provide a" @@ -6950,13 +6958,13 @@ msgstr "" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/crypto/otp/HOTP.java" #. > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:617 +#: website/public/showcase/aegis/index.html:621 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}Compare with the matching release source{ph1}." msgstr "{ph0}與匹配的釋出源進行比較{ph1}." -#: website/public/showcase/aegis/index.html:627 +#: website/public/showcase/aegis/index.html:631 msgctxt "page:showcase/aegis/index.html" msgid "Check the reconstruction" msgstr "檢查重建" @@ -6964,7 +6972,7 @@ msgstr "檢查重建" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/aegis/index.html:628 +#: website/public/showcase/aegis/index.html:632 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -6975,22 +6983,22 @@ msgstr "" "我們將選定的 REA 返回的 Java 方法放進小型測試程式。它們的輸出與獨立重建的實現一致,共驗證 {ph0}133 " "個測試用例{ph1},包括時間塊邊界和以零開頭的驗證碼。" -#: website/public/showcase/aegis/index.html:638 +#: website/public/showcase/aegis/index.html:642 msgctxt "page:showcase/aegis/index.html" msgid "Example time" msgstr "示例時間" -#: website/public/showcase/aegis/index.html:640 +#: website/public/showcase/aegis/index.html:644 msgctxt "page:showcase/aegis/index.html" msgid "Six-digit code" msgstr "六位驗證碼" -#: website/public/showcase/aegis/index.html:645 +#: website/public/showcase/aegis/index.html:649 msgctxt "page:showcase/aegis/index.html" msgid "30 seconds" msgstr "30秒" -#: website/public/showcase/aegis/index.html:660 +#: website/public/showcase/aegis/index.html:664 msgctxt "page:showcase/aegis/index.html" msgid "1,111,111,109 seconds" msgstr "1,111,111,109秒" @@ -6998,7 +7006,7 @@ msgstr "1,111,111,109秒" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="https://www.rfc-editor.org/rfc/rfc6238.html#appendix-B" > #. {ph1}: </a > -#: website/public/showcase/aegis/index.html:667 +#: website/public/showcase/aegis/index.html:671 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7006,31 +7014,31 @@ msgid "" "{ph0}RFC 6238{ph1}. Check the browser implementation against them:" msgstr "生成函式還符合 {ph0}RFC 6238{ph1} 中釋出的六個 SHA-1 對照用例。可以用這些用例檢查瀏覽器實現:" -#: website/public/showcase/aegis/index.html:675 +#: website/public/showcase/aegis/index.html:679 msgctxt "page:showcase/aegis/index.html" msgid "Run reference checks" msgstr "執行對照檢查" -#: website/public/showcase/aegis/index.html:682 +#: website/public/showcase/aegis/index.html:686 msgctxt "page:showcase/aegis/index.html" msgid "Read the demo's calculation" msgstr "閱讀演示的計算" -#: website/public/showcase/aegis/index.html:686 +#: website/public/showcase/aegis/index.html:690 msgctxt "page:showcase/aegis/index.html" msgid "" "The reference cases use eight digits. The check also verifies their six-" "digit results." msgstr "參考案例使用八位數字。 檢查也驗證他們的六位數的結果。" -#: website/public/showcase/aegis/index.html:695 +#: website/public/showcase/aegis/index.html:699 msgctxt "page:showcase/aegis/index.html" msgid "" "Verification runs extracted Java methods and the new demo. The Android APK " "was inspected statically." msgstr "驗證執行提取的Java方法和新的演示。 對Android APK進行了靜態檢查。" -#: website/public/showcase/aegis/index.html:702 +#: website/public/showcase/aegis/index.html:706 msgctxt "page:showcase/aegis/index.html" msgid "Inspect the APK yourself" msgstr "親自檢查APK" @@ -7038,7 +7046,7 @@ msgstr "親自檢查APK" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="../../get-started/"> #. {ph1}: </a> -#: website/public/showcase/aegis/index.html:703 +#: website/public/showcase/aegis/index.html:707 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7050,7 +7058,7 @@ msgstr "" #. {ph0}: <code>JAVA_HOME</code> #. {ph1}: <code>PATH</code> -#: website/public/showcase/aegis/index.html:708 +#: website/public/showcase/aegis/index.html:712 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7058,19 +7066,19 @@ msgid "" "{ph1}. This case used JDK 21." msgstr "Android分析需要完整的JDK17或更高版本。 選擇它與 {ph0} 或 {ph1}. 本案例使用了JDK21。" -#: website/public/showcase/aegis/index.html:724 +#: website/public/showcase/aegis/index.html:728 msgctxt "page:showcase/aegis/index.html" msgid "Point REA at the provider file and inspect the APK:" msgstr "讓 REA 使用分析後端配置檔案,再檢查 APK:" -#: website/public/showcase/aegis/index.html:727 +#: website/public/showcase/aegis/index.html:731 msgctxt "page:showcase/aegis/index.html" msgid "macOS / Linux" msgstr "macOS/Linux" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>REA_JADX_MCP_JAR</code> -#: website/public/showcase/aegis/index.html:741 +#: website/public/showcase/aegis/index.html:745 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7080,7 +7088,7 @@ msgstr "助手可以透過 REA CLI 繼續使用上方的 prompt。如果使用 M #. {ph0}: <strong > #. {ph1}: </strong > -#: website/public/showcase/aegis/index.html:746 +#: website/public/showcase/aegis/index.html:750 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7088,7 +7096,7 @@ msgid "" "different time interval?{ph1}" msgstr "下一個問題: {ph0}當帳戶使用八位數字或不同的時間間隔時會發生什麼?{ph1}" -#: website/public/showcase/aegis/index.html:756 +#: website/public/showcase/aegis/index.html:760 msgctxt "page:showcase/aegis/index.html" msgid "Sources" msgstr "資料來源" @@ -7104,7 +7112,7 @@ msgstr "資料來源" #. href="https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/LICENSE" #. > #. {ph5}: </a > -#: website/public/showcase/aegis/index.html:758 +#: website/public/showcase/aegis/index.html:762 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -7116,14 +7124,14 @@ msgstr "{ph0}官方Aegis3.4.3釋出{ph1} · {ph2}匹配源提交{ph3} · {ph4}GP #. {ph1}: </a > #. {ph2}: <a href="test-vectors.json"> #. {ph3}: </a> -#: website/public/showcase/aegis/index.html:774 +#: website/public/showcase/aegis/index.html:778 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "{ph0}RFC 6238 reference cases{ph1} · {ph2}Demo test data{ph3}" msgstr "{ph0}RFC6238參考案例{ph1} · {ph2}演示測試資料{ph3}" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/aegis/index.html:781 +#: website/public/showcase/aegis/index.html:785 msgctxt "page:showcase/aegis/index.html" msgid "" "Inspected with REA 6.1.0 on 9 October 2026. Decompiled excerpts are credited" @@ -7144,37 +7152,37 @@ msgid "" "calculation and try a reconstruction with an adjustable clock." msgstr "用 REA 檢查 Aegis Android APK,還原六位登入驗證碼的計算,再試玩可調時鐘的重建演示。" -#: website/public/showcase/aegis/index.html:241 +#: website/public/showcase/aegis/index.html:245 msgctxt "page:showcase/aegis/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/showcase/aegis/index.html:252 +#: website/public/showcase/aegis/index.html:256 msgctxt "page:showcase/aegis/index.html" msgid "Aegis APK case study" msgstr "Aegis APK案例研究" -#: website/public/showcase/aegis/index.html:265 +#: website/public/showcase/aegis/index.html:269 msgctxt "page:showcase/aegis/index.html" msgid "Copy Aegis example prompt" msgstr "複製Aegis示例提示" -#: website/public/showcase/aegis/index.html:478 +#: website/public/showcase/aegis/index.html:482 msgctxt "page:showcase/aegis/index.html" msgid "Follow the login-code calculation" msgstr "按照登入程式碼計算" -#: website/public/showcase/aegis/index.html:728 +#: website/public/showcase/aegis/index.html:732 msgctxt "page:showcase/aegis/index.html" msgid "Copy APK inspection command" msgstr "複製APK檢查命令" -#: website/public/showcase/aegis/index.html:804 +#: website/public/showcase/aegis/index.html:808 msgctxt "page:showcase/aegis/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/showcase/ctf/index.html:108 +#: website/public/showcase/ctf/index.html:103 msgctxt "page:showcase/ctf/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -7183,26 +7191,26 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/ctf/index.html:190 +#: website/public/showcase/ctf/index.html:194 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / CTF" msgstr "{ph0}首頁{ph1} / {ph2}案例展示{ph3} /CTF" -#: website/public/showcase/ctf/index.html:193 +#: website/public/showcase/ctf/index.html:197 msgctxt "page:showcase/ctf/index.html" msgid "Case study · DownUnderCTF 2023" msgstr "案例研究·Downunderctf2023" #. {ph0}: <br /> -#: website/public/showcase/ctf/index.html:194 +#: website/public/showcase/ctf/index.html:198 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "Find the flag in{ph0}a CTF binary." msgstr "找到國旗{ph0}一個CTF二進位制檔案。" #. {ph0}: <code>Correct!</code> -#: website/public/showcase/ctf/index.html:195 +#: website/public/showcase/ctf/index.html:199 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7210,17 +7218,17 @@ msgid "" "find an input that makes the original program print {ph0}." msgstr "使用方法 REA 要檢查一個小的flag 檢查器,將其規則轉換為方程,並找到一個使原始程式列印的輸入 {ph0}." -#: website/public/showcase/ctf/index.html:200 +#: website/public/showcase/ctf/index.html:204 msgctxt "page:showcase/ctf/index.html" msgid "masked squares flag checker · Easy · Linux x86-64" msgstr "蒙面方格旗檢查器 · 容易·Linuxx86-64" -#: website/public/showcase/ctf/index.html:203 +#: website/public/showcase/ctf/index.html:207 msgctxt "page:showcase/ctf/index.html" msgid "View the original challenge" msgstr "檢視原始挑戰" -#: website/public/showcase/ctf/index.html:211 +#: website/public/showcase/ctf/index.html:215 msgctxt "page:showcase/ctf/index.html" msgid "From a binary to a checked answer" msgstr "從二進位制到檢查答案" @@ -7231,7 +7239,7 @@ msgstr "從二進位制到檢查答案" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:213 +#: website/public/showcase/ctf/index.html:217 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7247,7 +7255,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:221 +#: website/public/showcase/ctf/index.html:225 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7264,7 +7272,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/ctf/index.html:229 +#: website/public/showcase/ctf/index.html:233 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7275,20 +7283,20 @@ msgstr "" "{ph0}03 · 解決並執行{ph1}{ph2}恢復旗→正確!{ph3}{ph4}一個Python指令碼解決方程. REA " "捕獲接受結果的原始程式。{ph5}" -#: website/public/showcase/ctf/index.html:238 +#: website/public/showcase/ctf/index.html:242 msgctxt "page:showcase/ctf/index.html" msgid "" "The challenge is by joseph, published in DownUnderCTF's official repository." msgstr "挑戰是由約瑟夫,發表在DownUnderCTF的官方程式碼儲存庫。" -#: website/public/showcase/ctf/index.html:246 +#: website/public/showcase/ctf/index.html:250 msgctxt "page:showcase/ctf/index.html" msgid "In this case study" msgstr "在本個案研究中" #. {ph0}: <a href="#find"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:248 +#: website/public/showcase/ctf/index.html:252 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Find the checking code{ph1}" @@ -7296,7 +7304,7 @@ msgstr "{ph0}查詢檢查程式碼{ph1}" #. {ph0}: <a href="#mask"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:249 +#: website/public/showcase/ctf/index.html:253 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Read one mask{ph1}" @@ -7304,7 +7312,7 @@ msgstr "{ph0}讀一個面具{ph1}" #. {ph0}: <a href="#code"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:250 +#: website/public/showcase/ctf/index.html:254 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Assembly to readable code{ph1}" @@ -7312,7 +7320,7 @@ msgstr "{ph0}彙編到可讀程式碼{ph1}" #. {ph0}: <a href="#solve"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:251 +#: website/public/showcase/ctf/index.html:255 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Solve the equations{ph1}" @@ -7320,7 +7328,7 @@ msgstr "{ph0}解方程{ph1}" #. {ph0}: <a href="#verify"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:252 +#: website/public/showcase/ctf/index.html:256 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Check the answer{ph1}" @@ -7328,20 +7336,20 @@ msgstr "{ph0}檢查答案{ph1}" #. {ph0}: <a href="#try"> #. {ph1}: </a> -#: website/public/showcase/ctf/index.html:253 +#: website/public/showcase/ctf/index.html:257 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}Try it yourself{ph1}" msgstr "{ph0}你自己試試吧{ph1}" -#: website/public/showcase/ctf/index.html:258 +#: website/public/showcase/ctf/index.html:262 msgctxt "page:showcase/ctf/index.html" msgid "Find the checking code" msgstr "查詢檢查程式碼" #. {ph0}: <code>Correct!</code> #. {ph1}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:259 +#: website/public/showcase/ctf/index.html:263 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7357,17 +7365,17 @@ msgstr "講義是一個15KB可執行檔案。 它要求一面旗幟,然後列 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/ctf/index.html:266 +#: website/public/showcase/ctf/index.html:270 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/showcase/ctf/index.html:271 -#: website/public/showcase/ctf/index.html:490 -#: website/public/showcase/ctf/index.html:514 -#: website/public/showcase/ctf/index.html:584 -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:275 +#: website/public/showcase/ctf/index.html:494 +#: website/public/showcase/ctf/index.html:518 +#: website/public/showcase/ctf/index.html:588 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy" msgstr "複製" @@ -7378,7 +7386,7 @@ msgstr "複製" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/ctf/index.html:280 +#: website/public/showcase/ctf/index.html:284 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7389,33 +7397,33 @@ msgstr "" "{ph0}›{ph1}{ph2}使用REA分析ms_flag_checker並找到標誌。 " "解釋檢查是如何工作的,然後用原始程式驗證答案。{ph3}{ph4}{ph5}" -#: website/public/showcase/ctf/index.html:289 +#: website/public/showcase/ctf/index.html:293 msgctxt "page:showcase/ctf/index.html" msgid "" "An example prompt, with the downloaded challenge available locally and a " "native analysis provider connected." msgstr "一個示例提示,下載的質詢在本地可用,並連線了原生分析提供程式。" -#: website/public/showcase/ctf/index.html:295 +#: website/public/showcase/ctf/index.html:299 msgctxt "page:showcase/ctf/index.html" msgid "Follow the input prompt to its function" msgstr "按照輸入提示到其函式" -#: website/public/showcase/ctf/index.html:324 +#: website/public/showcase/ctf/index.html:328 msgctxt "page:showcase/ctf/index.html" msgid "" "The reference gives the agent a place to investigate, even though the " "executable's original function names have been removed." msgstr "引用為程式設計助手提供了一個調查的地方,即使可執行檔案的原始函式名已被刪除。" -#: website/public/showcase/ctf/index.html:331 +#: website/public/showcase/ctf/index.html:335 msgctxt "page:showcase/ctf/index.html" msgid "Read the checker and its two helpers" msgstr "閱讀檢查器和它的兩個助手" #. {ph0}: <code>0x18</code> #. {ph1}: <code>0x270</code> -#: website/public/showcase/ctf/index.html:359 +#: website/public/showcase/ctf/index.html:363 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7426,19 +7434,19 @@ msgstr "" "第一個迴圈複製36個字元程式碼。 檢查迴圈解碼掩碼,對所選程式碼求和,並將結果與儲存的數字進行比較。 其 {ph0}-位元組跨步 {ph1} " "位元組給出26個掩碼。" -#: website/public/showcase/ctf/index.html:367 +#: website/public/showcase/ctf/index.html:371 msgctxt "page:showcase/ctf/index.html" msgid "" "These are selected results from a fresh REA analysis. The local target path " "is shortened for display; addresses refer to REA's imported image." msgstr "這些是來自新鮮REA分析的選擇結果。 本地目標路徑縮短顯示;地址參考REA的匯入影象。" -#: website/public/showcase/ctf/index.html:375 +#: website/public/showcase/ctf/index.html:379 msgctxt "page:showcase/ctf/index.html" msgid "One check reveals one character" msgstr "一張檢查顯示一個字元" -#: website/public/showcase/ctf/index.html:376 +#: website/public/showcase/ctf/index.html:380 msgctxt "page:showcase/ctf/index.html" msgid "" "The checker arranges the input in a 6×6 grid. A mask chooses which cells " @@ -7448,13 +7456,13 @@ msgstr "檢查器將輸入排列在6×6網格中。 掩碼選擇哪些單元格 #. {ph0}: <a href="../../assets/figures/ctf-mask-equation.svg" > #. {ph1}: </a > -#: website/public/showcase/ctf/index.html:396 +#: website/public/showcase/ctf/index.html:400 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "The seventh check selects just one position. {ph0}Open figure{ph1}." msgstr "第七個檢查只選擇一個位置。 {ph0}開啟圖{ph1}." -#: website/public/showcase/ctf/index.html:403 +#: website/public/showcase/ctf/index.html:407 msgctxt "page:showcase/ctf/index.html" msgid "Read the mask and its target from the binary" msgstr "從二進位制檔案中讀取掩碼及其目標" @@ -7463,7 +7471,7 @@ msgstr "從二進位制檔案中讀取掩碼及其目標" #. {ph1}: <code>eb</code> #. {ph2}: <code>code[21] = 55</code> #. {ph3}: <code>7</code> -#: website/public/showcase/ctf/index.html:425 +#: website/public/showcase/ctf/index.html:429 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7474,12 +7482,12 @@ msgstr "" "指示 {ph0} 將掩碼位元組讀取為有符號值。 這就是為什麼 {ph1} 表示-21. 目標是一個小端整數。 這些位元組一起告訴程式設計助手 " "{ph2},所以該字元是 {ph3}." -#: website/public/showcase/ctf/index.html:434 +#: website/public/showcase/ctf/index.html:438 msgctxt "page:showcase/ctf/index.html" msgid "From instructions to a readable check" msgstr "從指令到可讀的檢查" -#: website/public/showcase/ctf/index.html:435 +#: website/public/showcase/ctf/index.html:439 msgctxt "page:showcase/ctf/index.html" msgid "" "Select a step to connect the summing helper and its caller to the same rule " @@ -7488,7 +7496,7 @@ msgstr "選擇一個步驟將求和幫助程式及其呼叫者連線到C中的 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:445 +#: website/public/showcase/ctf/index.html:449 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01{ph1} Start" @@ -7496,7 +7504,7 @@ msgstr "{ph0}01{ph1} 開始" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:453 +#: website/public/showcase/ctf/index.html:457 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}02{ph1} Select" @@ -7504,7 +7512,7 @@ msgstr "{ph0}02{ph1} 選擇" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:461 +#: website/public/showcase/ctf/index.html:465 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}03{ph1} Add" @@ -7512,7 +7520,7 @@ msgstr "{ph0}03{ph1} 新增" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:469 +#: website/public/showcase/ctf/index.html:473 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}04{ph1} Advance" @@ -7520,18 +7528,18 @@ msgstr "{ph0}04{ph1} 前進,前進" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/ctf/index.html:477 +#: website/public/showcase/ctf/index.html:481 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}05{ph1} Compare" msgstr "{ph0}05{ph1} 比較一下" -#: website/public/showcase/ctf/index.html:489 +#: website/public/showcase/ctf/index.html:493 msgctxt "page:showcase/ctf/index.html" msgid "REA · selected original instructions" msgstr "REA · 選定的原始說明" -#: website/public/showcase/ctf/index.html:513 +#: website/public/showcase/ctf/index.html:517 msgctxt "page:showcase/ctf/index.html" msgid "Readable C · one-check summary" msgstr "可讀的C · 一檢查摘要" @@ -7539,7 +7547,7 @@ msgstr "可讀的C · 一檢查摘要" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ECX</code> -#: website/public/showcase/ctf/index.html:542 +#: website/public/showcase/ctf/index.html:546 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "{ph0}01 · Start at zero.{ph1} {ph2} holds the running sum." @@ -7547,7 +7555,7 @@ msgstr "{ph0}01 · 從零開始。{ph1} {ph2} 持有執行總和。" #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:546 +#: website/public/showcase/ctf/index.html:550 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7557,7 +7565,7 @@ msgstr "{ph0}02 · 檢查掩碼單元格。{ph1} 零值跳過字元;非零值包 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:550 +#: website/public/showcase/ctf/index.html:554 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7567,7 +7575,7 @@ msgstr "{ph0}03 · 新增字元程式碼。{ph1} 輸入在相同偏移量處的 #. {ph0}: <strong> #. {ph1}: </strong> -#: website/public/showcase/ctf/index.html:554 +#: website/public/showcase/ctf/index.html:558 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7579,7 +7587,7 @@ msgstr "{ph0}04 · 移動到下一個單元格。{ph1} 原始迴圈每個整數 #. {ph1}: </strong> #. {ph2}: <code>EAX</code> #. {ph3}: <code>Incorrect!</code> -#: website/public/showcase/ctf/index.html:559 +#: website/public/showcase/ctf/index.html:563 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7587,19 +7595,19 @@ msgid "" "in {ph2}. A mismatch jumps to {ph3}." msgstr "{ph0}05 · 與儲存的目標進行比較。{ph1} 呼叫方在 {ph2}. 不匹配跳轉到 {ph3}." -#: website/public/showcase/ctf/index.html:566 +#: website/public/showcase/ctf/index.html:570 msgctxt "page:showcase/ctf/index.html" msgid "" "The instructions come from the summing helper and its caller. The C is an " "explanatory summary with descriptive names and a flattened 36-cell loop." msgstr "指令來自求和助手及其呼叫者。 C是一個具有描述性名稱和扁平36個單元格迴圈的解釋性摘要。" -#: website/public/showcase/ctf/index.html:574 +#: website/public/showcase/ctf/index.html:578 msgctxt "page:showcase/ctf/index.html" msgid "Solve the 26 equations" msgstr "求解26個方程" -#: website/public/showcase/ctf/index.html:575 +#: website/public/showcase/ctf/index.html:579 msgctxt "page:showcase/ctf/index.html" msgid "" "Most masks select several cells. For example, the first check adds 16 " @@ -7608,13 +7616,13 @@ msgid "" msgstr "" "大多數掩碼選擇幾個單元格。 例如,第一次檢查新增了16個字元程式碼,總共需要1441個。 重疊的選擇給出了一個小的Python指令碼可以一起求解的方程。" -#: website/public/showcase/ctf/index.html:583 +#: website/public/showcase/ctf/index.html:587 msgctxt "page:showcase/ctf/index.html" msgid "Python · solver excerpt" msgstr "Python · 求解器摘錄" #. {ph0}: <code>DUCTF{…}</code> -#: website/public/showcase/ctf/index.html:611 +#: website/public/showcase/ctf/index.html:615 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7626,19 +7634,19 @@ msgstr "" "Z3是一個求解器,可以找到滿足這些方程的值。 此摘錄使用提取的檢查,並假定 {ph0} 用字母,數字,下劃線和大括號標記。 " "完整的下載包括所有26個面具和目標。" -#: website/public/showcase/ctf/index.html:617 +#: website/public/showcase/ctf/index.html:621 msgctxt "page:showcase/ctf/index.html" msgid "Download the complete solver" msgstr "下載完整的求解器" -#: website/public/showcase/ctf/index.html:623 +#: website/public/showcase/ctf/index.html:627 msgctxt "page:showcase/ctf/index.html" msgid "Check the answer with the original program" msgstr "用原始程式檢查答案" #. {ph0}: <code>z</code> #. {ph1}: <code>y</code> -#: website/public/showcase/ctf/index.html:624 +#: website/public/showcase/ctf/index.html:628 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7648,59 +7656,59 @@ msgid "" msgstr "" "REA的程序捕獲記錄接受已解決標誌的原始可執行檔案。 更改一個選定的字元 {ph0} 到 {ph1} 使第一和1440而不是1441,並且程式拒絕它。" -#: website/public/showcase/ctf/index.html:634 +#: website/public/showcase/ctf/index.html:638 msgctxt "page:showcase/ctf/index.html" msgid "Input" msgstr "輸入" -#: website/public/showcase/ctf/index.html:635 +#: website/public/showcase/ctf/index.html:639 msgctxt "page:showcase/ctf/index.html" msgid "Observed output" msgstr "觀察到的輸出" -#: website/public/showcase/ctf/index.html:636 +#: website/public/showcase/ctf/index.html:640 msgctxt "page:showcase/ctf/index.html" msgid "Exit code" msgstr "退出程式碼" -#: website/public/showcase/ctf/index.html:641 +#: website/public/showcase/ctf/index.html:645 msgctxt "page:showcase/ctf/index.html" msgid "Solver's flag" msgstr "解算者之旗" -#: website/public/showcase/ctf/index.html:646 +#: website/public/showcase/ctf/index.html:650 msgctxt "page:showcase/ctf/index.html" msgid "One character changed" msgstr "一個角色改變了" -#: website/public/showcase/ctf/index.html:654 +#: website/public/showcase/ctf/index.html:658 msgctxt "page:showcase/ctf/index.html" msgid "Show the recovered flag and captured output" msgstr "顯示恢復的標誌和捕獲的輸出" -#: website/public/showcase/ctf/index.html:657 +#: website/public/showcase/ctf/index.html:661 msgctxt "page:showcase/ctf/index.html" msgid "REA · original program output" msgstr "REA · 原始程式輸出" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy flag" msgstr "複製標誌" -#: website/public/showcase/ctf/index.html:670 +#: website/public/showcase/ctf/index.html:674 msgctxt "page:showcase/ctf/index.html" msgid "" "The recovered value also matches the flag in the organizers' published " "challenge metadata, checked after solving the binary." msgstr "恢復的值還與組織者釋出的挑戰後設資料中的標誌相匹配,在解決二進位制後檢查。" -#: website/public/showcase/ctf/index.html:676 +#: website/public/showcase/ctf/index.html:680 msgctxt "page:showcase/ctf/index.html" msgid "Source, target identity and analysis details" msgstr "來源、目標身份和分析詳細資訊" -#: website/public/showcase/ctf/index.html:677 +#: website/public/showcase/ctf/index.html:681 msgctxt "page:showcase/ctf/index.html" msgid "" "Fresh analysis and two process captures on 8 October 2026, using REA 4.1.0 " @@ -7710,7 +7718,7 @@ msgstr "" "在2026年10月8日使用REA4.1.0和Ghidra12.1.4在Linux x64上進行新的分析和兩個過程捕獲。 " "二進位制檔案是一個剝離的x86-64ELF,15,248位元組。" -#: website/public/showcase/ctf/index.html:688 +#: website/public/showcase/ctf/index.html:692 msgctxt "page:showcase/ctf/index.html" msgid "" "The string references, functions and constants were inspected before reading" @@ -7730,7 +7738,7 @@ msgstr "在閱讀組織者的原始碼或解決方案之前,對字串引用, #. href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked- #. squares.md" > #. {ph5}: </a > -#: website/public/showcase/ctf/index.html:693 +#: website/public/showcase/ctf/index.html:697 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7738,25 +7746,25 @@ msgid "" "flag{ph3} · {ph4}REA evidence notes{ph5}" msgstr "{ph0}與主辦方來源比較{ph1} · {ph2}挑戰後設資料和標誌{ph3} · {ph4} REA證據說明{ph5}" -#: website/public/showcase/ctf/index.html:713 +#: website/public/showcase/ctf/index.html:717 msgctxt "page:showcase/ctf/index.html" msgid "Try it yourself" msgstr "你自己試試吧" -#: website/public/showcase/ctf/index.html:714 +#: website/public/showcase/ctf/index.html:718 msgctxt "page:showcase/ctf/index.html" msgid "" "Download the original challenge and the solver into one folder. Use the " "prompt above to investigate with your agent, or run the included script." msgstr "將原始挑戰和求解器下載到一個資料夾中。 使用上面的提示與你的程式設計助手進行調查,或執行包含的指令碼。" -#: website/public/showcase/ctf/index.html:730 +#: website/public/showcase/ctf/index.html:734 msgctxt "page:showcase/ctf/index.html" msgid "Terminal · solve and run" msgstr "終端 · 解決和執行" #. {ph0}: <code>z3-solver</code> -#: website/public/showcase/ctf/index.html:747 +#: website/public/showcase/ctf/index.html:751 #, python-brace-format msgctxt "page:showcase/ctf/index.html" msgid "" @@ -7765,7 +7773,7 @@ msgid "" "x86-64." msgstr "指令碼列印候選標誌;將其貼上到程式的提示符處。 解決需要Python和 {ph0}. 執行原始可執行檔案需要Linux x86-64。" -#: website/public/showcase/ctf/index.html:752 +#: website/public/showcase/ctf/index.html:756 msgctxt "page:showcase/ctf/index.html" msgid "Set up REA with your coding agent" msgstr "設定REA與你的程式設計助手" @@ -7783,27 +7791,27 @@ msgid "" "original program." msgstr "使用REA來解決DownUnderCTF的掩碼方塊flag 檢查器。 找到檢查函式,提取掩碼並將恢復的標誌與原始程式進行比較。" -#: website/public/showcase/ctf/index.html:245 +#: website/public/showcase/ctf/index.html:249 msgctxt "page:showcase/ctf/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/showcase/ctf/index.html:256 +#: website/public/showcase/ctf/index.html:260 msgctxt "page:showcase/ctf/index.html" msgid "CTF flag-checker case study" msgstr "CTFflag 檢查個案研究" -#: website/public/showcase/ctf/index.html:271 +#: website/public/showcase/ctf/index.html:275 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF example prompt" msgstr "複製CTF示例提示" -#: website/public/showcase/ctf/index.html:382 +#: website/public/showcase/ctf/index.html:386 msgctxt "page:showcase/ctf/index.html" msgid "CTF mask equation; scroll horizontally on smaller screens" msgstr "CTF掩碼方程;在較小的螢幕上水平滾動" -#: website/public/showcase/ctf/index.html:388 +#: website/public/showcase/ctf/index.html:392 msgctxt "page:showcase/ctf/index.html" msgid "" "The seventh mask skips 21 cells, selects position 21, then skips 14. Only " @@ -7811,42 +7819,42 @@ msgid "" "means the character is 7." msgstr "第七個掩碼跳過21個單元格,選擇位置21,然後跳過14。 只有該單元格貢獻總和。 它所需的字元程式碼是55,這意味著字元是7。" -#: website/public/showcase/ctf/index.html:440 +#: website/public/showcase/ctf/index.html:444 msgctxt "page:showcase/ctf/index.html" msgid "Follow the CTF check" msgstr "遵循CTF檢查" -#: website/public/showcase/ctf/index.html:490 +#: website/public/showcase/ctf/index.html:494 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF assembly" msgstr "複製CTF裝配" -#: website/public/showcase/ctf/index.html:514 +#: website/public/showcase/ctf/index.html:518 msgctxt "page:showcase/ctf/index.html" msgid "Copy readable CTF check" msgstr "複製可讀CTF檢查" -#: website/public/showcase/ctf/index.html:584 +#: website/public/showcase/ctf/index.html:588 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver excerpt" msgstr "複製CTF解算器摘錄" -#: website/public/showcase/ctf/index.html:658 +#: website/public/showcase/ctf/index.html:662 msgctxt "page:showcase/ctf/index.html" msgid "Copy recovered flag" msgstr "複製恢復標誌" -#: website/public/showcase/ctf/index.html:731 +#: website/public/showcase/ctf/index.html:735 msgctxt "page:showcase/ctf/index.html" msgid "Copy CTF solver commands" msgstr "複製CTF求解器命令" -#: website/public/showcase/ctf/index.html:773 +#: website/public/showcase/ctf/index.html:777 msgctxt "page:showcase/ctf/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/showcase/dx-ball/index.html:108 +#: website/public/showcase/dx-ball/index.html:103 msgctxt "page:showcase/dx-ball/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -7855,35 +7863,35 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/dx-ball/index.html:190 +#: website/public/showcase/dx-ball/index.html:194 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / DX-Ball" msgstr "{ph0}首頁{ph1} / {ph2}案例展示{ph3} / DX-Ball" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:193 +#: website/public/showcase/dx-ball/index.html:197 msgctxt "page:showcase/dx-ball/index.html" msgid "Case study · DX-Ball 1.07" msgstr "案例 · DX-Ball 1.07" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <br /> -#: website/public/showcase/dx-ball/index.html:194 +#: website/public/showcase/dx-ball/index.html:198 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Rebuilding DX-Ball{ph0}from its executable." msgstr "從可執行檔案{ph0}重建 DX-Ball。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:195 +#: website/public/showcase/dx-ball/index.html:199 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The goal is a maintainable C version of the 1996 Windows game. REA helps the" " agent inspect the original, one function at a time." msgstr "目標是為這款 1996 年的 Windows 遊戲重建一份可維護的 C 程式碼。REA 幫助程式設計助手逐個分析原版函式。" -#: website/public/showcase/dx-ball/index.html:199 +#: website/public/showcase/dx-ball/index.html:203 msgctxt "page:showcase/dx-ball/index.html" msgid "Windows i386 · C · REA" msgstr "Windows i386 · C · REA" @@ -7891,7 +7899,7 @@ msgstr "Windows i386 · C · REA" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <a href="../../assets/figures/dx-ball-sound-pan-investigation.svg" > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:216 +#: website/public/showcase/dx-ball/index.html:220 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -7902,7 +7910,7 @@ msgstr "" "從可執行檔案中的一個函式,到經過驗證的 C 程式碼:REA 提供指令、呼叫方和讀取的資料,重建專案據此實現並測試函式。{ph0}檢視大圖{ph1}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:227 +#: website/public/showcase/dx-ball/index.html:231 msgctxt "page:showcase/dx-ball/index.html" msgid "In this case study" msgstr "本案例內容" @@ -7910,7 +7918,7 @@ msgstr "本案例內容" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <a href="#progress"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:229 +#: website/public/showcase/dx-ball/index.html:233 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}The project{ph1}" @@ -7918,7 +7926,7 @@ msgstr "{ph0}專案進度{ph1}" #. {ph0}: <a href="#sound-pan"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:230 +#: website/public/showcase/dx-ball/index.html:234 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Sound pan{ph1}" @@ -7926,7 +7934,7 @@ msgstr "{ph0}聲像計算{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:231 +#: website/public/showcase/dx-ball/index.html:235 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Checking the result{ph1}" @@ -7934,25 +7942,25 @@ msgstr "{ph0}檢查結果{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/dx-ball/index.html:232 +#: website/public/showcase/dx-ball/index.html:236 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Continue the work{ph1}" msgstr "{ph0}繼續工作{ph1}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:240 +#: website/public/showcase/dx-ball/index.html:244 msgctxt "page:showcase/dx-ball/index.html" msgid "maintained C functions" msgstr "個可維護的 C 函式" -#: website/public/showcase/dx-ball/index.html:244 +#: website/public/showcase/dx-ball/index.html:248 msgctxt "page:showcase/dx-ball/index.html" msgid "comparisons with original code" msgstr "與原始程式碼的比較" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:248 +#: website/public/showcase/dx-ball/index.html:252 msgctxt "page:showcase/dx-ball/index.html" msgid "functions with matching compiled bytes" msgstr "個編譯後位元組匹配的函式" @@ -7964,7 +7972,7 @@ msgstr "個編譯後位元組匹配的函式" #. {ph2}: <a href="https://github.com/N0zoM1z0/dx- #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md" > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:251 +#: website/public/showcase/dx-ball/index.html:255 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -7973,13 +7981,13 @@ msgid "" msgstr "專案進度截至 2026 年 10 月 7 日。{ph0}進度記錄{ph1} · {ph2}測試覆蓋情況{ph3}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:263 +#: website/public/showcase/dx-ball/index.html:267 msgctxt "page:showcase/dx-ball/index.html" msgid "The project so far" msgstr "當前進度" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:264 +#: website/public/showcase/dx-ball/index.html:268 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered code covers board and resource handling, brick hits, " @@ -7992,13 +8000,13 @@ msgstr "" " Windows 整合。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:274 +#: website/public/showcase/dx-ball/index.html:278 msgctxt "page:showcase/dx-ball/index.html" msgid "Finding the sound-pan calculation" msgstr "找出聲音的左右位置如何計算" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:275 +#: website/public/showcase/dx-ball/index.html:279 msgctxt "page:showcase/dx-ball/index.html" msgid "" "When a brick is hit, its horizontal position is passed to the sound code. " @@ -8014,17 +8022,17 @@ msgstr "磚塊被擊中時,它的橫座標會傳給聲音處理程式碼。這 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/dx-ball/index.html:282 +#: website/public/showcase/dx-ball/index.html:286 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/showcase/dx-ball/index.html:286 -#: website/public/showcase/dx-ball/index.html:477 -#: website/public/showcase/dx-ball/index.html:498 -#: website/public/showcase/dx-ball/index.html:569 -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:290 +#: website/public/showcase/dx-ball/index.html:481 +#: website/public/showcase/dx-ball/index.html:502 +#: website/public/showcase/dx-ball/index.html:573 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy" msgstr "複製" @@ -8036,7 +8044,7 @@ msgstr "複製" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/dx-ball/index.html:295 +#: website/public/showcase/dx-ball/index.html:299 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8046,7 +8054,7 @@ msgstr "" "{ph0}›{ph1}{ph2}用 REA 找出 DX-Ball 如何計算聲音的左右位置。解釋計算過程,並展示程式碼。{ph3}{ph4}{ph5}" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:303 +#: website/public/showcase/dx-ball/index.html:307 msgctxt "page:showcase/dx-ball/index.html" msgid "" "An example prompt for your coding agent, with the local executable " @@ -8055,7 +8063,7 @@ msgid "" msgstr "把本地可執行檔案交給程式設計助手,再使用這個示例 prompt。下面展示助手為回答問題發起的 REA 查詢,以及得到的證據。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:308 +#: website/public/showcase/dx-ball/index.html:312 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The agent used REA to inspect the function, follow its brick-hit caller and " @@ -8067,7 +8075,7 @@ msgstr "助手用 REA 檢查函式、追蹤呼叫它的磚塊碰撞函式,再 #. {ph0}: <code>0x406400</code> #. {ph1}: <code>FUN_00406400(void)</code> #. {ph2}: <code>__ftol()</code> -#: website/public/showcase/dx-ball/index.html:314 +#: website/public/showcase/dx-ball/index.html:318 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8078,13 +8086,13 @@ msgid "" msgstr "" "REA 最初返回的 {ph0} 虛擬碼宣告瞭 {ph1},並呼叫 {ph2}。但指令中還有來自棧的輸入和浮點運算。這個差異提示助手:還需要繼續查。" -#: website/public/showcase/dx-ball/index.html:322 +#: website/public/showcase/dx-ball/index.html:326 msgctxt "page:showcase/dx-ball/index.html" msgid "The first decompiler view" msgstr "最初的反編譯結果" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:335 +#: website/public/showcase/dx-ball/index.html:339 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The output shows a conversion call. Reading the instructions below reveals " @@ -8092,20 +8100,20 @@ msgid "" msgstr "結果裡能看到一次轉換呼叫。繼續閱讀下面的指令,就能找出輸入,以及傳入這個呼叫前的計算。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:341 +#: website/public/showcase/dx-ball/index.html:345 msgctxt "page:showcase/dx-ball/index.html" msgid "Three questions answered through REA" msgstr "用 REA 回答三個問題" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:344 +#: website/public/showcase/dx-ball/index.html:348 msgctxt "page:showcase/dx-ball/index.html" msgid "Recover the missing input" msgstr "找回缺失的輸入" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>[EBP+8]</code> -#: website/public/showcase/dx-ball/index.html:361 +#: website/public/showcase/dx-ball/index.html:365 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8114,7 +8122,7 @@ msgid "" msgstr "函式結果同時提供虛擬碼、指令和呼叫方。這裡的 {ph0} 顯示了反編譯結果中缺失的整數輸入。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:368 +#: website/public/showcase/dx-ball/index.html:372 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the caller to understand the input" msgstr "追蹤呼叫方,理解輸入含義" @@ -8122,7 +8130,7 @@ msgstr "追蹤呼叫方,理解輸入含義" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>tile_x</code> #. {ph1}: <code>20 + 30 × tile_x</code> -#: website/public/showcase/dx-ball/index.html:385 +#: website/public/showcase/dx-ball/index.html:389 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8130,26 +8138,26 @@ msgid "" "scale {ph0} by 30; adding 20 gives the brick's screen coordinate, {ph1}." msgstr "REA 在第一次結果中就給出了這個呼叫方。呼叫前的指令將 {ph0} 乘以 30,再加上 20,得到磚塊的螢幕座標 {ph1}。" -#: website/public/showcase/dx-ball/index.html:392 +#: website/public/showcase/dx-ball/index.html:396 msgctxt "page:showcase/dx-ball/index.html" msgid "Read the values behind the memory addresses" msgstr "讀取記憶體地址後面的值" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:413 +#: website/public/showcase/dx-ball/index.html:417 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The returned bytes establish the two arithmetic constants and initial pan " "scale. The agent now has the values needed for the C expression." msgstr "返回的位元組確定了兩個運算常量,以及聲像縮放係數的初始值。助手由此得到編寫 C 表示式所需的數值。" -#: website/public/showcase/dx-ball/index.html:421 +#: website/public/showcase/dx-ball/index.html:425 msgctxt "page:showcase/dx-ball/index.html" msgid "From REA's findings to C" msgstr "從 REA 分析結果到 C 程式碼" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:422 +#: website/public/showcase/dx-ball/index.html:426 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Follow the five steps below. Each selection highlights the original " @@ -8158,7 +8166,7 @@ msgstr "下面分五步展示計算。點選每一步,原始指令和對應的 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:432 +#: website/public/showcase/dx-ball/index.html:436 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}01{ph1} Input" @@ -8166,7 +8174,7 @@ msgstr "{ph0}01{ph1} 輸入" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:440 +#: website/public/showcase/dx-ball/index.html:444 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}02{ph1} Multiply" @@ -8174,7 +8182,7 @@ msgstr "{ph0}02{ph1} 乘以" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:448 +#: website/public/showcase/dx-ball/index.html:452 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}03{ph1} Subtract" @@ -8182,7 +8190,7 @@ msgstr "{ph0}03{ph1} 減去" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:456 +#: website/public/showcase/dx-ball/index.html:460 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}04{ph1} Scale" @@ -8190,20 +8198,20 @@ msgstr "{ph0}04{ph1} 縮放" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/dx-ball/index.html:464 +#: website/public/showcase/dx-ball/index.html:468 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}05{ph1} Return" msgstr "{ph0}05{ph1} 返回" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:476 +#: website/public/showcase/dx-ball/index.html:480 msgctxt "page:showcase/dx-ball/index.html" msgid "Original x86 · excerpt" msgstr "原始 x86 · 節選" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:497 +#: website/public/showcase/dx-ball/index.html:501 msgctxt "page:showcase/dx-ball/index.html" msgid "Reconstructed C" msgstr "重建的 C 程式碼" @@ -8214,7 +8222,7 @@ msgstr "重建的 C 程式碼" #. {ph2}: <code>[EBP+8]</code> #. {ph3}: <code>FILD</code> #. {ph4}: <code>x</code> -#: website/public/showcase/dx-ball/index.html:524 +#: website/public/showcase/dx-ball/index.html:528 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8233,7 +8241,7 @@ msgstr "" #. {ph3}: <code>0x420068</code> #. {ph4}: <code>read_bytes</code> #. {ph5}: <code>1.5625</code> -#: website/public/showcase/dx-ball/index.html:531 +#: website/public/showcase/dx-ball/index.html:535 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8250,7 +8258,7 @@ msgstr "" #. {ph3}: <code>0x420070</code> #. {ph4}: <code>500.0</code> #. {ph5}: <code>320</code> -#: website/public/showcase/dx-ball/index.html:537 +#: website/public/showcase/dx-ball/index.html:541 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8268,7 +8276,7 @@ msgstr "" #. {ph3}: <code>0x4210a0</code> #. {ph4}: <code>dxball_pan_scale</code> #. {ph5}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:543 +#: website/public/showcase/dx-ball/index.html:547 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8285,7 +8293,7 @@ msgstr "" #. {ph2}: <code>0x406430</code> #. {ph3}: <code>__ftol</code> #. {ph4}: <code>DxBallInt</code> -#: website/public/showcase/dx-ball/index.html:550 +#: website/public/showcase/dx-ball/index.html:554 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8297,7 +8305,7 @@ msgstr "" "{ph4},再與原始 x86 函式比較,驗證返回值。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:559 +#: website/public/showcase/dx-ball/index.html:563 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The assembly excerpt selects the input, arithmetic and return instructions. " @@ -8305,24 +8313,24 @@ msgid "" "setup and cleanup." msgstr "這段彙編節選包含輸入、運算和返回指令。下面的完整列表還保留了中間的儲存操作,以及函式開頭和結尾的處理。" -#: website/public/showcase/dx-ball/index.html:565 +#: website/public/showcase/dx-ball/index.html:569 msgctxt "page:showcase/dx-ball/index.html" msgid "Full assembly and supporting evidence" msgstr "完整彙編與相關證據" -#: website/public/showcase/dx-ball/index.html:568 +#: website/public/showcase/dx-ball/index.html:572 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · 0x406400–0x40643e" msgstr "REA結果 · 0x406400–0x40643e" -#: website/public/showcase/dx-ball/index.html:602 +#: website/public/showcase/dx-ball/index.html:606 msgctxt "page:showcase/dx-ball/index.html" msgid "What the caller supplies" msgstr "呼叫方傳入什麼" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>0x411f40</code> -#: website/public/showcase/dx-ball/index.html:603 +#: website/public/showcase/dx-ball/index.html:607 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8330,55 +8338,55 @@ msgid "" "then pushes it before the call:" msgstr "{ph0} 處的磚塊碰撞函式把格子座標乘以 30,再加上 20,然後在呼叫前將結果壓棧:" -#: website/public/showcase/dx-ball/index.html:617 +#: website/public/showcase/dx-ball/index.html:621 msgctxt "page:showcase/dx-ball/index.html" msgid "What the data reads establish" msgstr "讀取資料確認了什麼" -#: website/public/showcase/dx-ball/index.html:620 +#: website/public/showcase/dx-ball/index.html:624 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte reads, decoded as little-endian doubles" msgstr "REA 讀取的位元組,按小端雙精度浮點數解碼" -#: website/public/showcase/dx-ball/index.html:625 +#: website/public/showcase/dx-ball/index.html:629 msgctxt "page:showcase/dx-ball/index.html" msgid "Address" msgstr "地址" -#: website/public/showcase/dx-ball/index.html:626 +#: website/public/showcase/dx-ball/index.html:630 msgctxt "page:showcase/dx-ball/index.html" msgid "Value" msgstr "數值" -#: website/public/showcase/dx-ball/index.html:627 +#: website/public/showcase/dx-ball/index.html:631 msgctxt "page:showcase/dx-ball/index.html" msgid "Used for" msgstr "用於" -#: website/public/showcase/dx-ball/index.html:634 +#: website/public/showcase/dx-ball/index.html:638 msgctxt "page:showcase/dx-ball/index.html" msgid "First multiplication" msgstr "第一次乘法" -#: website/public/showcase/dx-ball/index.html:639 +#: website/public/showcase/dx-ball/index.html:643 msgctxt "page:showcase/dx-ball/index.html" msgid "Subtraction" msgstr "減法" #. {ph0}: <code>1.0</code> -#: website/public/showcase/dx-ball/index.html:643 +#: website/public/showcase/dx-ball/index.html:647 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0} initially" msgstr "{ph0} 最初" -#: website/public/showcase/dx-ball/index.html:644 +#: website/public/showcase/dx-ball/index.html:648 msgctxt "page:showcase/dx-ball/index.html" msgid "Stored pan scale" msgstr "儲存的聲像縮放係數" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:649 +#: website/public/showcase/dx-ball/index.html:653 msgctxt "page:showcase/dx-ball/index.html" msgid "" "Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target. The linked " @@ -8393,7 +8401,7 @@ msgstr "使用 REA 4.1.0 記錄,分析目標為透過雜湊確定的 DX-Ball 1 #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md" #. > #. {ph3}: </a > -#: website/public/showcase/dx-ball/index.html:654 +#: website/public/showcase/dx-ball/index.html:658 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8401,13 +8409,13 @@ msgid "" "references{ph3}" msgstr "{ph0}重建原始碼{ph1} · {ph2}調查筆記與證據引用{ph3}" -#: website/public/showcase/dx-ball/index.html:668 +#: website/public/showcase/dx-ball/index.html:672 msgctxt "page:showcase/dx-ball/index.html" msgid "Checking the recovered function" msgstr "驗證還原的函式" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:669 +#: website/public/showcase/dx-ball/index.html:673 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The recovered function passes two checks: its return values match the " @@ -8415,13 +8423,13 @@ msgid "" msgstr "還原的函式透過了兩項檢查:返回值與原版一致,編譯後的位元組與原始可執行檔案一致。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:675 +#: website/public/showcase/dx-ball/index.html:679 msgctxt "page:showcase/dx-ball/index.html" msgid "3,205 behavior cases" msgstr "3,205 個行為測試用例" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:676 +#: website/public/showcase/dx-ball/index.html:680 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The tests execute the original x86 function and compare its return value " @@ -8432,13 +8440,13 @@ msgstr "" "和 −1。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:684 +#: website/public/showcase/dx-ball/index.html:688 msgctxt "page:showcase/dx-ball/index.html" msgid "63 matching bytes" msgstr "63 位元組完全匹配" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:685 +#: website/public/showcase/dx-ball/index.html:689 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The C function is compiled with the pinned VC4.0 toolchain. Compiler replay " @@ -8447,7 +8455,7 @@ msgid "" msgstr "C 函式使用指定的 VC4.0 工具鏈編譯。應用經過檢查的重定位,並核對引用的常量後,編譯結果與原始函式的全部位元組一致。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:693 +#: website/public/showcase/dx-ball/index.html:697 msgctxt "page:showcase/dx-ball/index.html" msgid "" "At a scale of 1, the recovered calculation returns −500 at the left edge, 0 " @@ -8459,19 +8467,19 @@ msgstr "縮放係數為 1 時,計算在螢幕左邊緣返回 −500,中心 #. ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md" #. > #. {ph1}: </a > -#: website/public/showcase/dx-ball/index.html:699 +#: website/public/showcase/dx-ball/index.html:703 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "{ph0}Read the compiler replay details{ph1}" msgstr "{ph0}閱讀編譯器重播詳細資訊{ph1}" -#: website/public/showcase/dx-ball/index.html:708 +#: website/public/showcase/dx-ball/index.html:712 msgctxt "page:showcase/dx-ball/index.html" msgid "Continue the investigation" msgstr "繼續調查" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:709 +#: website/public/showcase/dx-ball/index.html:713 msgctxt "page:showcase/dx-ball/index.html" msgid "" "The same approach is being used for particle updates, explosion queues and " @@ -8480,14 +8488,14 @@ msgid "" msgstr "粒子更新、爆炸佇列和獎勵生成也使用同樣的方法:檢查相關函式,還原狀態與依賴,再把實現和原版比較。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:715 +#: website/public/showcase/dx-ball/index.html:719 msgctxt "page:showcase/dx-ball/index.html" msgid "" "To inspect the sound-pan function yourself, follow the DX-Ball project's " "setup instructions and supply its matching original target. Then run:" msgstr "如果你也想分析這個聲像函式,先按 DX-Ball 專案的說明配置環境,並準備匹配的原始檔案。然後執行:" -#: website/public/showcase/dx-ball/index.html:722 +#: website/public/showcase/dx-ball/index.html:726 msgctxt "page:showcase/dx-ball/index.html" msgid "In the DX-Ball checkout" msgstr "在 DX-Ball 儲存庫目錄中" @@ -8497,7 +8505,7 @@ msgstr "在 DX-Ball 儲存庫目錄中" #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/dx-ball/index.html:736 +#: website/public/showcase/dx-ball/index.html:740 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8510,7 +8518,7 @@ msgstr "{ph0}DX-Ball 儲存庫{ph1}{ph2}當前原始碼、進度和本地配置 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:741 +#: website/public/showcase/dx-ball/index.html:745 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8525,7 +8533,7 @@ msgstr "{ph0}REA 分析流程{ph1}{ph2}追蹤這段計算,再用同樣方法 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/dx-ball/index.html:748 +#: website/public/showcase/dx-ball/index.html:752 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "" @@ -8549,14 +8557,14 @@ msgstr "" "檢視 DX-Ball 的重建過程:用 REA 分析二進位制檔案,編寫可維護的 C 程式碼,再透過原始 x86 行為測試和編譯位元組匹配驗證。" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:202 +#: website/public/showcase/dx-ball/index.html:206 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DX-Ball sound-pan investigation; scroll horizontally on smaller screens" msgstr "DX-Ball 聲像計算調查;小螢幕可橫向滾動" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:208 +#: website/public/showcase/dx-ball/index.html:212 msgctxt "page:showcase/dx-ball/index.html" msgid "" "DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller " @@ -8569,89 +8577,89 @@ msgstr "" "1.5625,減去 500.0,再乘以 pan_scale,最後返回整數。重建的 C 程式碼透過 3,205 個用例與原始 x86 函式比較,並用 " "VC4.0 編譯結果匹配全部 63 位元組。" -#: website/public/showcase/dx-ball/index.html:226 +#: website/public/showcase/dx-ball/index.html:230 msgctxt "page:showcase/dx-ball/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/showcase/dx-ball/index.html:235 +#: website/public/showcase/dx-ball/index.html:239 msgctxt "page:showcase/dx-ball/index.html" msgid "DX-Ball reconstruction case study" msgstr "DX-Ball重建案例研究" -#: website/public/showcase/dx-ball/index.html:286 +#: website/public/showcase/dx-ball/index.html:290 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy example prompt" msgstr "複製示例提示" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:427 +#: website/public/showcase/dx-ball/index.html:431 msgctxt "page:showcase/dx-ball/index.html" msgid "Follow the sound-pan calculation" msgstr "追蹤聲像計算" -#: website/public/showcase/dx-ball/index.html:477 +#: website/public/showcase/dx-ball/index.html:481 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy original assembly excerpt" msgstr "複製原始彙編摘錄" -#: website/public/showcase/dx-ball/index.html:498 +#: website/public/showcase/dx-ball/index.html:502 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy sound-pan function" msgstr "複製聲像函式" # Reviewed for clear terminology and preserved evidence. -#: website/public/showcase/dx-ball/index.html:569 +#: website/public/showcase/dx-ball/index.html:573 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy complete sound-pan assembly" msgstr "複製完整聲像計算彙編" -#: website/public/showcase/dx-ball/index.html:723 +#: website/public/showcase/dx-ball/index.html:727 msgctxt "page:showcase/dx-ball/index.html" msgid "Copy DX-Ball analysis command" msgstr "複製DX-Ball分析命令" -#: website/public/showcase/dx-ball/index.html:781 +#: website/public/showcase/dx-ball/index.html:785 msgctxt "page:showcase/dx-ball/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/showcase/index.html:108 +#: website/public/showcase/index.html:103 msgctxt "page:showcase/index.html" msgid "Skip to content" msgstr "跳轉到內容" #. {ph0}: <a href="../"> #. {ph1}: </a> -#: website/public/showcase/index.html:190 +#: website/public/showcase/index.html:194 #, python-brace-format msgctxt "page:showcase/index.html" msgid "{ph0}Home{ph1} / Showcases" msgstr "{ph0}首頁{ph1} /陳列櫃" -#: website/public/showcase/index.html:191 +#: website/public/showcase/index.html:195 msgctxt "page:showcase/index.html" msgid "REA case studies." msgstr "REA 實際案例。" -#: website/public/showcase/index.html:192 +#: website/public/showcase/index.html:196 msgctxt "page:showcase/index.html" msgid "" "Android, games, Electron and a CTF challenge, with code, figures and checked" " results." msgstr "安卓,遊戲,Electron和CTF挑戰,與程式碼,數字和檢查結果。" -#: website/public/showcase/index.html:199 +#: website/public/showcase/index.html:203 msgctxt "page:showcase/index.html" msgid "Android · APK analysis" msgstr "Android · APK 分析" -#: website/public/showcase/index.html:201 +#: website/public/showcase/index.html:205 msgctxt "page:showcase/index.html" msgid "How an authenticator generates a login code" msgstr "驗證器如何生成登入驗證碼" -#: website/public/showcase/index.html:202 +#: website/public/showcase/index.html:206 msgctxt "page:showcase/index.html" msgid "" "Find Aegis's six-digit code calculation in its released APK. Trace the " @@ -8659,22 +8667,22 @@ msgid "" "changes every 30 seconds." msgstr "在其釋出的APK中找到Aegis的六位數程式碼計算。 使用REA跟蹤生成方法,然後移動演示時鐘以檢視程式碼每30秒更改一次的原因。" -#: website/public/showcase/index.html:213 +#: website/public/showcase/index.html:217 msgctxt "page:showcase/index.html" msgid "Read the Android case study" msgstr "閱讀Android案例研究" -#: website/public/showcase/index.html:217 +#: website/public/showcase/index.html:221 msgctxt "page:showcase/index.html" msgid "CTF · Native analysis" msgstr "CTF · 原生分析" -#: website/public/showcase/index.html:219 +#: website/public/showcase/index.html:223 msgctxt "page:showcase/index.html" msgid "Solve a CTF flag checker" msgstr "分析 CTF flag 檢查器" -#: website/public/showcase/index.html:220 +#: website/public/showcase/index.html:224 msgctxt "page:showcase/index.html" msgid "" "Inspect an easy DownUnderCTF challenge with REA. Find its checking " @@ -8682,22 +8690,22 @@ msgid "" "with the original program." msgstr "使用REA檢查一個簡單的DownUnderCTF挑戰。 找到它的檢查函式,將掩碼和和轉換為方程,然後用原始程式驗證已求解的標誌。" -#: website/public/showcase/index.html:231 +#: website/public/showcase/index.html:235 msgctxt "page:showcase/index.html" msgid "Read the CTF case study" msgstr "閱讀CTF案例研究" -#: website/public/showcase/index.html:235 +#: website/public/showcase/index.html:239 msgctxt "page:showcase/index.html" msgid "Native · Reconstruction" msgstr "原生程式 · 重建" -#: website/public/showcase/index.html:237 +#: website/public/showcase/index.html:241 msgctxt "page:showcase/index.html" msgid "DX-Ball's sound-pan calculation" msgstr "DX-Ball 的聲像計算" -#: website/public/showcase/index.html:238 +#: website/public/showcase/index.html:242 msgctxt "page:showcase/index.html" msgid "" "Recover a sound-pan calculation from a 1996 Windows game. REA's " @@ -8707,22 +8715,22 @@ msgstr "" "從1996年的Windows遊戲中恢復左/右聲音位置的計算。 " "REA的指令,呼叫者引用和數字常量導致一個小的C函式,對照原始行為和所有63個編譯位元組進行檢查。" -#: website/public/showcase/index.html:250 +#: website/public/showcase/index.html:254 msgctxt "page:showcase/index.html" msgid "Read the DX-Ball case study" msgstr "閱讀DX-Ball案例研究" -#: website/public/showcase/index.html:254 +#: website/public/showcase/index.html:258 msgctxt "page:showcase/index.html" msgid "Electron · Feature tracing" msgstr "Electron · 功能追蹤" -#: website/public/showcase/index.html:256 +#: website/public/showcase/index.html:260 msgctxt "page:showcase/index.html" msgid "How Notion copies text and HTML" msgstr "Notion 如何複製文字和 HTML" -#: website/public/showcase/index.html:257 +#: website/public/showcase/index.html:261 msgctxt "page:showcase/index.html" msgid "" "Trace a page-facing API through Notion's packaged JavaScript. Follow its IPC" @@ -8732,22 +8740,22 @@ msgstr "" "透過跟蹤面向頁面的API Notion包裝好了 JavaScript. " "跟隨它的IPC包裝到系統剪貼簿,然後看看一個小的HTML標記如何保持豐富的塊資料連線到複製。" -#: website/public/showcase/index.html:268 +#: website/public/showcase/index.html:272 msgctxt "page:showcase/index.html" msgid "Read the Notion case study" msgstr "閱讀Notion案例研究" -#: website/public/showcase/index.html:272 +#: website/public/showcase/index.html:276 msgctxt "page:showcase/index.html" msgid "PC-98 DOS · Reconstruction" msgstr "PC-98 DOS · 重建" -#: website/public/showcase/index.html:274 +#: website/public/showcase/index.html:278 msgctxt "page:showcase/index.html" msgid "How TH04 aims a ring of bullets" msgstr "TH04 如何把環形彈幕對準玩家" -#: website/public/showcase/index.html:275 +#: website/public/showcase/index.html:279 msgctxt "page:showcase/index.html" msgid "" "Inspect the original 16-bit angle helper with REA. Match its multiply, " @@ -8755,24 +8763,24 @@ msgid "" "a ring aimed at the player." msgstr "用REA檢查原始的16位角度助手。 將其乘法,除法和座標操作匹配到可讀的C++,然後看看它們如何產生一個針對玩家的環形彈幕。" -#: website/public/showcase/index.html:286 +#: website/public/showcase/index.html:290 msgctxt "page:showcase/index.html" msgid "Read the TH04 case study" msgstr "閱讀TH04案例研究" -#: website/public/showcase/index.html:291 +#: website/public/showcase/index.html:295 msgctxt "page:showcase/index.html" msgid "Step-by-step guides" msgstr "循序漸進指南" -#: website/public/showcase/index.html:292 +#: website/public/showcase/index.html:296 msgctxt "page:showcase/index.html" msgid "" "The guides walk through a native calculation, an Electron export and a " "browser request. Each starts with a prompt and a concrete target." msgstr "本指南介紹了本機計算、Electron匯出和瀏覽器請求。 每個都以提示和具體目標開始。" -#: website/public/showcase/index.html:296 +#: website/public/showcase/index.html:300 msgctxt "page:showcase/index.html" msgid "Read the guides" msgstr "閱讀指南" @@ -8791,12 +8799,12 @@ msgstr "" "跟我來 REA 透過程式碼、數字和演示進行調查:Android身份驗證器, DX-Ball, Notion, TH04 " "和一個DownUnderCTFflag 檢查器。" -#: website/public/showcase/index.html:313 +#: website/public/showcase/index.html:317 msgctxt "page:showcase/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/showcase/notion/index.html:108 +#: website/public/showcase/notion/index.html:103 msgctxt "page:showcase/notion/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -8805,37 +8813,37 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/notion/index.html:190 +#: website/public/showcase/notion/index.html:194 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / Notion" msgstr "{ph0}首頁{ph1} / {ph2}案例展示{ph3} / Notion" -#: website/public/showcase/notion/index.html:193 +#: website/public/showcase/notion/index.html:197 msgctxt "page:showcase/notion/index.html" msgid "Case study · Electron" msgstr "個案研究*Electron" #. {ph0}: <br /> -#: website/public/showcase/notion/index.html:194 +#: website/public/showcase/notion/index.html:198 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "How Notion copies{ph0}text and HTML." msgstr "如何 Notion 複製{ph0}文字和HTML。" -#: website/public/showcase/notion/index.html:195 +#: website/public/showcase/notion/index.html:199 msgctxt "page:showcase/notion/index.html" msgid "" "Trace a clipboard call from Notion's page API, through the preload and main " "process, to Electron's clipboard writer." msgstr "跟蹤剪貼簿呼叫從Notion的頁面API,透過預載入和主程序,到Electron的剪貼簿編寫器。" -#: website/public/showcase/notion/index.html:199 +#: website/public/showcase/notion/index.html:203 msgctxt "page:showcase/notion/index.html" msgid "Notion Desktop 7.6.1 · JavaScript · REA" msgstr "Notion桌面7.6.1·JavaScript*REA" -#: website/public/showcase/notion/index.html:203 +#: website/public/showcase/notion/index.html:207 msgctxt "page:showcase/notion/index.html" msgid "The bridge inside Notion's desktop package" msgstr "Notion 桌面包中的橋接程式碼" @@ -8847,7 +8855,7 @@ msgstr "Notion 桌面包中的橋接程式碼" #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:205 +#: website/public/showcase/notion/index.html:209 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8862,7 +8870,7 @@ msgstr "{ph0}01 · 面向頁面的API{ph1} {ph2}{ph3}{ph4} {ph5}預載入公開 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:212 +#: website/public/showcase/notion/index.html:216 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8877,7 +8885,7 @@ msgstr "{ph0}02 · 預載入包裝器{ph1} {ph2}{ph3}{ph4} {ph5}包裝器傳送 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:219 +#: website/public/showcase/notion/index.html:223 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8892,7 +8900,7 @@ msgstr "{ph0}03 · 主程序處理程式{ph1} {ph2}{ph3}{ph4} {ph5}接收器檢 #. {ph4}: </span> #. {ph5}: <span class="flow-note" > #. {ph6}: </span > -#: website/public/showcase/notion/index.html:226 +#: website/public/showcase/notion/index.html:230 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8901,28 +8909,28 @@ msgid "" msgstr "{ph0}04 · 系統剪貼簿{ph1} {ph2}{ph3}{ph4} {ph5}Electron 寫入提供的文字和HTML。{ph6}" #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:234 +#: website/public/showcase/notion/index.html:238 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "One channel joins the two sides: {ph0}" msgstr "一個通道連線雙方: {ph0}" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:238 +#: website/public/showcase/notion/index.html:242 msgctxt "page:showcase/notion/index.html" msgid "" "The packaged code uses the same channel in the preload and main process. " "Resolving the wrappers reveals the Electron calls behind those names." msgstr "預載入指令碼和主程序使用同一個通道。解析包裝函式後,就能看出這些名稱背後實際呼叫的 Electron 函式。" -#: website/public/showcase/notion/index.html:247 +#: website/public/showcase/notion/index.html:251 msgctxt "page:showcase/notion/index.html" msgid "In this case study" msgstr "在本個案研究中" #. {ph0}: <a href="#clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:249 +#: website/public/showcase/notion/index.html:253 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Follow the clipboard bridge{ph1}" @@ -8930,7 +8938,7 @@ msgstr "{ph0}跟隨剪貼簿橋{ph1}" #. {ph0}: <a href="#rich-clipboard"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:250 +#: website/public/showcase/notion/index.html:254 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}Keeping a block's structure{ph1}" @@ -8938,20 +8946,20 @@ msgstr "{ph0}保留內容塊的結構{ph1}" #. {ph0}: <a href="#continue"> #. {ph1}: </a> -#: website/public/showcase/notion/index.html:251 +#: website/public/showcase/notion/index.html:255 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}More examples and sources{ph1}" msgstr "{ph0}更多示例和來源{ph1}" -#: website/public/showcase/notion/index.html:256 +#: website/public/showcase/notion/index.html:260 msgctxt "page:showcase/notion/index.html" msgid "Where does the copy operation go?" msgstr "複製操作去哪裡?" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>clipboard.write</code> -#: website/public/showcase/notion/index.html:257 +#: website/public/showcase/notion/index.html:261 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8968,17 +8976,17 @@ msgstr "頁面可以呼叫名為 {ph0} 的方法。它在預載入指令碼中 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/notion/index.html:264 +#: website/public/showcase/notion/index.html:268 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/showcase/notion/index.html:268 -#: website/public/showcase/notion/index.html:341 -#: website/public/showcase/notion/index.html:370 -#: website/public/showcase/notion/index.html:401 -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:272 +#: website/public/showcase/notion/index.html:345 +#: website/public/showcase/notion/index.html:374 +#: website/public/showcase/notion/index.html:405 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy" msgstr "複製" @@ -8989,7 +8997,7 @@ msgstr "複製" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/notion/index.html:277 +#: website/public/showcase/notion/index.html:281 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -8998,20 +9006,20 @@ msgid "" msgstr "" "{ph0}›{ph1}{ph2}使用REA跟蹤Notion如何將文字和HTML複製到系統剪貼簿。 在每個步驟顯示程式碼。{ph3}{ph4}{ph5}" -#: website/public/showcase/notion/index.html:285 +#: website/public/showcase/notion/index.html:289 msgctxt "page:showcase/notion/index.html" msgid "" "An example prompt with Notion's local application package available to your " "coding agent." msgstr "一個示例提示與Notion的本地應用程式包可供你的程式設計助手." -#: website/public/showcase/notion/index.html:290 +#: website/public/showcase/notion/index.html:294 msgctxt "page:showcase/notion/index.html" msgid "REA finds where to start reading" msgstr "REA查詢從哪裡開始閱讀" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:291 +#: website/public/showcase/notion/index.html:295 msgctxt "page:showcase/notion/index.html" msgid "" "Analyzing the tab preload with REA locates the API exposed to the page and " @@ -9019,14 +9027,14 @@ msgid "" " the minified bundle:" msgstr "用 REA 分析標籤頁的預載入指令碼,可以找到暴露給頁面的 API,以及傳送 IPC 請求的呼叫。兩個結果都給出了在壓縮程式碼中的位置:" -#: website/public/showcase/notion/index.html:297 +#: website/public/showcase/notion/index.html:301 msgctxt "page:showcase/notion/index.html" msgid "REA findings → two places to open" msgstr "REA 分析結果 → 兩個原始碼位置" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>analyze_javascript_application</code> -#: website/public/showcase/notion/index.html:312 +#: website/public/showcase/notion/index.html:316 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9040,7 +9048,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>invokerInMain</code> #. {ph1}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:319 +#: website/public/showcase/notion/index.html:323 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9052,25 +9060,25 @@ msgstr "" "助手開啟這些位置,在組裝的 API 中找到剪貼簿成員,再讀取 {ph0}。呼叫處傳入 " "{ph1},讓助手知道要在主程序程式碼中搜尋哪個名稱。下面四段程式碼展示這條呼叫鏈。" -#: website/public/showcase/notion/index.html:328 +#: website/public/showcase/notion/index.html:332 msgctxt "page:showcase/notion/index.html" msgid "Four short pieces of code" msgstr "四段簡短程式碼" -#: website/public/showcase/notion/index.html:329 +#: website/public/showcase/notion/index.html:333 msgctxt "page:showcase/notion/index.html" msgid "" "Simplified from the packaged JavaScript, with readable variable names. " "Unrelated members are omitted." msgstr "從打包的JavaScript簡化,具有可讀的變數名稱。 不相關的成員被省略。" -#: website/public/showcase/notion/index.html:335 +#: website/public/showcase/notion/index.html:339 msgctxt "page:showcase/notion/index.html" msgid "Start at the API exposed to the page" msgstr "從公開到頁面的API開始" #. {ph0}: <code>invokerInMain</code> -#: website/public/showcase/notion/index.html:357 +#: website/public/showcase/notion/index.html:361 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9078,14 +9086,14 @@ msgid "" "how the request leaves the page's process." msgstr "此成員提供通道名稱。 的實施 {ph0} 告訴我們請求如何離開頁面的程序。" -#: website/public/showcase/notion/index.html:364 +#: website/public/showcase/notion/index.html:368 msgctxt "page:showcase/notion/index.html" msgid "Resolve the preload's wrapper" msgstr "解析預載入的包裝器" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code class="notion-channel">notion:clipboard:write</code> -#: website/public/showcase/notion/index.html:387 +#: website/public/showcase/notion/index.html:391 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9093,14 +9101,14 @@ msgid "" "response IPC. We can now look for {ph0} on the main-process side." msgstr "返回的函式透過 Electron 的請求/響應 IPC 轉發引數。接下來可以在主程序中查詢 {ph0}。" -#: website/public/showcase/notion/index.html:395 +#: website/public/showcase/notion/index.html:399 msgctxt "page:showcase/notion/index.html" msgid "Check how the receiver is registered" msgstr "檢查接收器是如何註冊的" #. {ph0}: <code>addListener</code> #. {ph1}: <code>ipcMain.handle</code> -#: website/public/showcase/notion/index.html:416 +#: website/public/showcase/notion/index.html:420 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9108,13 +9116,13 @@ msgid "" "receiver for that channel." msgstr "主程序使用另一個包裝器。 其 {ph0} 方法註冊一個 {ph1} 那個頻道的接收器。" -#: website/public/showcase/notion/index.html:423 +#: website/public/showcase/notion/index.html:427 msgctxt "page:showcase/notion/index.html" msgid "Find the write and its sender check" msgstr "查詢寫入及其發件人檢查" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:446 +#: website/public/showcase/notion/index.html:450 msgctxt "page:showcase/notion/index.html" msgid "" "This is the destination. After checking the sender, the handler passes the " @@ -9124,14 +9132,14 @@ msgstr "" "這就是呼叫的終點。處理函式檢查傳送方後,把收到的資料交給 Electron 的剪貼簿 " "API。通道名和兩個解析後的包裝函式,把暴露給頁面的方法連線到了這裡。" -#: website/public/showcase/notion/index.html:457 +#: website/public/showcase/notion/index.html:461 msgctxt "page:showcase/notion/index.html" msgid "How does a copied block keep its structure?" msgstr "複製的塊如何保持其結構?" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>electronApi.clipboard.write</code> -#: website/public/showcase/notion/index.html:458 +#: website/public/showcase/notion/index.html:462 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9140,83 +9148,83 @@ msgid "" msgstr "" "Notion 的網頁編輯器透過 {ph0} 傳送文字和 HTML。它在本地保留內容塊資料,再在複製的 HTML 中放入一個 ID,將二者關聯起來。" -#: website/public/showcase/notion/index.html:464 +#: website/public/showcase/notion/index.html:468 msgctxt "page:showcase/notion/index.html" msgid "HTML links to saved block data" msgstr "儲存的塊資料的HTML連結" -#: website/public/showcase/notion/index.html:488 +#: website/public/showcase/notion/index.html:492 msgctxt "page:showcase/notion/index.html" msgid "Read the HTML ID" msgstr "讀取HTML ID" -#: website/public/showcase/notion/index.html:489 +#: website/public/showcase/notion/index.html:493 msgctxt "page:showcase/notion/index.html" msgid "Find the same local ID" msgstr "查詢相同的本地ID" -#: website/public/showcase/notion/index.html:490 +#: website/public/showcase/notion/index.html:494 msgctxt "page:showcase/notion/index.html" msgid "Restore Notion block data" msgstr "恢復Notion塊資料" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:492 +#: website/public/showcase/notion/index.html:496 msgctxt "page:showcase/notion/index.html" msgid "" "Illustrative text and ID. The recorded module test restores the block data " "when IDs match; a stale entry returns only text and HTML." msgstr "文字和 ID 為示意值。已記錄的模組測試顯示:ID 匹配時可以取回內容塊資料;條目失效時只返回文字和 HTML。" -#: website/public/showcase/notion/index.html:498 +#: website/public/showcase/notion/index.html:502 msgctxt "page:showcase/notion/index.html" msgid "" "On paste, Notion looks for the HTML ID and checks it against the saved copy." " Matching IDs restore the block data." msgstr "在貼上時,Notion查詢HTML ID並根據儲存的複製進行檢查。 匹配的Id恢復所述塊資料。" -#: website/public/showcase/notion/index.html:502 +#: website/public/showcase/notion/index.html:506 msgctxt "page:showcase/notion/index.html" msgid "Clipboard format recorded from web assets cached on July 13, 2026." msgstr "從2026年7月13日快取的web資產中記錄的剪貼簿格式。" -#: website/public/showcase/notion/index.html:508 +#: website/public/showcase/notion/index.html:512 msgctxt "page:showcase/notion/index.html" msgid "More examples and sources" msgstr "更多示例和來源" -#: website/public/showcase/notion/index.html:510 +#: website/public/showcase/notion/index.html:514 msgctxt "page:showcase/notion/index.html" msgid "Another example: Markdown tables" msgstr "另一個例子:Markdown 表格" -#: website/public/showcase/notion/index.html:511 +#: website/public/showcase/notion/index.html:515 msgctxt "page:showcase/notion/index.html" msgid "" "Notion parses Markdown into block data. This example shows how a table " "becomes header and data rows." msgstr "Notion將Markdown解析為塊資料。 此示例顯示錶如何成為標題和資料行。" -#: website/public/showcase/notion/index.html:516 +#: website/public/showcase/notion/index.html:520 msgctxt "page:showcase/notion/index.html" msgid "A table through Notion's Markdown parser" msgstr "透過Notion的Markdown解析器的表格" -#: website/public/showcase/notion/index.html:537 +#: website/public/showcase/notion/index.html:541 msgctxt "page:showcase/notion/index.html" msgid "" "Recorded output from an extracted Markdown parser. The table becomes rows " "and cells." msgstr "從提取的Markdown解析器記錄輸出。 表變為行和單元格。" -#: website/public/showcase/notion/index.html:544 +#: website/public/showcase/notion/index.html:548 msgctxt "page:showcase/notion/index.html" msgid "Another path: the offline SQLite connection" msgstr "另一條路徑:離線SQLite連線" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>getSqliteMeta</code> -#: website/public/showcase/notion/index.html:545 +#: website/public/showcase/notion/index.html:549 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9229,14 +9237,14 @@ msgstr "" "工具程序。後續的語句批次和結果直接透過這個埠傳輸。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:551 +#: website/public/showcase/notion/index.html:555 msgctxt "page:showcase/notion/index.html" msgid "" "Following this handoff explains where the database work runs, and why " "tracing only the initial IPC request misses the later conversation." msgstr "追蹤這次交接,就能知道資料庫操作在哪個程序執行,也能解釋為什麼只跟蹤最初的 IPC 請求會漏掉後續通訊。" -#: website/public/showcase/notion/index.html:558 +#: website/public/showcase/notion/index.html:562 msgctxt "page:showcase/notion/index.html" msgid "Sources and how to read the excerpts" msgstr "資料來源及如何閱讀摘錄" @@ -9245,7 +9253,7 @@ msgstr "資料來源及如何閱讀摘錄" #. {ph0}: <code>app.asar</code> #. {ph1}: <code>main/index.js</code> #. {ph2}: <code>isNotionWebContents</code> -#: website/public/showcase/notion/index.html:559 +#: website/public/showcase/notion/index.html:563 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9262,7 +9270,7 @@ msgstr "" #. {ph1}: <code>58169</code> #. {ph2}: <code>736810</code> #. {ph3}: <code>422457</code> -#: website/public/showcase/notion/index.html:567 +#: website/public/showcase/notion/index.html:571 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9276,7 +9284,7 @@ msgstr "" "模組。這些資源有獨立版本。儲存的測試執行提取出的模組和小型測試程式;輸出反映的是這些測試,沒有記錄桌面 UI 操作。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/notion/index.html:575 +#: website/public/showcase/notion/index.html:579 msgctxt "page:showcase/notion/index.html" msgid "" "The REA result shown here is a focused analysis of the saved tab preload, " @@ -9289,7 +9297,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>422457</code> -#: website/public/showcase/notion/index.html:582 +#: website/public/showcase/notion/index.html:586 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9305,7 +9313,7 @@ msgstr "" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:590 +#: website/public/showcase/notion/index.html:594 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9317,7 +9325,7 @@ msgstr "{ph0} JavaScript應用指南{ph1}{ph2}遵循一個小的Electron應用 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/notion/index.html:597 +#: website/public/showcase/notion/index.html:601 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "" @@ -9341,52 +9349,52 @@ msgstr "" "追蹤 Notion 的剪貼簿 API,經過 Electron 預載入指令碼、IPC " "包裝函式和主程序。透過簡短程式碼節選瞭解呼叫鏈,再檢視富文字剪貼簿格式。" -#: website/public/showcase/notion/index.html:246 +#: website/public/showcase/notion/index.html:250 msgctxt "page:showcase/notion/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/showcase/notion/index.html:254 +#: website/public/showcase/notion/index.html:258 msgctxt "page:showcase/notion/index.html" msgid "Notion Electron case study" msgstr "Notion Electron案例研究" -#: website/public/showcase/notion/index.html:268 +#: website/public/showcase/notion/index.html:272 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion analysis prompt" msgstr "複製Notion分析提示" -#: website/public/showcase/notion/index.html:341 +#: website/public/showcase/notion/index.html:345 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion preload excerpt" msgstr "複製Notion預載入摘錄" -#: website/public/showcase/notion/index.html:370 +#: website/public/showcase/notion/index.html:374 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion invoke wrapper excerpt" msgstr "複製 Notion 呼叫包裝摘錄" -#: website/public/showcase/notion/index.html:401 +#: website/public/showcase/notion/index.html:405 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion handler wrapper excerpt" msgstr "複製Notion處理程式包裝器摘錄" -#: website/public/showcase/notion/index.html:429 +#: website/public/showcase/notion/index.html:433 msgctxt "page:showcase/notion/index.html" msgid "Copy Notion clipboard receiver excerpt" msgstr "複製Notion剪貼簿接收器摘錄" -#: website/public/showcase/notion/index.html:484 +#: website/public/showcase/notion/index.html:488 msgctxt "page:showcase/notion/index.html" msgid "Restoring rich clipboard data on paste" msgstr "在貼上上還原豐富的剪貼簿資料" -#: website/public/showcase/notion/index.html:627 +#: website/public/showcase/notion/index.html:631 msgctxt "page:showcase/notion/index.html" msgid "Back to top" msgstr "回到頂部" -#: website/public/showcase/th04/index.html:108 +#: website/public/showcase/th04/index.html:103 msgctxt "page:showcase/th04/index.html" msgid "Skip to content" msgstr "跳轉到內容" @@ -9395,43 +9403,43 @@ msgstr "跳轉到內容" #. {ph1}: </a> #. {ph2}: <a href="../"> #. {ph3}: </a> -#: website/public/showcase/th04/index.html:190 +#: website/public/showcase/th04/index.html:194 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Home{ph1} / {ph2}Showcases{ph3} / TH04" msgstr "{ph0}首頁{ph1} / {ph2}案例展示{ph3} / TH04" -#: website/public/showcase/th04/index.html:193 +#: website/public/showcase/th04/index.html:197 msgctxt "page:showcase/th04/index.html" msgid "Case study · Touhou 4: Lotus Land Story" msgstr "個案研究·東方4:蓮花地故事" #. {ph0}: <br /> -#: website/public/showcase/th04/index.html:194 +#: website/public/showcase/th04/index.html:198 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Reconstructing TH04's{ph0}bullet patterns." msgstr "重建TH04{ph0}子彈圖案。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:195 +#: website/public/showcase/th04/index.html:199 msgctxt "page:showcase/th04/index.html" msgid "" "A ring of bullets starts with a short angle calculation. Use REA to inspect " "the original DOS function, then follow its instructions into readable C++." msgstr "一圈彈幕從一段簡短的角度計算開始。用 REA 檢查原始 DOS 函式,再把指令對應到可讀的 C++ 程式碼。" -#: website/public/showcase/th04/index.html:200 +#: website/public/showcase/th04/index.html:204 msgctxt "page:showcase/th04/index.html" msgid "PC-98 · 16-bit DOS · C++ and assembly" msgstr "PC-98·16位DOS · C++和彙編" -#: website/public/showcase/th04/index.html:201 +#: website/public/showcase/th04/index.html:205 msgctxt "page:showcase/th04/index.html" msgid "View the TH04 reconstruction" msgstr "檢視TH04重建" -#: website/public/showcase/th04/index.html:207 +#: website/public/showcase/th04/index.html:211 msgctxt "page:showcase/th04/index.html" msgid "From original instructions to checked source" msgstr "從原始指令到經過驗證的原始碼" @@ -9442,7 +9450,7 @@ msgstr "從原始指令到經過驗證的原始碼" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:209 +#: website/public/showcase/th04/index.html:213 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9457,7 +9465,7 @@ msgstr "{ph0}01 · 原創遊戲{ph1}{ph2}主要。EXE檔案{ph3}{ph4}該 PC-98 #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:216 +#: website/public/showcase/th04/index.html:220 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9475,7 +9483,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:224 +#: website/public/showcase/th04/index.html:228 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9491,7 +9499,7 @@ msgstr "" #. {ph3}: </strong > #. {ph4}: <span class="flow-note" > #. {ph5}: </span > -#: website/public/showcase/th04/index.html:231 +#: website/public/showcase/th04/index.html:235 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9503,21 +9511,21 @@ msgstr "" "位元組匹配{ph3}{ph4}已記錄的編譯器檢查覆蓋了包含這個輔助函式的彈幕生成程式碼。{ph5}" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:240 +#: website/public/showcase/th04/index.html:244 msgctxt "page:showcase/th04/index.html" msgid "" "REA returns the original code and its analysis evidence. The TH04 project " "supplies the maintained source and compiler checks." msgstr "REA 返回原始程式碼和分析證據。TH04 專案提供維護中的原始碼,以及編譯器檢查結果。" -#: website/public/showcase/th04/index.html:248 +#: website/public/showcase/th04/index.html:252 msgctxt "page:showcase/th04/index.html" msgid "In this case study" msgstr "在本個案研究中" #. {ph0}: <a href="#ring"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:250 +#: website/public/showcase/th04/index.html:254 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The bullet ring{ph1}" @@ -9525,7 +9533,7 @@ msgstr "{ph0}子彈環{ph1}" #. {ph0}: <a href="#rea"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:251 +#: website/public/showcase/th04/index.html:255 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}What REA returns{ph1}" @@ -9533,7 +9541,7 @@ msgstr "{ph0}REA 返回什麼{ph1}" #. {ph0}: <a href="#source"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:252 +#: website/public/showcase/th04/index.html:256 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Assembly to C++{ph1}" @@ -9541,7 +9549,7 @@ msgstr "{ph0}彙編到C++{ph1}" #. {ph0}: <a href="#checking"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:253 +#: website/public/showcase/th04/index.html:257 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Checking the source{ph1}" @@ -9549,19 +9557,19 @@ msgstr "{ph0}檢查來源{ph1}" #. {ph0}: <a href="#project"> #. {ph1}: </a> -#: website/public/showcase/th04/index.html:254 +#: website/public/showcase/th04/index.html:258 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}The full project{ph1}" msgstr "{ph0}完整專案{ph1}" -#: website/public/showcase/th04/index.html:259 +#: website/public/showcase/th04/index.html:263 msgctxt "page:showcase/th04/index.html" msgid "How a ring aims at the player" msgstr "環形彈幕如何瞄準玩家" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:260 +#: website/public/showcase/th04/index.html:264 msgctxt "page:showcase/th04/index.html" msgid "" "Elly's attack requests an aimed ring with an initial count of 16. One helper" @@ -9577,16 +9585,16 @@ msgstr "Elly 的攻擊請求一個初始數量為 16 的自機狙環形彈幕。 #. {ph5}: <i> #. {ph6}: </i> #. {ph7}: </span > -#: website/public/showcase/th04/index.html:267 +#: website/public/showcase/th04/index.html:271 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}Your coding agent" msgstr "{ph0}{ph1}{ph2}{ph3}{ph4}{ph5}{ph6}{ph7}你的程式設計助手" -#: website/public/showcase/th04/index.html:272 -#: website/public/showcase/th04/index.html:328 -#: website/public/showcase/th04/index.html:505 -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:276 +#: website/public/showcase/th04/index.html:332 +#: website/public/showcase/th04/index.html:509 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy" msgstr "複製" @@ -9597,7 +9605,7 @@ msgstr "複製" #. {ph3}: </span > #. {ph4}: <span class="terminal-cursor" aria-hidden="true"> #. {ph5}: </span> -#: website/public/showcase/th04/index.html:281 +#: website/public/showcase/th04/index.html:285 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9606,7 +9614,7 @@ msgid "" msgstr "" "{ph0}›{ph1}{ph2}使用REA查詢TH04如何建立一個子彈環並將其瞄準玩家。 解釋計算並顯示程式碼。{ph3}{ph4}{ph5}" -#: website/public/showcase/th04/index.html:290 +#: website/public/showcase/th04/index.html:294 msgctxt "page:showcase/th04/index.html" msgid "" "An example prompt, with the original executable and reconstruction checkout " @@ -9615,7 +9623,7 @@ msgstr "一個示例提示,原始可執行檔案和重建簽出可在本地使 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>0, 16, 32, …, 240</code> -#: website/public/showcase/th04/index.html:294 +#: website/public/showcase/th04/index.html:298 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9628,7 +9636,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <a href="../../assets/figures/th04-bullet-ring.svg" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:314 +#: website/public/showcase/th04/index.html:318 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9636,12 +9644,12 @@ msgid "" "40 and template rotation 0. {ph0}Open figure{ph1}" msgstr "圖中演示還原出的角度計算:子彈數量為 16,玩家方向為 40,模板旋轉角為 0。{ph0}檢視大圖{ph1}" -#: website/public/showcase/th04/index.html:322 +#: website/public/showcase/th04/index.html:326 msgctxt "page:showcase/th04/index.html" msgid "The firing template in the recovered source" msgstr "還原原始碼中的發射模板" -#: website/public/showcase/th04/index.html:327 +#: website/public/showcase/th04/index.html:331 msgctxt "page:showcase/th04/index.html" msgid "Elly's ring attack · source excerpt" msgstr "Elly 的環形攻擊 · 原始碼節選" @@ -9650,7 +9658,7 @@ msgstr "Elly 的環形攻擊 · 原始碼節選" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:342 +#: website/public/showcase/th04/index.html:346 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9658,14 +9666,14 @@ msgid "" "{ph0}Read the attack's source{ph1}." msgstr "這些線在難度和效能調整之前選擇模式。 {ph0}閱讀攻擊的來源{ph1}." -#: website/public/showcase/th04/index.html:353 +#: website/public/showcase/th04/index.html:357 msgctxt "page:showcase/th04/index.html" msgid "What REA returns" msgstr "REA 返回什麼" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>bullet_velocity_and_angle_set()</code> -#: website/public/showcase/th04/index.html:354 +#: website/public/showcase/th04/index.html:358 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9674,20 +9682,20 @@ msgid "" " result explain the pattern." msgstr "我們檢查設定每顆子彈速度和角度的函式 {ph0}。REA 返回指令、虛擬碼和引用,其中三部分解釋了這種彈幕如何生成。" -#: website/public/showcase/th04/index.html:362 +#: website/public/showcase/th04/index.html:366 msgctxt "page:showcase/th04/index.html" msgid "Check the DOS image before reading its code" msgstr "在閱讀其程式碼之前檢查DOS映像" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:383 +#: website/public/showcase/th04/index.html:387 msgctxt "page:showcase/th04/index.html" msgid "" "The check ties the loaded code and relocation records to the supplied " "executable. The path above is shortened for display." msgstr "這項檢查確認載入的程式碼和重定位記錄對應提供的可執行檔案。上方路徑為便於顯示而縮短。" -#: website/public/showcase/th04/index.html:389 +#: website/public/showcase/th04/index.html:393 msgctxt "page:showcase/th04/index.html" msgid "Read the ring's multiply and divide" msgstr "檢視環形彈幕的乘除計算" @@ -9696,7 +9704,7 @@ msgstr "檢視環形彈幕的乘除計算" #. {ph0}: <code>SI</code> #. {ph1}: <code>DS:53AF</code> #. {ph2}: <code>bullet_template.count</code> -#: website/public/showcase/th04/index.html:407 +#: website/public/showcase/th04/index.html:411 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9706,13 +9714,13 @@ msgid "" msgstr "" "{ph0} 儲存子彈索引。移位將它乘以 256,再除以從 {ph1} 讀取的數量。重建原始碼把這個欄位命名為 {ph2}。完整指令序列見下文。" -#: website/public/showcase/th04/index.html:416 +#: website/public/showcase/th04/index.html:420 msgctxt "page:showcase/th04/index.html" msgid "Find where the pattern turns toward the player" msgstr "找到模式轉向玩家的位置" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:437 +#: website/public/showcase/th04/index.html:441 msgctxt "page:showcase/th04/index.html" msgid "" "The instruction operands expose two coordinate differences and a direction " @@ -9723,13 +9731,13 @@ msgstr "" "指令運算元顯示了兩個座標差,以及一個計算方向的輔助函式。它的返回值加到相對環形角度上。原始碼名稱讓這些地址的含義更易讀;REA " "則幫助助手核對地址背後的原始操作。" -#: website/public/showcase/th04/index.html:448 +#: website/public/showcase/th04/index.html:452 msgctxt "page:showcase/th04/index.html" msgid "From assembly to readable C++" msgstr "從彙編到可讀C++" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:449 +#: website/public/showcase/th04/index.html:453 msgctxt "page:showcase/th04/index.html" msgid "" "Select a step to match the original instructions with the angle calculation." @@ -9739,7 +9747,7 @@ msgstr "點選每一步,對照原始指令和角度計算。這份摘要展示 #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:460 +#: website/public/showcase/th04/index.html:464 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}01{ph1} Index" @@ -9747,7 +9755,7 @@ msgstr "{ph0}01{ph1} 索引" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:468 +#: website/public/showcase/th04/index.html:472 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}02{ph1} Space" @@ -9755,7 +9763,7 @@ msgstr "{ph0}02{ph1} 等分" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:476 +#: website/public/showcase/th04/index.html:480 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}03{ph1} Aim" @@ -9763,7 +9771,7 @@ msgstr "{ph0}03{ph1} 瞄準" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:484 +#: website/public/showcase/th04/index.html:488 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}04{ph1} Rotate" @@ -9771,18 +9779,18 @@ msgstr "{ph0}04{ph1} 旋轉" #. {ph0}: <span> #. {ph1}: </span> -#: website/public/showcase/th04/index.html:492 +#: website/public/showcase/th04/index.html:496 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}05{ph1} Store" msgstr "{ph0}05{ph1} 儲存" -#: website/public/showcase/th04/index.html:504 +#: website/public/showcase/th04/index.html:508 msgctxt "page:showcase/th04/index.html" msgid "REA · original 16-bit instructions" msgstr "REA · 原始 16 位指令" -#: website/public/showcase/th04/index.html:538 +#: website/public/showcase/th04/index.html:542 msgctxt "page:showcase/th04/index.html" msgid "Readable C++ · aimed-ring summary" msgstr "可讀 C++ · 自機狙環形彈幕摘要" @@ -9791,7 +9799,7 @@ msgstr "可讀 C++ · 自機狙環形彈幕摘要" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>SI</code> -#: website/public/showcase/th04/index.html:567 +#: website/public/showcase/th04/index.html:571 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9804,7 +9812,7 @@ msgstr "{ph0}01 · 讀取子彈索引。{ph1} 棧引數載入到 {ph2}。在 16 #. {ph1}: </strong> #. {ph2}: <code>SHL AX,8</code> #. {ph3}: <code>IDIV</code> -#: website/public/showcase/th04/index.html:572 +#: website/public/showcase/th04/index.html:576 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9819,7 +9827,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AX</code> -#: website/public/showcase/th04/index.html:579 +#: website/public/showcase/th04/index.html:583 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9834,7 +9842,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>ADD AL,[0x53ad]</code> -#: website/public/showcase/th04/index.html:585 +#: website/public/showcase/th04/index.html:589 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9848,7 +9856,7 @@ msgstr "" #. {ph0}: <strong> #. {ph1}: </strong> #. {ph2}: <code>AL</code> -#: website/public/showcase/th04/index.html:591 +#: website/public/showcase/th04/index.html:595 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9861,7 +9869,7 @@ msgstr "" "後迴繞,與無符號位元組轉換一致。周圍原始碼還會根據這個角度和速率計算速度分量。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:600 +#: website/public/showcase/th04/index.html:604 msgctxt "page:showcase/th04/index.html" msgid "" "The assembly selects the aimed-ring branch, aim calculation and final store." @@ -9869,7 +9877,7 @@ msgid "" "maintained source in the linked project." msgstr "彙編節選展示自機狙環形分支、瞄準計算和最終儲存。上面的 C++ 是便於閱讀的摘要。下方的編譯器檢查針對連結專案中維護的原始碼。" -#: website/public/showcase/th04/index.html:606 +#: website/public/showcase/th04/index.html:610 msgctxt "page:showcase/th04/index.html" msgid "Read the maintained ring and aim source" msgstr "閱讀維護的環和瞄準源" @@ -9886,7 +9894,7 @@ msgstr "閱讀維護的環和瞄準源" #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6" #. > #. {ph5}: </a > -#: website/public/showcase/th04/index.html:635 +#: website/public/showcase/th04/index.html:639 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -9894,37 +9902,37 @@ msgid "" "representation{ph5}" msgstr "{ph0}環宏{ph1} · {ph2}目標和速度源{ph3} · {ph4}角度表示{ph5}" -#: website/public/showcase/th04/index.html:655 +#: website/public/showcase/th04/index.html:659 msgctxt "page:showcase/th04/index.html" msgid "Checking the maintained source" msgstr "檢查維護的源" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:656 +#: website/public/showcase/th04/index.html:660 msgctxt "page:showcase/th04/index.html" msgid "" "The TH04 project's recorded checks compile the bullet-generation code, " "including this helper, with its pinned Turbo C++ 4.0J toolchain." msgstr "TH04 專案記錄的檢查使用指定的 Turbo C++ 4.0J 工具鏈,編譯包含這個輔助函式的彈幕生成程式碼。" -#: website/public/showcase/th04/index.html:663 +#: website/public/showcase/th04/index.html:667 msgctxt "page:showcase/th04/index.html" msgid "2,139 matching bytes" msgstr "2,139匹配位元組" -#: website/public/showcase/th04/index.html:664 +#: website/public/showcase/th04/index.html:668 msgctxt "page:showcase/th04/index.html" msgid "" "The compiled bullet-generation code matches a 2,139-byte section of the " "original executable." msgstr "編譯的子彈生成程式碼與原始可執行檔案的2,139位元組部分相匹配。" -#: website/public/showcase/th04/index.html:670 +#: website/public/showcase/th04/index.html:674 msgctxt "page:showcase/th04/index.html" msgid "Two clean builds" msgstr "兩個乾淨的構建" -#: website/public/showcase/th04/index.html:671 +#: website/public/showcase/th04/index.html:675 msgctxt "page:showcase/th04/index.html" msgid "" "Two separate builds produce the same matching bytes. The recorded input " @@ -9935,66 +9943,66 @@ msgstr "兩個單獨的構建產生相同的匹配位元組。 記錄的輸入 #. href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation" #. > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:677 +#: website/public/showcase/th04/index.html:681 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Recorded on 3 October 2026. {ph0}Read the compiler checks{ph1}." msgstr "2026年10月3日錄得。 {ph0}閱讀編譯器檢查{ph1}." -#: website/public/showcase/th04/index.html:685 +#: website/public/showcase/th04/index.html:689 msgctxt "page:showcase/th04/index.html" msgid "Target identity and analysis scope" msgstr "目標身份和分析範圍" -#: website/public/showcase/th04/index.html:690 +#: website/public/showcase/th04/index.html:694 msgctxt "page:showcase/th04/index.html" msgid "Original target" msgstr "原始目標" #. {ph0}: <code>MAIN.EXE</code> -#: website/public/showcase/th04/index.html:691 +#: website/public/showcase/th04/index.html:695 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, 156,258 bytes, DOS MZ" msgstr "{ph0},156,258位元組,DOS MZ" -#: website/public/showcase/th04/index.html:694 +#: website/public/showcase/th04/index.html:698 msgctxt "page:showcase/th04/index.html" msgid "Helper entry" msgstr "傭工入境" #. {ph0}: <code>0x2cfc8</code> -#: website/public/showcase/th04/index.html:695 +#: website/public/showcase/th04/index.html:699 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0} in REA's loaded image" msgstr "{ph0} 在REA的載入影象" -#: website/public/showcase/th04/index.html:698 +#: website/public/showcase/th04/index.html:702 msgctxt "page:showcase/th04/index.html" msgid "Original file offset" msgstr "原始檔案偏移量" #. {ph0}: <code>0x1e7c8</code> #. {ph1}: <code>address_to_file_offset</code> -#: website/public/showcase/th04/index.html:699 +#: website/public/showcase/th04/index.html:703 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}, returned by {ph1}" msgstr "{ph0},返回 {ph1}" -#: website/public/showcase/th04/index.html:705 +#: website/public/showcase/th04/index.html:709 msgctxt "page:showcase/th04/index.html" msgid "Recorded code inspection" msgstr "記錄程式碼檢查" -#: website/public/showcase/th04/index.html:706 +#: website/public/showcase/th04/index.html:710 msgctxt "page:showcase/th04/index.html" msgid "REA 4.1.0 · 7 October 2026" msgstr "REA4.1.0*2026年10月7日" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:711 +#: website/public/showcase/th04/index.html:715 msgctxt "page:showcase/th04/index.html" msgid "" "Compiler checks cover the complete bullet-add code section, including this " @@ -10003,7 +10011,7 @@ msgstr "編譯器檢查覆蓋完整的彈幕新增程式碼段,包括這個輔 # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>0x1000</code> -#: website/public/showcase/th04/index.html:716 +#: website/public/showcase/th04/index.html:720 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10017,7 +10025,7 @@ msgstr "" # Reviewed for clear case-study reasoning and evidence. #. {ph0}: <code>0d72e980</code> -#: website/public/showcase/th04/index.html:723 +#: website/public/showcase/th04/index.html:727 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10031,7 +10039,7 @@ msgstr "" "對同一原始目標的檢查。遊戲檔案的身份由儲存庫清單確定,獨立原始轉儲的來源仍未確定。" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:731 +#: website/public/showcase/th04/index.html:735 msgctxt "page:showcase/th04/index.html" msgid "" "The figure illustrates the angle calculation. Full-game controls, timing and" @@ -10039,13 +10047,13 @@ msgid "" "project." msgstr "圖中說明的是角度計算。完整遊戲的控制、時序和 PC-98 硬體行為,在重建專案中有各自的執行時檢查。" -#: website/public/showcase/th04/index.html:740 +#: website/public/showcase/th04/index.html:744 msgctxt "page:showcase/th04/index.html" msgid "The full TH04 reconstruction" msgstr "完整的TH04重建" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:741 +#: website/public/showcase/th04/index.html:745 msgctxt "page:showcase/th04/index.html" msgid "" "The project builds the game's four DOS products from maintained C++ and " @@ -10055,7 +10063,7 @@ msgstr "專案用維護中的 C++ 和彙編構建遊戲的四個 DOS 程式。 #. {ph0}: <a class="text-link" href="https://github.com/N0zoM1z0/th04" > #. {ph1}: </a > -#: website/public/showcase/th04/index.html:747 +#: website/public/showcase/th04/index.html:751 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "{ph0}Explore the TH04 repository{ph1}" @@ -10067,7 +10075,7 @@ msgstr "{ph0}探索 TH04 程式碼儲存庫{ph1}" #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:753 +#: website/public/showcase/th04/index.html:757 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10081,7 +10089,7 @@ msgstr "{ph0}子彈生成源{ph1}{ph2}完整的助手,其他模式型別和模 #. {ph1}: </a > #. {ph2}: <span > #. {ph3}: </span > -#: website/public/showcase/th04/index.html:762 +#: website/public/showcase/th04/index.html:766 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10095,7 +10103,7 @@ msgstr "{ph0}DOS構建和執行指南{ph1}{ph2}構建原始碼並在專案的PC- #. {ph1}: </a > #. {ph2}: <span> #. {ph3}: </span> -#: website/public/showcase/th04/index.html:771 +#: website/public/showcase/th04/index.html:775 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "" @@ -10117,29 +10125,29 @@ msgid "" "player." msgstr "用 REA 檢查 TH04 的原始 16 位 DOS 程式碼。對照彙編與還原的 C++,瞭解環形彈幕如何等分方向並瞄準玩家。" -#: website/public/showcase/th04/index.html:247 +#: website/public/showcase/th04/index.html:251 msgctxt "page:showcase/th04/index.html" msgid "On this page" msgstr "在本頁" -#: website/public/showcase/th04/index.html:257 +#: website/public/showcase/th04/index.html:261 msgctxt "page:showcase/th04/index.html" msgid "TH04 bullet-pattern case study" msgstr "TH04子彈型案例研究" -#: website/public/showcase/th04/index.html:272 +#: website/public/showcase/th04/index.html:276 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 example prompt" msgstr "複製TH04示例提示" -#: website/public/showcase/th04/index.html:300 +#: website/public/showcase/th04/index.html:304 msgctxt "page:showcase/th04/index.html" msgid "" "TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens" msgstr "TH04固定和瞄準子彈環;在較小的螢幕上水平滾動" # Reviewed for clear case-study reasoning and evidence. -#: website/public/showcase/th04/index.html:306 +#: website/public/showcase/th04/index.html:310 msgctxt "page:showcase/th04/index.html" msgid "" "Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. " @@ -10150,27 +10158,27 @@ msgstr "" "兩幅圖展示 16 顆子彈的環。固定環從角度 0 開始。加上玩家方向 40 後,每個方向都旋轉相同角度,高亮的第一顆子彈指向玩家。兩者都保持 16 " "個角度單位的間距,即 22.5 度。" -#: website/public/showcase/th04/index.html:328 +#: website/public/showcase/th04/index.html:332 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 firing template" msgstr "複製 TH04 發射範本" -#: website/public/showcase/th04/index.html:455 +#: website/public/showcase/th04/index.html:459 msgctxt "page:showcase/th04/index.html" msgid "Follow the TH04 aimed-ring calculation" msgstr "按照TH04-環計算" -#: website/public/showcase/th04/index.html:505 +#: website/public/showcase/th04/index.html:509 msgctxt "page:showcase/th04/index.html" msgid "Copy TH04 assembly excerpt" msgstr "複製TH04彙編摘錄" -#: website/public/showcase/th04/index.html:539 +#: website/public/showcase/th04/index.html:543 msgctxt "page:showcase/th04/index.html" msgid "Copy readable aimed-ring calculation" msgstr "複製可讀瞄準環計算" -#: website/public/showcase/th04/index.html:796 +#: website/public/showcase/th04/index.html:800 msgctxt "page:showcase/th04/index.html" msgid "Back to top" msgstr "回到頂部" @@ -10278,14 +10286,14 @@ msgctxt "runtime" msgid "Fixed speed: {speed}." msgstr "固定速度: {speed}." -#: website/public/assets/dino-demo.js:251 +#: website/public/assets/dino-demo.js:249 msgctxt "runtime" msgid "" "Replayed the recovered rule. All four values match the controlled original-" "game check when rounded to three decimals." msgstr "重放了恢復的規則。 當四捨五入到三位小數時,所有四個值都匹配受控的原始遊戲檢查。" -#: website/public/assets/dino-demo.js:254 +#: website/public/assets/dino-demo.js:252 msgctxt "runtime" msgid "" "The replay differs from the recorded original-game values. Compare the speed" @@ -10633,592 +10641,600 @@ msgctxt "figure:th04-bullet-ring.svg" msgid "Same spacing: 256 ÷ 16 = 16 angle units = 22.5°" msgstr "相同間距:256÷16=16角度單位=22.5°" -#: website/public/blog/index.html:119 -#: website/public/blog/touhou-reconstruction/index.html:119 -#: website/public/examples/dino-lab/index.html:120 -#: website/public/faq/index.html:119 -#: website/public/first-investigation/index.html:119 -#: website/public/get-started/index.html:119 -#: website/public/guides/browser/index.html:119 -#: website/public/guides/index.html:119 -#: website/public/guides/javascript/index.html:119 -#: website/public/guides/native/index.html:119 website/public/index.html:121 -#: website/public/showcase/aegis/index.html:120 -#: website/public/showcase/ctf/index.html:119 -#: website/public/showcase/dx-ball/index.html:119 -#: website/public/showcase/index.html:119 -#: website/public/showcase/notion/index.html:119 -#: website/public/showcase/th04/index.html:119 +#: website/public/blog/index.html:114 +#: website/public/blog/reverse-engineering-models/index.html:114 +#: website/public/blog/touhou-reconstruction/index.html:114 +#: website/public/examples/dino-lab/index.html:115 +#: website/public/faq/index.html:114 +#: website/public/first-investigation/index.html:114 +#: website/public/get-started/index.html:114 +#: website/public/guides/browser/index.html:114 +#: website/public/guides/index.html:114 +#: website/public/guides/javascript/index.html:114 +#: website/public/guides/native/index.html:114 website/public/index.html:116 +#: website/public/showcase/aegis/index.html:115 +#: website/public/showcase/ctf/index.html:114 +#: website/public/showcase/dx-ball/index.html:114 +#: website/public/showcase/index.html:114 +#: website/public/showcase/notion/index.html:114 +#: website/public/showcase/th04/index.html:114 msgctxt "shared" msgid "Showcases" msgstr "案例展示" -#: website/public/blog/index.html:120 -#: website/public/blog/touhou-reconstruction/index.html:120 -#: website/public/examples/dino-lab/index.html:121 -#: website/public/faq/index.html:120 -#: website/public/first-investigation/index.html:120 -#: website/public/get-started/index.html:120 -#: website/public/guides/browser/index.html:120 -#: website/public/guides/index.html:120 -#: website/public/guides/javascript/index.html:120 -#: website/public/guides/native/index.html:120 website/public/index.html:122 -#: website/public/showcase/aegis/index.html:121 -#: website/public/showcase/ctf/index.html:120 -#: website/public/showcase/dx-ball/index.html:120 -#: website/public/showcase/index.html:120 -#: website/public/showcase/notion/index.html:120 -#: website/public/showcase/th04/index.html:120 +#: website/public/blog/index.html:115 +#: website/public/blog/reverse-engineering-models/index.html:115 +#: website/public/blog/touhou-reconstruction/index.html:115 +#: website/public/examples/dino-lab/index.html:116 +#: website/public/faq/index.html:115 +#: website/public/first-investigation/index.html:115 +#: website/public/get-started/index.html:115 +#: website/public/guides/browser/index.html:115 +#: website/public/guides/index.html:115 +#: website/public/guides/javascript/index.html:115 +#: website/public/guides/native/index.html:115 website/public/index.html:117 +#: website/public/showcase/aegis/index.html:116 +#: website/public/showcase/ctf/index.html:115 +#: website/public/showcase/dx-ball/index.html:115 +#: website/public/showcase/index.html:115 +#: website/public/showcase/notion/index.html:115 +#: website/public/showcase/th04/index.html:115 msgctxt "shared" msgid "Blog" msgstr "部落格" -#: website/public/blog/index.html:118 -#: website/public/blog/touhou-reconstruction/index.html:118 -#: website/public/examples/dino-lab/index.html:119 -#: website/public/faq/index.html:118 -#: website/public/first-investigation/index.html:118 -#: website/public/get-started/index.html:118 -#: website/public/guides/browser/index.html:118 -#: website/public/guides/index.html:118 -#: website/public/guides/javascript/index.html:118 -#: website/public/guides/native/index.html:118 website/public/index.html:120 -#: website/public/showcase/aegis/index.html:119 -#: website/public/showcase/ctf/index.html:118 -#: website/public/showcase/dx-ball/index.html:118 -#: website/public/showcase/index.html:118 -#: website/public/showcase/notion/index.html:118 -#: website/public/showcase/th04/index.html:118 +#: website/public/blog/index.html:113 +#: website/public/blog/reverse-engineering-models/index.html:113 +#: website/public/blog/touhou-reconstruction/index.html:113 +#: website/public/examples/dino-lab/index.html:114 +#: website/public/faq/index.html:113 +#: website/public/first-investigation/index.html:113 +#: website/public/get-started/index.html:113 +#: website/public/guides/browser/index.html:113 +#: website/public/guides/index.html:113 +#: website/public/guides/javascript/index.html:113 +#: website/public/guides/native/index.html:113 website/public/index.html:115 +#: website/public/showcase/aegis/index.html:114 +#: website/public/showcase/ctf/index.html:113 +#: website/public/showcase/dx-ball/index.html:113 +#: website/public/showcase/index.html:113 +#: website/public/showcase/notion/index.html:113 +#: website/public/showcase/th04/index.html:113 msgctxt "shared" msgid "Get started" msgstr "開始使用" -#: website/public/blog/index.html:121 -#: website/public/blog/touhou-reconstruction/index.html:121 -#: website/public/examples/dino-lab/index.html:122 -#: website/public/faq/index.html:121 -#: website/public/first-investigation/index.html:121 -#: website/public/get-started/index.html:121 -#: website/public/guides/browser/index.html:121 -#: website/public/guides/index.html:121 -#: website/public/guides/javascript/index.html:121 -#: website/public/guides/native/index.html:121 website/public/index.html:123 -#: website/public/showcase/aegis/index.html:122 -#: website/public/showcase/ctf/index.html:121 -#: website/public/showcase/dx-ball/index.html:121 -#: website/public/showcase/index.html:121 -#: website/public/showcase/notion/index.html:121 -#: website/public/showcase/th04/index.html:121 +#: website/public/blog/index.html:116 +#: website/public/blog/reverse-engineering-models/index.html:116 +#: website/public/blog/touhou-reconstruction/index.html:116 +#: website/public/examples/dino-lab/index.html:117 +#: website/public/faq/index.html:116 +#: website/public/first-investigation/index.html:116 +#: website/public/get-started/index.html:116 +#: website/public/guides/browser/index.html:116 +#: website/public/guides/index.html:116 +#: website/public/guides/javascript/index.html:116 +#: website/public/guides/native/index.html:116 website/public/index.html:118 +#: website/public/showcase/aegis/index.html:117 +#: website/public/showcase/ctf/index.html:116 +#: website/public/showcase/dx-ball/index.html:116 +#: website/public/showcase/index.html:116 +#: website/public/showcase/notion/index.html:116 +#: website/public/showcase/th04/index.html:116 msgctxt "shared" msgid "Guides" msgstr "指南" -#: website/public/blog/index.html:218 -#: website/public/blog/touhou-reconstruction/index.html:1068 -#: website/public/examples/dino-lab/index.html:463 -#: website/public/faq/index.html:561 -#: website/public/first-investigation/index.html:511 -#: website/public/get-started/index.html:870 -#: website/public/guides/browser/index.html:486 -#: website/public/guides/index.html:270 -#: website/public/guides/javascript/index.html:491 -#: website/public/guides/native/index.html:497 website/public/index.html:1179 -#: website/public/showcase/aegis/index.html:796 -#: website/public/showcase/ctf/index.html:765 -#: website/public/showcase/dx-ball/index.html:773 -#: website/public/showcase/index.html:305 -#: website/public/showcase/notion/index.html:619 -#: website/public/showcase/th04/index.html:788 +#: website/public/blog/index.html:236 +#: website/public/blog/reverse-engineering-models/index.html:875 +#: website/public/blog/touhou-reconstruction/index.html:1072 +#: website/public/examples/dino-lab/index.html:467 +#: website/public/faq/index.html:565 +#: website/public/first-investigation/index.html:515 +#: website/public/get-started/index.html:874 +#: website/public/guides/browser/index.html:499 +#: website/public/guides/index.html:274 +#: website/public/guides/javascript/index.html:495 +#: website/public/guides/native/index.html:501 website/public/index.html:1183 +#: website/public/showcase/aegis/index.html:800 +#: website/public/showcase/ctf/index.html:769 +#: website/public/showcase/dx-ball/index.html:777 +#: website/public/showcase/index.html:309 +#: website/public/showcase/notion/index.html:623 +#: website/public/showcase/th04/index.html:792 msgctxt "shared" msgid "Source" msgstr "原始碼" -#: website/public/blog/index.html:219 -#: website/public/blog/touhou-reconstruction/index.html:1069 -#: website/public/examples/dino-lab/index.html:464 -#: website/public/faq/index.html:562 -#: website/public/first-investigation/index.html:512 -#: website/public/get-started/index.html:871 -#: website/public/guides/browser/index.html:487 -#: website/public/guides/index.html:271 -#: website/public/guides/javascript/index.html:492 -#: website/public/guides/native/index.html:498 website/public/index.html:1180 -#: website/public/showcase/aegis/index.html:797 -#: website/public/showcase/ctf/index.html:766 -#: website/public/showcase/dx-ball/index.html:774 -#: website/public/showcase/index.html:306 -#: website/public/showcase/notion/index.html:620 -#: website/public/showcase/th04/index.html:789 +#: website/public/blog/index.html:237 +#: website/public/blog/reverse-engineering-models/index.html:876 +#: website/public/blog/touhou-reconstruction/index.html:1073 +#: website/public/examples/dino-lab/index.html:468 +#: website/public/faq/index.html:566 +#: website/public/first-investigation/index.html:516 +#: website/public/get-started/index.html:875 +#: website/public/guides/browser/index.html:500 +#: website/public/guides/index.html:275 +#: website/public/guides/javascript/index.html:496 +#: website/public/guides/native/index.html:502 website/public/index.html:1184 +#: website/public/showcase/aegis/index.html:801 +#: website/public/showcase/ctf/index.html:770 +#: website/public/showcase/dx-ball/index.html:778 +#: website/public/showcase/index.html:310 +#: website/public/showcase/notion/index.html:624 +#: website/public/showcase/th04/index.html:793 msgctxt "shared" msgid "MIT license" msgstr "MIT 許可證" -#: website/public/blog/index.html:220 -#: website/public/blog/touhou-reconstruction/index.html:1070 -#: website/public/examples/dino-lab/index.html:465 -#: website/public/faq/index.html:563 -#: website/public/first-investigation/index.html:513 -#: website/public/get-started/index.html:872 -#: website/public/guides/browser/index.html:488 -#: website/public/guides/index.html:272 -#: website/public/guides/javascript/index.html:493 -#: website/public/guides/native/index.html:499 website/public/index.html:1181 -#: website/public/showcase/aegis/index.html:798 -#: website/public/showcase/ctf/index.html:767 -#: website/public/showcase/dx-ball/index.html:775 -#: website/public/showcase/index.html:307 -#: website/public/showcase/notion/index.html:621 -#: website/public/showcase/th04/index.html:790 +#: website/public/blog/index.html:238 +#: website/public/blog/reverse-engineering-models/index.html:877 +#: website/public/blog/touhou-reconstruction/index.html:1074 +#: website/public/examples/dino-lab/index.html:469 +#: website/public/faq/index.html:567 +#: website/public/first-investigation/index.html:517 +#: website/public/get-started/index.html:876 +#: website/public/guides/browser/index.html:501 +#: website/public/guides/index.html:276 +#: website/public/guides/javascript/index.html:497 +#: website/public/guides/native/index.html:503 website/public/index.html:1185 +#: website/public/showcase/aegis/index.html:802 +#: website/public/showcase/ctf/index.html:771 +#: website/public/showcase/dx-ball/index.html:779 +#: website/public/showcase/index.html:311 +#: website/public/showcase/notion/index.html:625 +#: website/public/showcase/th04/index.html:794 msgctxt "shared" msgid "Join the community" msgstr "加入社群" -#: website/public/blog/index.html:221 -#: website/public/blog/touhou-reconstruction/index.html:1071 -#: website/public/examples/dino-lab/index.html:466 -#: website/public/faq/index.html:564 -#: website/public/first-investigation/index.html:514 -#: website/public/get-started/index.html:873 -#: website/public/guides/browser/index.html:489 -#: website/public/guides/index.html:273 -#: website/public/guides/javascript/index.html:494 -#: website/public/guides/native/index.html:500 website/public/index.html:1182 -#: website/public/showcase/aegis/index.html:799 -#: website/public/showcase/ctf/index.html:768 -#: website/public/showcase/dx-ball/index.html:776 -#: website/public/showcase/index.html:308 -#: website/public/showcase/notion/index.html:622 -#: website/public/showcase/th04/index.html:791 +#: website/public/blog/index.html:239 +#: website/public/blog/reverse-engineering-models/index.html:878 +#: website/public/blog/touhou-reconstruction/index.html:1075 +#: website/public/examples/dino-lab/index.html:470 +#: website/public/faq/index.html:568 +#: website/public/first-investigation/index.html:518 +#: website/public/get-started/index.html:877 +#: website/public/guides/browser/index.html:502 +#: website/public/guides/index.html:277 +#: website/public/guides/javascript/index.html:498 +#: website/public/guides/native/index.html:504 website/public/index.html:1186 +#: website/public/showcase/aegis/index.html:803 +#: website/public/showcase/ctf/index.html:772 +#: website/public/showcase/dx-ball/index.html:780 +#: website/public/showcase/index.html:312 +#: website/public/showcase/notion/index.html:626 +#: website/public/showcase/th04/index.html:795 msgctxt "shared" msgid "Follow us on X" msgstr "在 X 上關注我們" -#: website/public/examples/dino-lab/index.html:302 +#: website/public/examples/dino-lab/index.html:306 msgctxt "page:examples/dino-lab/index.html" msgid "REA · selected script source" msgstr "REA · 選定指令碼源" -#: website/public/first-investigation/index.html:370 +#: website/public/first-investigation/index.html:374 msgctxt "page:first-investigation/index.html" msgid "Source" msgstr "原始碼" -#: website/public/first-investigation/index.html:424 +#: website/public/first-investigation/index.html:428 msgctxt "page:first-investigation/index.html" msgid "Expected formatter output" msgstr "預期格式化程式輸出" -#: website/public/guides/index.html:215 +#: website/public/guides/index.html:219 msgctxt "page:guides/index.html" msgid "Instructions" msgstr "指令" -#: website/public/guides/index.html:216 +#: website/public/guides/index.html:220 msgctxt "page:guides/index.html" msgid "Caller" msgstr "呼叫方" -#: website/public/guides/index.html:217 +#: website/public/guides/index.html:221 msgctxt "page:guides/index.html" msgid "Constants" msgstr "常量" -#: website/public/guides/index.html:218 +#: website/public/guides/index.html:222 msgctxt "page:guides/index.html" msgid "C function" msgstr "C函式" -#: website/public/guides/index.html:233 +#: website/public/guides/index.html:237 msgctxt "page:guides/index.html" msgid "Button" msgstr "按鈕" -#: website/public/guides/index.html:234 +#: website/public/guides/index.html:238 msgctxt "page:guides/index.html" msgid "Preload API" msgstr "預載入API" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "IPC" msgstr "IPC" -#: website/public/guides/index.html:235 +#: website/public/guides/index.html:239 msgctxt "page:guides/index.html" msgid "CSV file" msgstr "CSV檔案" -#: website/public/guides/index.html:255 +#: website/public/guides/index.html:259 msgctxt "page:guides/index.html" msgid "Your click" msgstr "你的點選" -#: website/public/guides/index.html:256 +#: website/public/guides/index.html:260 msgctxt "page:guides/index.html" msgid "Captured request" msgstr "捕獲的請求" -#: website/public/guides/index.html:257 +#: website/public/guides/index.html:261 msgctxt "page:guides/index.html" msgid "Export script" msgstr "匯出指令碼" -#: website/public/guides/javascript/index.html:353 +#: website/public/guides/javascript/index.html:357 msgctxt "page:guides/javascript/index.html" msgid "REA result · summary.ipc excerpt" msgstr "REA 結果 · summary.ipc 摘錄" -#: website/public/guides/native/index.html:380 +#: website/public/guides/native/index.html:384 msgctxt "page:guides/native/index.html" msgid "REA instruction excerpt · 0x406409" msgstr "REA指令摘錄·0x406409" -#: website/public/guides/native/index.html:394 +#: website/public/guides/native/index.html:398 msgctxt "page:guides/native/index.html" msgid "REA caller excerpt · 0x411f5b" msgstr "REA呼叫方摘錄 · 0x411f5b" -#: website/public/guides/native/index.html:408 +#: website/public/guides/native/index.html:412 msgctxt "page:guides/native/index.html" msgid "REA byte results · interpreted as little-endian doubles" msgstr "REA位元組結果 · 解釋為little-endian雙精度浮點數" -#: website/public/guides/native/index.html:425 +#: website/public/guides/native/index.html:429 msgctxt "page:guides/native/index.html" msgid "Recovered C · excerpt" msgstr "恢復C · 摘錄" -#: website/public/index.html:228 +#: website/public/index.html:232 msgctxt "page:index.html" msgid "See how REA works ↓" msgstr "看看 REA 如何工作 ↓" -#: website/public/index.html:235 +#: website/public/index.html:239 msgctxt "page:index.html" msgid "Showcases →" msgstr "檢視案例 →" -#: website/public/index.html:745 +#: website/public/index.html:749 msgctxt "page:index.html" msgid "Selected settings from the inspected script" msgstr "實際指令碼中的設定節選" -#: website/public/index.html:917 +#: website/public/index.html:921 msgctxt "page:index.html" msgid "Readable summary of the % handler" msgstr "% 處理函式的可讀摘要" -#: website/public/index.html:981 +#: website/public/index.html:985 msgctxt "page:index.html" msgid "REA · selected original instructions" msgstr "REA · 原始指令節選" -#: website/public/index.html:992 +#: website/public/index.html:996 msgctxt "page:index.html" msgid "Operator IDs · Microsoft’s source" msgstr "運算子 ID · Microsoft 原始碼" -#: website/public/index.html:1166 +#: website/public/index.html:1170 msgctxt "page:index.html" msgid "Follow @reatools on X" msgstr "在X上關注@reatools" -#: website/public/showcase/aegis/index.html:395 -#: website/public/showcase/aegis/index.html:427 +#: website/public/showcase/aegis/index.html:399 +#: website/public/showcase/aegis/index.html:431 msgctxt "page:showcase/aegis/index.html" msgid "Agent → REA" msgstr "程式設計助手→ REA" -#: website/public/showcase/aegis/index.html:405 +#: website/public/showcase/aegis/index.html:409 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · selected results" msgstr "REA →程式設計助手 · 選定結果" -#: website/public/showcase/aegis/index.html:441 +#: website/public/showcase/aegis/index.html:445 msgctxt "page:showcase/aegis/index.html" msgid "REA → agent · methods and callers" msgstr "REA →程式設計助手·方法和呼叫者" -#: website/public/showcase/aegis/index.html:511 +#: website/public/showcase/aegis/index.html:515 msgctxt "page:showcase/aegis/index.html" msgid "REA · selected decompiled Java" msgstr "REA · 精選反編譯Java" -#: website/public/showcase/aegis/index.html:541 +#: website/public/showcase/aegis/index.html:545 msgctxt "page:showcase/aegis/index.html" msgid "Readable summary · agent's interpretation" msgstr "可讀摘要 · 程式設計助手解釋" -#: website/public/showcase/aegis/index.html:596 +#: website/public/showcase/aegis/index.html:600 msgctxt "page:showcase/aegis/index.html" msgid "REA · generateOTP, complete body" msgstr "REA · generateOTP 完整函式體" -#: website/public/showcase/aegis/index.html:714 +#: website/public/showcase/aegis/index.html:718 msgctxt "page:showcase/aegis/index.html" msgid "Download Aegis APK" msgstr "下載Aegis APK" -#: website/public/showcase/aegis/index.html:718 +#: website/public/showcase/aegis/index.html:722 msgctxt "page:showcase/aegis/index.html" msgid "Download Android analysis provider" msgstr "下載 Android 分析後端" -#: website/public/showcase/ctf/index.html:298 -#: website/public/showcase/ctf/index.html:334 +#: website/public/showcase/ctf/index.html:302 +#: website/public/showcase/ctf/index.html:338 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA" msgstr "程式設計助手→ REA" -#: website/public/showcase/ctf/index.html:314 +#: website/public/showcase/ctf/index.html:318 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected results" msgstr "REA →程式設計助手 · 選定結果" -#: website/public/showcase/ctf/index.html:346 +#: website/public/showcase/ctf/index.html:350 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · selected instructions" msgstr "REA →程式設計助手 · 選擇說明" -#: website/public/showcase/ctf/index.html:409 +#: website/public/showcase/ctf/index.html:413 msgctxt "page:showcase/ctf/index.html" msgid "Agent → REA · read_bytes" msgstr "程式設計助手→ REA · read_bytes" -#: website/public/showcase/ctf/index.html:416 +#: website/public/showcase/ctf/index.html:420 msgctxt "page:showcase/ctf/index.html" msgid "REA → agent · seventh entries" msgstr "REA →程式設計助手·第七項" -#: website/public/showcase/ctf/index.html:684 +#: website/public/showcase/ctf/index.html:688 msgctxt "page:showcase/ctf/index.html" msgid "Original executable · SHA-256" msgstr "原始可執行檔案 · SHA-256" -#: website/public/showcase/ctf/index.html:720 +#: website/public/showcase/ctf/index.html:724 msgctxt "page:showcase/ctf/index.html" msgid "Download the original challenge" msgstr "下載原始挑戰" -#: website/public/showcase/ctf/index.html:724 +#: website/public/showcase/ctf/index.html:728 msgctxt "page:showcase/ctf/index.html" msgid "Download solver" msgstr "下載求解器" -#: website/public/showcase/dx-ball/index.html:325 +#: website/public/showcase/dx-ball/index.html:329 msgctxt "page:showcase/dx-ball/index.html" msgid "REA result · pseudocode excerpt" msgstr "REA結果 · 虛擬碼摘錄" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/dx-ball/index.html:348 -#: website/public/showcase/dx-ball/index.html:372 +#: website/public/showcase/dx-ball/index.html:352 +#: website/public/showcase/dx-ball/index.html:376 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · {ph0}" msgstr "程式設計助手→ REA · {ph0}" -#: website/public/showcase/dx-ball/index.html:354 +#: website/public/showcase/dx-ball/index.html:358 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA →程式設計助手·指令摘錄" -#: website/public/showcase/dx-ball/index.html:378 +#: website/public/showcase/dx-ball/index.html:382 msgctxt "page:showcase/dx-ball/index.html" msgid "REA → agent · caller excerpt" msgstr "REA →程式設計助手·呼叫方摘錄" # Reviewed for clear terminology and preserved evidence. #. {ph0}: <code>read_bytes</code> -#: website/public/showcase/dx-ball/index.html:396 +#: website/public/showcase/dx-ball/index.html:400 #, python-brace-format msgctxt "page:showcase/dx-ball/index.html" msgid "Agent → REA · two {ph0} requests" msgstr "助手 → REA · 兩次 {ph0} 請求" -#: website/public/showcase/dx-ball/index.html:406 +#: website/public/showcase/dx-ball/index.html:410 msgctxt "page:showcase/dx-ball/index.html" msgid "REA byte results · decoded as doubles" msgstr "REA 位元組結果 · 雙精度浮點數解碼" -#: website/public/showcase/dx-ball/index.html:759 +#: website/public/showcase/dx-ball/index.html:763 msgctxt "page:showcase/dx-ball/index.html" msgid "Start with your own target" msgstr "從你自己的目標開始" -#: website/public/showcase/index.html:208 +#: website/public/showcase/index.html:212 msgctxt "page:showcase/index.html" msgid "APK" msgstr "APK" -#: website/public/showcase/index.html:209 +#: website/public/showcase/index.html:213 msgctxt "page:showcase/index.html" msgid "Generating code" msgstr "生成驗證碼" -#: website/public/showcase/index.html:210 +#: website/public/showcase/index.html:214 msgctxt "page:showcase/index.html" msgid "Recovered rule" msgstr "還原的規則" -#: website/public/showcase/index.html:211 +#: website/public/showcase/index.html:215 msgctxt "page:showcase/index.html" msgid "Adjustable clock" msgstr "可調時鐘" -#: website/public/showcase/index.html:226 +#: website/public/showcase/index.html:230 msgctxt "page:showcase/index.html" msgid "Binary" msgstr "二進位制" -#: website/public/showcase/index.html:227 +#: website/public/showcase/index.html:231 msgctxt "page:showcase/index.html" msgid "Checking code" msgstr "檢查 flag 的程式碼" -#: website/public/showcase/index.html:228 +#: website/public/showcase/index.html:232 msgctxt "page:showcase/index.html" msgid "Equations" msgstr "方程" -#: website/public/showcase/index.html:229 +#: website/public/showcase/index.html:233 msgctxt "page:showcase/index.html" msgid "Correct!" msgstr "正確!" -#: website/public/showcase/index.html:245 +#: website/public/showcase/index.html:249 msgctxt "page:showcase/index.html" msgid "Executable" msgstr "可執行檔案" -#: website/public/showcase/index.html:246 +#: website/public/showcase/index.html:250 msgctxt "page:showcase/index.html" msgid "REA findings" msgstr "REA調查結果" -#: website/public/showcase/index.html:247 +#: website/public/showcase/index.html:251 msgctxt "page:showcase/index.html" msgid "Recovered C" msgstr "還原的 C 程式碼" -#: website/public/showcase/index.html:248 +#: website/public/showcase/index.html:252 msgctxt "page:showcase/index.html" msgid "Validation" msgstr "驗證" -#: website/public/showcase/index.html:263 +#: website/public/showcase/index.html:267 msgctxt "page:showcase/index.html" msgid "Packaged app" msgstr "打包應用程式" -#: website/public/showcase/index.html:264 +#: website/public/showcase/index.html:268 msgctxt "page:showcase/index.html" msgid "Exposed API" msgstr "公開API" -#: website/public/showcase/index.html:265 +#: website/public/showcase/index.html:269 msgctxt "page:showcase/index.html" msgid "IPC wrappers" msgstr "IPC包裝器" -#: website/public/showcase/index.html:266 +#: website/public/showcase/index.html:270 msgctxt "page:showcase/index.html" msgid "Clipboard" msgstr "剪貼簿" -#: website/public/showcase/index.html:281 +#: website/public/showcase/index.html:285 msgctxt "page:showcase/index.html" msgid "Original DOS code" msgstr "原始DOS程式碼" -#: website/public/showcase/index.html:282 +#: website/public/showcase/index.html:286 msgctxt "page:showcase/index.html" msgid "REA instructions" msgstr "REA 指令" -#: website/public/showcase/index.html:283 +#: website/public/showcase/index.html:287 msgctxt "page:showcase/index.html" msgid "Angle calculation" msgstr "角度計算" -#: website/public/showcase/index.html:284 +#: website/public/showcase/index.html:288 msgctxt "page:showcase/index.html" msgid "Bullet ring" msgstr "環形彈幕" -#: website/public/showcase/notion/index.html:300 +#: website/public/showcase/notion/index.html:304 msgctxt "page:showcase/notion/index.html" msgid "Exposed page API" msgstr "公開頁面API" -#: website/public/showcase/notion/index.html:306 +#: website/public/showcase/notion/index.html:310 msgctxt "page:showcase/notion/index.html" msgid "Renderer IPC call" msgstr "渲染器IPC呼叫" -#: website/public/showcase/notion/index.html:468 +#: website/public/showcase/notion/index.html:472 msgctxt "page:showcase/notion/index.html" msgid "Sent to the system clipboard" msgstr "傳送到系統剪貼簿" -#: website/public/showcase/notion/index.html:476 +#: website/public/showcase/notion/index.html:480 msgctxt "page:showcase/notion/index.html" msgid "Saved locally by Notion" msgstr "Notion本地儲存" -#: website/public/showcase/notion/index.html:521 +#: website/public/showcase/notion/index.html:525 msgctxt "page:showcase/notion/index.html" msgid "Markdown input" msgstr "Markdown 輸入" -#: website/public/showcase/notion/index.html:528 +#: website/public/showcase/notion/index.html:532 msgctxt "page:showcase/notion/index.html" msgid "Structured parser output · excerpt" msgstr "結構化解析器輸出 · 摘錄" -#: website/public/showcase/notion/index.html:605 +#: website/public/showcase/notion/index.html:609 msgctxt "page:showcase/notion/index.html" msgid "Analyze your own app" msgstr "分析你自己的應用程式" -#: website/public/showcase/th04/index.html:365 +#: website/public/showcase/th04/index.html:369 msgctxt "page:showcase/th04/index.html" msgid "Agent → REA" msgstr "程式設計助手→ REA" -#: website/public/showcase/th04/index.html:374 +#: website/public/showcase/th04/index.html:378 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · selected fields" msgstr "REA →程式設計助手 · 選定欄位" #. {ph0}: <code>analyze_function</code> -#: website/public/showcase/th04/index.html:393 +#: website/public/showcase/th04/index.html:397 #, python-brace-format msgctxt "page:showcase/th04/index.html" msgid "Agent → REA · {ph0}" msgstr "程式設計助手→ REA · {ph0}" -#: website/public/showcase/th04/index.html:399 +#: website/public/showcase/th04/index.html:403 msgctxt "page:showcase/th04/index.html" msgid "REA → agent · instruction excerpt" msgstr "REA →程式設計助手·指令摘錄" -#: website/public/showcase/th04/index.html:420 +#: website/public/showcase/th04/index.html:424 msgctxt "page:showcase/th04/index.html" msgid "Same function result · aim excerpt" msgstr "相同的函式結果 · 目標摘錄" -#: website/public/showcase/th04/index.html:429 +#: website/public/showcase/th04/index.html:433 msgctxt "page:showcase/th04/index.html" msgid "Corresponding maintained C++" msgstr "對應維護的C++" -#: website/public/showcase/th04/index.html:609 +#: website/public/showcase/th04/index.html:613 msgctxt "page:showcase/th04/index.html" msgid "Ring macro · TH04 branch, excerpt" msgstr "環宏 · TH04分支,摘錄" -#: website/public/showcase/th04/index.html:619 +#: website/public/showcase/th04/index.html:623 msgctxt "page:showcase/th04/index.html" msgid "Angle and velocity · source excerpt" msgstr "角度和速度 · 源摘錄" @@ -11250,7 +11266,7 @@ msgstr "譯文正在更新,這一頁暫時顯示英文。" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/faq/index.html:421 +#: website/public/faq/index.html:425 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11266,7 +11282,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/first-investigation/index.html:239 +#: website/public/first-investigation/index.html:243 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11286,7 +11302,7 @@ msgstr "" #. {ph5}: </span > #. {ph6}: <span class="terminal-cursor" aria-hidden="true"> #. {ph7}: </span> -#: website/public/first-investigation/index.html:289 +#: website/public/first-investigation/index.html:293 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11305,7 +11321,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/get-started/index.html:428 +#: website/public/get-started/index.html:432 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11323,7 +11339,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:265 +#: website/public/index.html:269 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11341,7 +11357,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:1068 +#: website/public/index.html:1072 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11350,14 +11366,14 @@ msgid "" msgstr "{ph0}›{ph1}{ph2}用 REA 檢查 {ph3}。幫我克隆這個網站。{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">dino-speed.js</span> -#: website/public/examples/dino-lab/index.html:316 +#: website/public/examples/dino-lab/index.html:320 #, python-brace-format msgctxt "page:examples/dino-lab/index.html" msgid "Reconstruction · {ph0}" msgstr "重建工程 · {ph0}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/faq/index.html:214 +#: website/public/faq/index.html:218 #, python-brace-format msgctxt "page:faq/index.html" msgid "" @@ -11366,7 +11382,7 @@ msgid "" msgstr "準備好 {ph0} 和 npm 後,執行 setup,選擇程式設計助手,再確認擬進行的更改。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:198 +#: website/public/first-investigation/index.html:202 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "A supplied example · {ph0} and npm · Your coding agent" @@ -11375,7 +11391,7 @@ msgstr "提供的示例 · {ph0} 和 npm · 程式設計助手" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="../get-started/"> #. {ph2}: </a > -#: website/public/first-investigation/index.html:217 +#: website/public/first-investigation/index.html:221 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11392,7 +11408,7 @@ msgstr "" #. {ph5}: <span class="flow-note" > #. {ph6}: <code>notes.exportCsv()</code> #. {ph7}: </span > -#: website/public/first-investigation/index.html:335 +#: website/public/first-investigation/index.html:339 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0}Page · {ph1}{ph2}{ph3}Export notes{ph4}{ph5}Calls {ph6}.{ph7}" @@ -11406,7 +11422,7 @@ msgstr "{ph0}頁面 · {ph1}{ph2}{ph3}Export notes(匯出筆記){ph4}{ph5} #. {ph5}: </span > #. {ph6}: <span class="flow-note" > #. {ph7}: </span > -#: website/public/first-investigation/index.html:343 +#: website/public/first-investigation/index.html:347 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11423,7 +11439,7 @@ msgstr "{ph0}橋接 · {ph1}{ph2}{ph3}{ph4}{ph5}{ph6}向主程序傳送命名訊 #. {ph6}: <span class="flow-note" > #. {ph7}: <code>csv.js</code> #. {ph8}: </span > -#: website/public/first-investigation/index.html:351 +#: website/public/first-investigation/index.html:355 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11433,7 +11449,7 @@ msgstr "" "{ph0}處理函式 · {ph1}{ph2}{ph3}寫入 {ph4}{ph5}{ph6}呼叫 {ph7} 中的格式化函式,再寫入檔案。{ph8}" #. {ph0}: <span translate="no">main.js</span> -#: website/public/first-investigation/index.html:369 +#: website/public/first-investigation/index.html:373 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · lines 8–12" @@ -11448,7 +11464,7 @@ msgstr "{ph0} · 第 8–12 行" #. {ph6}: </span > #. {ph7}: <span class="terminal-cursor" aria-hidden="true"> #. {ph8}: </span> -#: website/public/first-investigation/index.html:411 +#: website/public/first-investigation/index.html:415 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11460,7 +11476,7 @@ msgstr "" "格式化函式驗證。展示預測和實際輸出。{ph6}{ph7}{ph8}" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:429 +#: website/public/first-investigation/index.html:433 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "" @@ -11469,7 +11485,7 @@ msgid "" msgstr "標題保留在一個帶引號的欄位裡,每個引號都寫成兩個。這裡用 {ph0} 直接檢查格式化函式。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/first-investigation/index.html:442 +#: website/public/first-investigation/index.html:446 #, python-brace-format msgctxt "page:first-investigation/index.html" msgid "{ph0} · CSV formatter" @@ -11477,7 +11493,7 @@ msgstr "{ph0} · CSV 格式化函式" #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:196 +#: website/public/get-started/index.html:200 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11485,7 +11501,7 @@ msgid "" msgstr "需要 {ph0} 22(22.19+)、24(24.11+)或 26+。npm 會隨 {ph1} 一起安裝。" #. {ph0}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:201 +#: website/public/get-started/index.html:205 #, python-brace-format msgctxt "page:get-started/index.html" msgid "Don't have {ph0}, or not sure?" @@ -11493,7 +11509,7 @@ msgstr "還沒安裝 {ph0},或不確定?" #. {ph0}: <code>node -v</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/get-started/index.html:220 +#: website/public/get-started/index.html:224 #, python-brace-format msgctxt "page:get-started/index.html" msgid "" @@ -11505,7 +11521,7 @@ msgstr "" "found”,先安裝 {ph1} 24 LTS:" #. {ph0}: <span translate="no">export.js</span> -#: website/public/guides/browser/index.html:437 +#: website/public/guides/browser/index.html:441 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "{ph0} · example source excerpt" @@ -11519,7 +11535,7 @@ msgstr "{ph0} · 示例源摘錄" #. {ph5}: <a href="../../examples/notes-web/notes.json" download > #. {ph6}: <span translate="no">notes.json</span> #. {ph7}: </a > -#: website/public/guides/browser/index.html:455 +#: website/public/guides/browser/index.html:459 #, python-brace-format msgctxt "page:guides/browser/index.html" msgid "" @@ -11528,9 +11544,9 @@ msgid "" msgstr "{ph0}開啟示例{ph1} · {ph2}下載 {ph3}{ph4} · {ph5}下載 {ph6}{ph7}" #. {ph0}: <span translate="no">renderer.js</span> -#: website/public/guides/javascript/index.html:305 -#: website/public/guides/javascript/index.html:321 -#: website/public/guides/javascript/index.html:336 +#: website/public/guides/javascript/index.html:309 +#: website/public/guides/javascript/index.html:325 +#: website/public/guides/javascript/index.html:340 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "{ph0} · example source" @@ -11538,7 +11554,7 @@ msgstr "{ph0} · 示例來源" #. {ph0}: <code>notes-example</code> #. {ph1}: <span translate="no">Node.js</span> -#: website/public/guides/javascript/index.html:370 +#: website/public/guides/javascript/index.html:374 #, python-brace-format msgctxt "page:guides/javascript/index.html" msgid "" @@ -11550,7 +11566,7 @@ msgstr "下載示例並解壓縮。 存檔包含完整的 {ph0} 資料夾。 分 #. {ph0}: <span translate="no">Node.js</span> #. {ph1}: <a href="get-started/"> #. {ph2}: </a> -#: website/public/index.html:290 +#: website/public/index.html:294 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11561,7 +11577,7 @@ msgstr "第一次使用,還沒安裝 {ph0} 或程式設計助手?{ph1}跟著 #. {ph0}: <strong > #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong > -#: website/public/index.html:314 +#: website/public/index.html:318 #, python-brace-format msgctxt "page:index.html" msgid "One question: {ph0}why does Calculator give 220 for {ph1}?{ph2}" @@ -11574,7 +11590,7 @@ msgstr "比如:{ph0}為什麼計算器算 {ph1} 會得到 220?{ph2}" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/index.html:502 +#: website/public/index.html:506 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11584,7 +11600,7 @@ msgstr "" "{ph0}›{ph1}{ph2}用 REA 檢查 Windows 計算器。為什麼 {ph3} 會得到 220?{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">index.js</span> -#: website/public/index.html:687 +#: website/public/index.html:691 #, python-brace-format msgctxt "page:index.html" msgid "REA · loaded {ph0} · selected lines" @@ -11593,7 +11609,7 @@ msgstr "REA · 已載入 {ph0} · 程式碼節選" #. {ph0}: <strong> #. {ph1}: <span translate="no">200 + 10%</span> #. {ph2}: </strong> -#: website/public/index.html:791 +#: website/public/index.html:795 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11609,7 +11625,7 @@ msgstr "我們已看到{ph0}為什麼 {ph1} 得到 220。{ph2}現在把 + 和 × #. {ph5}: <span class="flow-note" > #. {ph6}: <code>ms-calculator:</code> #. {ph7}: </span > -#: website/public/index.html:948 +#: website/public/index.html:952 #, python-brace-format msgctxt "page:index.html" msgid "" @@ -11627,7 +11643,7 @@ msgstr "" #. {ph4}: </span > #. {ph5}: <span class="terminal-cursor" aria-hidden="true"> #. {ph6}: </span> -#: website/public/showcase/aegis/index.html:274 +#: website/public/showcase/aegis/index.html:278 #, python-brace-format msgctxt "page:showcase/aegis/index.html" msgid "" @@ -11639,28 +11655,28 @@ msgstr "" "秒變化一次,再做一個可以調整時間的小示範。{ph4}{ph5}{ph6}" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:338 +#: website/public/showcase/notion/index.html:342 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · API member" msgstr "tab_browser_view/{ph0} · API 成員" #. {ph0}: <span translate="no">preload.js</span> -#: website/public/showcase/notion/index.html:367 +#: website/public/showcase/notion/index.html:371 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "tab_browser_view/{ph0} · IPC helper" msgstr "tab_browser_view/{ph0} · IPC 輔助函式" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:398 +#: website/public/showcase/notion/index.html:402 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · handler helper" msgstr "主要/{ph0} · 處理程式助手" #. {ph0}: <span translate="no">index.js</span> -#: website/public/showcase/notion/index.html:426 +#: website/public/showcase/notion/index.html:430 #, python-brace-format msgctxt "page:showcase/notion/index.html" msgid "main/{ph0} · clipboard receiver" @@ -11670,12 +11686,1177 @@ msgstr "主要/{ph0} · 剪貼簿接收器" # decorative. #. {ph0}: <span class="button-arrow" aria-hidden="true" data-i18n-skip #. >→</span > -#: website/public/index.html:229 +#: website/public/index.html:233 #, python-brace-format msgctxt "page:index.html" msgid "Get started {ph0}" msgstr "開始使用 {ph0}" +#: website/public/assets/theme.js:52 +msgctxt "runtime" +msgid "Switch to light mode" +msgstr "切換至淺色模式" + +#: website/public/assets/theme.js:53 +msgctxt "runtime" +msgid "Switch to dark mode" +msgstr "切換至深色模式" + +#. {ph0}: <a href="https://github.com/morluto/rea/blob/main/docs/web-network- +#. captures.md" > +#. {ph1}: </a > +#: website/public/guides/browser/index.html:480 +#, python-brace-format +msgctxt "page:guides/browser/index.html" +msgid "" +"For HTTP request and response bodies, use {ph0}Fiddler Everywhere: SAZ " +"captures, MCP and public skills{ph1}. Export SAZ or HAR 1.2 for offline REA " +"capture Evidence, or connect Everywhere's MCP server to inspect captured " +"traffic with your agent." +msgstr "" +"若要檢查 HTTP 請求與回應本文,請使用{ph0}Fiddler Everywhere:SAZ 擷取、MCP 與公開技能{ph1}。匯出 SAZ ? " +"HAR 1.2 可在 REA 中離線取得擷取 Evidence,也可以連接 Everywhere 的 MCP 伺服器,讓代理檢查已擷取的流量。" + +#. {ph0}: <br /> +#: website/public/blog/index.html:200 +#, python-brace-format +msgctxt "page:blog/index.html" +msgid "Model specialization{ph0}Essay" +msgstr "專用模型{ph0}隨筆" + +#: website/public/blog/index.html:202 +msgctxt "page:blog/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "逆向工程需要更大的模型嗎?" + +#: website/public/blog/index.html:203 +msgctxt "page:blog/index.html" +msgid "" +"What Touhou reconstruction suggests about general models, specialist models " +"and learning from compiler feedback." +msgstr "從 Touhou 重建的經驗,探討通用模型、專用模型,以及如何從編譯器回饋中學習。" + +#: website/public/blog/index.html:210 +msgctxt "page:blog/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "作者 N0zoM1z0 · 2026 年 10 月 13 日" + +#: website/public/blog/reverse-engineering-models/index.html:103 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Skip to content" +msgstr "跳轉到內容" + +#. {ph0}: <a href="../../"> +#. {ph1}: </a> +#. {ph2}: <a href="../"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:194 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Home{ph1} / {ph2}Blog{ph3} / Models and RE" +msgstr "{ph0}首頁{ph1} / {ph2}部落格{ph3} / 模型與逆向工程" + +#: website/public/blog/reverse-engineering-models/index.html:197 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Essay" +msgstr "隨筆" + +# Reviewed for technical meaning and readability; preserve the distinction +# between historical evidence and proposed experiments. +#: website/public/blog/reverse-engineering-models/index.html:198 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model?" +msgstr "逆向工程需要更大的模型嗎?" + +#: website/public/blog/reverse-engineering-models/index.html:199 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "By N0zoM1z0 · 13 October 2026" +msgstr "作者 N0zoM1z0 · 2026 年 10 月 13 日" + +#: website/public/blog/reverse-engineering-models/index.html:201 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Takeaway" +msgstr "要點" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:203 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Model capability changes the hypotheses an agent can find.{ph1} Later " +"sessions have solved problems that earlier work left unresolved." +msgstr "{ph0}模型能力會影響 agent 能提出哪些假設。{ph1} 後來的工作解決了早期嘗試未能解決的問題。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:211 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A familiar compiler gives specialization something concrete to " +"learn.{ph1} Some exact matches depend on narrow, reusable source patterns." +msgstr "{ph0}熟悉的編譯器為專用模型提供了具體的學習對象。{ph1} 有些精確匹配依賴細小但可以複用的原始碼模式。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#: website/public/blog/reverse-engineering-models/index.html:218 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Give repository knowledge a fair comparison.{ph1} A smaller model with " +"good retrieval may already know enough to make progress." +msgstr "{ph0}也要公平評估程式碼倉庫裡的知識。{ph1} 較小的模型配合良好的檢索,可能已經掌握了足以推進工作的知識。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:223 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Train the next useful experiment, and test its oracle.{ph1} The value " +"of feedback depends on what the checker actually verifies." +msgstr "{ph0}訓練模型選擇下一個有價值的實驗,同時檢驗它使用的驗證器。{ph1} 回饋是否有用,取決於驗證器究竟檢查了什麼。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:230 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Measure accepted reconstruction against time and cost.{ph1} That is the" +" result I want from the whole agent." +msgstr "{ph0}結合時間和成本,評估透過驗證的重建成果。{ph1} 這是我希望從整個 agent 工作流程中獲得的結果。" + +#: website/public/blog/reverse-engineering-models/index.html:241 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "In this article" +msgstr "在本文中" + +#. {ph0}: <a href="#model-capability"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:243 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What better models changed{ph1}" +msgstr "{ph0}更強的模型改變了什麼{ph1}" + +#. {ph0}: <a href="#specialization"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:244 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Why specialize?{ph1}" +msgstr "{ph0}為什麼考慮專用模型?{ph1}" + +#. {ph0}: <a href="#repository-knowledge"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:245 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Where experience lives{ph1}" +msgstr "{ph0}這些經驗應該存在哪裡?{ph1}" + +#. {ph0}: <a href="#learning-search"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:246 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}Learning the next experiment{ph1}" +msgstr "{ph0}學習選擇下一個有價值的實驗{ph1}" + +#. {ph0}: <a href="#re-and-rl"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:247 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}RE and reinforcement learning{ph1}" +msgstr "{ph0}逆向工程與強化學習{ph1}" + +#. {ph0}: <a href="#oracle"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:248 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}When the oracle is wrong{ph1}" +msgstr "{ph0}當驗證器出錯時{ph1}" + +#. {ph0}: <a href="#comparison"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:249 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}A comparison worth running{ph1}" +msgstr "{ph0}值得做的對照實驗{ph1}" + +#. {ph0}: <a href="#future-agent"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:250 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "{ph0}What kind of agent?{ph1}" +msgstr "{ph0}這意味著怎樣的 agent?{ph1}" + +#: website/public/blog/reverse-engineering-models/index.html:258 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What better models changed" +msgstr "更強的模型改變了什麼" + +#: website/public/blog/reverse-engineering-models/index.html:259 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Since August 2026, I have been exploring how much reverse engineering an " +"agent can carry out with access to a program and a way to check its work. " +"Most of my experience comes from reconstructing games, especially Touhou. As" +" I have changed models, the repositories have kept a record of what each " +"session managed to recover." +msgstr "" +"從 2026 年 8 月開始,我一直在探索:如果給 agent " +"訪問程式的能力,以及驗證自身工作的手段,它能獨立完成多少逆向工作?我的經驗主要來自遊戲重建,尤其是東方系列。隨著我更換模型,程式碼倉庫記錄了每次工作還原出的內容。" + +#: website/public/blog/reverse-engineering-models/index.html:267 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of that work aims at exact reconstruction: we compile the maintained " +"source under a pinned historical toolchain and check whether it reproduces " +"the target function. When a later model succeeds where earlier work stalled," +" the source changes show what made that progress possible." +msgstr "" +"這些工作很大一部分追求精確重建:用固定版本的歷史工具鏈編譯我們維護的原始碼,檢查它能否復現目標函式。當後來的模型解決了早期工作卡住的問題,我們可以從原始碼變化中看出,是什麼促成了這次進展。" + +#: website/public/blog/reverse-engineering-models/index.html:274 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The temporary values had to stay alive together" +msgstr "臨時值需要同時保持有效" + +#: website/public/blog/reverse-engineering-models/index.html:275 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Much of a TH09 attack function's logic had already been reconstructed, but " +"the compiler still stored temporary results differently from the original. " +"The remaining problem was how long those results needed to stay alive and " +"when their storage could be reused." +msgstr "" +"TH09 " +"中一個攻擊函式的大部分邏輯已經還原,但編譯器對臨時結果的儲存安排仍然與原版不同。剩下的問題在於:這些結果的生命週期應該多長,編譯器何時可以複用它們的儲存空間?" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:282 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A {ph0}GPT-6-Sol checkpoint{ph1} recorded this mismatch after testing " +"several ordinary source arrangements. When {ph2}GPT-6.1-Sol returned to the " +"problem{ph3}, it found a useful hypothesis about how long those temporary " +"values needed to stay alive." +msgstr "" +"{ph0}GPT-6-Sol 的一次工作記錄{ph1}表明,嘗試幾種常見的原始碼寫法後,差異仍未消除。後來,{ph2}GPT-6.1-Sol " +"重新研究這個問題{ph3},提出了一個有價值的假設:關鍵可能在於這些臨時值的生命週期。" + +#: website/public/blog/reverse-engineering-models/index.html:296 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The function produced temporary results and copied them into animation " +"positions. In C++, a temporary result stays alive until the expression using" +" it finishes. Grouping the real operations into one expression kept those " +"results alive together, so the compiler could no longer reuse the same " +"storage for all of them." +msgstr "" +"這個函式會產生臨時結果,再把它們複製到動畫的位置資料中。在 C++ " +"中,臨時結果會一直存在,直到使用它的表示式執行完畢。把實際操作放進同一個表示式,就能讓這些結果同時存活,編譯器也就不能為它們全部複用同一塊儲存空間。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:303 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"One result still shared storage with a value used later for collision " +"checks. Giving that value its own lifetime resolved the remaining overlap. " +"After several targeted experiments, {ph0}a clean rebuild confirmed that the " +"full function matched{ph1}." +msgstr "" +"其中一個結果仍然與稍後用於碰撞檢查的值共享儲存。給那個值單獨的生命週期後,最後一處重疊也消失了。經過幾次有針對性的實驗,{ph0}一次乾淨的重新構建確認,整個函式都已匹配{ph1}。" + +#: website/public/blog/reverse-engineering-models/index.html:312 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What interests me is how the discovery and the tests worked together. The " +"lifetime hypothesis gave the agent a new direction; compiler feedback helped" +" it refine that hypothesis into a source arrangement that matched." +msgstr "" +"我感興趣的是,發現與驗證如何共同推進工作。生命週期的假設給 agent 指明瞭新方向;編譯器的回饋又幫助它逐步調整原始碼,直到找到匹配的寫法。" + +#: website/public/blog/reverse-engineering-models/index.html:318 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A different control-flow graph" +msgstr "換一種控制流結構" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:319 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A second TH09 function shows why that new direction can matter. Here, the " +"obstacle was how several branches shared their final work. " +"{ph0}GPT-6.1-Sol's earlier work{ph1} got parts of the function to match, but" +" the branches still joined up differently from the original." +msgstr "" +"TH09 的另一個函式說明了,新方向為什麼重要。這次的難點是多個分支如何共享末尾的操作。{ph0}GPT-6.1-Sol " +"之前的工作{ph1}已經讓函式的一些部分匹配,但分支匯合的方式仍與原版不同。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph1}: </a > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph3}: </a > +#: website/public/blog/reverse-engineering-models/index.html:330 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}GPT-6-Astra changed the surrounding control-flow graph{ph1}. The main " +"paths now led to a shared final update and return. In that source structure," +" the compiler combined the branches in the same way as the original. The " +"complete function matched, and a {ph2}separate rebuild check confirmed " +"it{ph3}." +msgstr "" +"{ph0}GPT-6-Astra " +"改寫了外圍的控制流圖{ph1},讓主要路徑匯入共同的最終更新與返回。在這種原始碼結構下,編譯器合併分支的方式與原版一致。整個函式實現了匹配,{ph2}另一次獨立的重新構建也確認了這一結果{ph3}。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:342 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Changing the representation opened a more productive search space.{ph1}" +" Both cases give me a reason to take general model capability seriously: an " +"agent can keep trying local variations for a long time before finding a " +"better way to express the surrounding work." +msgstr "" +"{ph0}換一種表達方式,開啟了更有價值的搜尋空間。{ph1} 這兩個例子讓我認真看待通用模型的能力:agent " +"可能花很長時間嘗試局部變化,才找到一種更好的整體寫法。" + +#: website/public/blog/reverse-engineering-models/index.html:351 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"At the same time, the later sessions started with earlier source and " +"recorded failures. That accumulated work was part of their advantage. The " +"history lets us inspect the discoveries and their checks; a controlled " +"comparison would help separate the effect of the model from the experience " +"it inherited." +msgstr "" +"不過,後來的工作也繼承了之前的原始碼和失敗記錄。這些積累本身就是優勢的一部分。歷史記錄讓我們可以檢查發現及其驗證過程;要區分模型能力和繼承經驗各自帶來的幫助,還需要對照實驗。" + +#: website/public/blog/reverse-engineering-models/index.html:358 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is where the question becomes interesting to me. Some of the progress " +"came from finding a new representation, while much of the remaining work " +"involved testing source forms against a familiar compiler. How much needs " +"broad reasoning ability, and how much could a model learn through repeated " +"experience with that compiler and code?" +msgstr "" +"這正是我覺得有趣的地方。有些進展來自新的表達方式,剩下的大量工作則是在熟悉的編譯器上試驗不同寫法。其中有多少需要廣泛的推理能力?又有多少可以透過反覆接觸這個編譯器和這些程式碼來學會?" + +#: website/public/blog/reverse-engineering-models/index.html:368 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why might a specialist do well?" +msgstr "為什麼專用模型可能做得很好?" + +#: website/public/blog/reverse-engineering-models/index.html:369 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Touhou gives us a concrete reason to expect that experience to help. Much of" +" the game code comes from the same author, ZUN, so recurring habits are a " +"reasonable starting assumption. The repositories back that up with useful " +"examples: related loops and helper arrangements have supplied hypotheses " +"across games." +msgstr "" +"東方系列給了我們一個具體的理由,去期待經驗積累能發揮作用。大量遊戲程式碼出自同一個作者 " +"ZUN,因此,把反覆出現的程式設計習慣作為初始假設是合理的。程式碼倉庫也提供了實際例子:相似的迴圈和輔助函式組織方式,曾為其他遊戲的重建提供假設。" + +#: website/public/blog/reverse-engineering-models/index.html:376 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those source patterns become more specific when we include the compiler. " +"Under a particular version and set of options, small changes in source can " +"produce repeatable differences in machine code. Some of those differences " +"are surprisingly obscure." +msgstr "把編譯器也考慮進去,這些原始碼模式就更加具體了。在固定版本和選項下,原始碼的小變化可能穩定地產生不同的機器碼。其中一些規律藏得很深。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: <code>Supervisor::LoadDat</code> +#. {ph4}: </a > +#: website/public/blog/reverse-engineering-models/index.html:382 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In TH095, for example, {ph0}even the name used for a local variable could " +"change where VC7.1 stored it{ph1}. Moving the declaration alone did not " +"solve the layout, but an earlier background function had revealed a naming " +"pattern that affected the compiler's choice. That gave us a more promising " +"hypothesis for {ph2}the reconstruction of {ph3}{ph4}." +msgstr "" +"以 TH095 為例,{ph0}連局部變數的名字,都可能改變 VC7.1 " +"為它安排的儲存位置{ph1}。只移動宣告並不能解決佈局問題,但先前重建的一個背景函式揭示了會影響編譯器選擇的命名模式。這為{ph2}重建 " +"{ph3}{ph4}提供了更有希望的假設。" + +#: website/public/blog/reverse-engineering-models/index.html:396 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reusing that pattern for the file-size variable produced the required layout" +" without adding storage. The full function then matched." +msgstr "把這個模式用於表示檔案大小的變數,不增加額外儲存就得到了所需佈局。隨後,整個函式實現了匹配。" + +#: website/public/blog/reverse-engineering-models/index.html:401 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This is the sort of narrow detail a general model may not know when it " +"arrives. A specialist trained on this compiler could encounter many such " +"cases and learn which source variations are worth testing first." +msgstr "這類細節非常具體,通用模型第一次接觸時未必知道。而針對這個編譯器訓練的專用模型,可以接觸許多類似案例,學會哪些原始碼變化值得優先嚐試。" + +#: website/public/blog/reverse-engineering-models/index.html:407 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The opportunity is especially clear in final matching problems where we " +"already understand the behavior. We are then asking which ordinary source " +"form this compiler turns into the observed instructions. Specialization " +"could help the model propose those forms more efficiently, while the target " +"still determines which hypotheses survive." +msgstr "" +"當我們已經理解函式行為,只剩最後的匹配差異時,這個機會尤其明顯。此時的問題是:這個編譯器會把哪一種普通寫法編譯成眼前的指令?專用訓練可能讓模型更高效地提出這些寫法,而最終由目標程式決定哪些假設成立。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:415 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The useful patterns would have to retain their context, though. TH08 uses an" +" earlier Visual C++ version than TH095 and TH09. TH04 uses a different DOS-" +"era compiler, and its {ph0}player reconstruction{ph1} needed different " +"hypotheses about source patterns and how the compiled code was combined into" +" an executable. Shared authorship gives us a prior, but each target tells us" +" whether it applies. Distinguishing those contexts is part of what a " +"specialist would need to learn." +msgstr "" +"但這些模式必須保留適用的上下文。TH08 使用的 Visual C++ 版本早於 TH095 和 TH09。TH04 用的是另一種 DOS " +"時代的編譯器,其{ph0}玩家邏輯重建{ph1}需要不同的假設,既涉及原始碼寫法,也涉及編譯後的程式碼如何連結成可執行檔案。同一作者為我們提供了先驗,具體目標則告訴我們它是否適用。區分這些情況,也是專用模型需要學會的事。" + +#: website/public/blog/reverse-engineering-models/index.html:431 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Where should that experience live?" +msgstr "這些經驗應該存在哪裡?" + +#. {ph0}: <a href="../touhou-reconstruction/"> +#. {ph1}: </a> +#: website/public/blog/reverse-engineering-models/index.html:432 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before deciding to teach those patterns through model training, I would look" +" at the knowledge we already keep in the repository. In the {ph0}previous " +"essay{ph1}, I wrote about it becoming the project's working memory. That " +"memory includes compiler lessons, along with the source and failed " +"experiments that made them useful." +msgstr "" +"在決定透過訓練讓模型學會這些模式之前,我會先看看程式碼倉庫裡已有的知識。在{ph0}上一篇文章{ph1}中,我寫過:倉庫正在成為專案的工作記憶。這裡儲存著對編譯器的認識,也儲存著相關原始碼和失敗實驗,讓這些經驗有據可查。" + +#: website/public/blog/reverse-engineering-models/index.html:441 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"By retrieving that record, an agent can start with a known result and " +"inspect how we reached it. It can also avoid alternatives that have already " +"failed in the same context. The starting point improves without changing the" +" model's weights." +msgstr "" +"檢索這些記錄後,agent 可以從已知結果出發,看看我們是如何得到它的,也可以避開在相同條件下已經失敗的方案。模型的參數沒有改變,工作的起點卻提高了。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:447 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"When reconstructing TH09's enemy-spawn function, a {ph0}GPT-6-Luna-max " +"session{ph1} drew a hypothesis from TH08's corresponding source family. That" +" earlier source suggested how to structure the loop and handle failures " +"within it. TH09's own evidence supplied the game-specific details, and clean" +" rebuilds confirmed the complete match." +msgstr "" +"重建 TH09 的敵人生成函式時,{ph0}GPT-6-Luna-max 的一次工作{ph1}從 TH08 " +"對應的原始碼中找到了假設。之前的寫法提示了迴圈該如何組織,以及內部失敗該如何處理。TH09 " +"自身的證據補上了遊戲特有的細節,乾淨的重新構建確認了整個函式的匹配。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:458 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}\"The model did not know that compiler quirk\" and \"the model could " +"not use it\" are different problems.{ph1} Retrieval may solve the first, but" +" turning that fact into a useful candidate still takes work. And if the " +"candidate fails, the model must decide what the result means for its next " +"attempt. Knowing the relevant pattern is only the beginning of that process." +msgstr "" +"{ph0}“模型不知道這個編譯器特性”和“模型不會利用它”,是兩個不同的問題。{ph1} " +"檢索可能解決前者,但把知識變成有價值的候選原始碼,仍然需要能力。如果候選方案失敗了,模型還得判斷這次結果對下一次嘗試意味著什麼。知道相關模式,只是這個過程的起點。" + +#: website/public/blog/reverse-engineering-models/index.html:468 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For that reason, I would include a smaller general model with good retrieval" +" in any comparison. Giving it the same library of experience would help us " +"identify what training adds: better candidate generation, better decisions " +"after feedback, or both." +msgstr "" +"所以,在任何對照實驗中,我都會加入一個具備良好檢索能力的小型通用模型。給它相同的經驗庫,才能看清訓練究竟增加了什麼:更好的候選方案、更好的回饋後決策,還是兩者都有?" + +#: website/public/blog/reverse-engineering-models/index.html:476 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Learning the next useful experiment" +msgstr "學習選擇下一個有價值的實驗" + +#: website/public/blog/reverse-engineering-models/index.html:477 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Those decisions after feedback are what I would most like to study. In " +"agentic reconstruction, the model proposes an explanation and tests it " +"against the program. Even when the candidate fails, the result can narrow " +"the remaining possibilities and suggest a more useful next experiment." +msgstr "" +"回饋之後如何決策,是我最想研究的部分。在 agent " +"驅動的重建中,模型提出解釋,再用程式來驗證。即使候選方案失敗了,結果也可能縮小剩餘的可能性,提示下一步更值得嘗試什麼。" + +#: website/public/blog/reverse-engineering-models/index.html:484 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Consider the temporary-results example again. Its final source shows the " +"arrangement that worked, but the route to that source contains more " +"information. Each of the following experiments helped identify what still " +"needed to change." +msgstr "再看前面的臨時結果例子。最終原始碼展示了成功的寫法,但得到它的過程包含更多資訊。下面的每次實驗,都幫助我們確定了還有什麼需要改變。" + +#: website/public/blog/reverse-engineering-models/index.html:497 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Experiment" +msgstr "實驗" + +#: website/public/blog/reverse-engineering-models/index.html:498 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What its result taught us" +msgstr "結果告訴了我們什麼" + +#: website/public/blog/reverse-engineering-models/index.html:503 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Try a different way to copy the results" +msgstr "嘗試另一種複製結果的方式" + +#: website/public/blog/reverse-engineering-models/index.html:504 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "The copy code changes, but the function still differs." +msgstr "複製程式碼改變了,但函式仍有差異。" + +#: website/public/blog/reverse-engineering-models/index.html:509 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Use the returned values directly" +msgstr "直接使用回傳值" + +#: website/public/blog/reverse-engineering-models/index.html:510 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Copying follows the original pattern, but temporary storage still differs." +msgstr "複製方式與原版一致,但臨時儲存佈局仍有差異。" + +#: website/public/blog/reverse-engineering-models/index.html:516 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the temporary results alive together" +msgstr "讓臨時結果同時保持有效" + +#: website/public/blog/reverse-engineering-models/index.html:517 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"They get separate storage, but one still overlaps a value used later for " +"collision checks." +msgstr "它們得到了各自的儲存空間,但其中一個仍與稍後用於碰撞檢查的值重疊。" + +#: website/public/blog/reverse-engineering-models/index.html:523 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Keep the collision-check value separate" +msgstr "讓碰撞檢查的值擁有獨立儲存" + +#: website/public/blog/reverse-engineering-models/index.html:524 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A clean rebuild confirms the complete match." +msgstr "乾淨的重新構建確認了整個函式的匹配。" + +#: website/public/blog/reverse-engineering-models/index.html:529 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Selected experiments from the attack-function reconstruction above, grouped " +"by what they taught us." +msgstr "選自前面攻擊函式的重建實驗,按每次得到的認識整理。" + +#: website/public/blog/reverse-engineering-models/index.html:533 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A training record that keeps this sequence can teach more than the final " +"source alone. It connects each proposed change to an observed result and the" +" next decision. Keeping ineffective variations matters too: they tell a " +"later agent which hypotheses have already been tested in that context." +msgstr "" +"儲存這個過程的訓練記錄,比單獨儲存最終原始碼能教會模型更多東西。它把每個改動、觀察到的結果和下一步決策聯絡起來。無效的嘗試也值得保留:後來的 agent" +" 可以據此知道,在這個上下文中,哪些假設已經檢驗過。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:540 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}I would want the model to learn how to use feedback.{ph1} A neutral " +"result is a reason to reconsider the variation; a changed mismatch may point" +" to another cause. When local edits stop being informative, the agent should" +" be able to revisit the source representation or inspect the evidence again." +msgstr "" +"{ph0}我希望模型學會如何利用回饋。{ph1} " +"結果沒有變化,可能意味著該重新考慮這個改動;差異發生變化,則可能指向另一個原因。當局部修改不再提供有效資訊時,agent " +"應該可以重新考慮原始碼的整體表達,或者回頭檢查證據。" + +#: website/public/blog/reverse-engineering-models/index.html:549 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Learning to make those choices requires autonomy. Sometimes the useful next " +"step is inspecting another caller rather than compiling another edit. A " +"rigid sequence of required rewrites would remove that choice, along with " +"part of the behavior we want the model to learn." +msgstr "" +"學會這些選擇,需要自主性。有時,更有價值的下一步是檢查另一個呼叫者,而不是再修改一次原始碼並編譯。如果強制按照固定順序改寫,就會剝奪這種選擇,也失去一部分我們希望模型學會的行為。" + +#: website/public/blog/reverse-engineering-models/index.html:558 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Why RE is interesting for reinforcement learning" +msgstr "為什麼逆向工程值得用來探索強化學習" + +#: website/public/blog/reverse-engineering-models/index.html:559 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Bounded reconstruction gives us a practical environment for studying these " +"choices. Once the target and compiler are pinned, many source experiments " +"produce quick, repeatable feedback. The agent can compile a candidate, " +"inspect the mismatch and use that observation to choose its next step." +msgstr "" +"範圍明確的重建任務,為研究這些選擇提供了一個實際環境。目標和編譯器版本固定之後,許多原始碼實驗都能快速給出可重複的回饋。agent " +"可以編譯候選原始碼、檢查差異,再根據觀察選擇下一步。" + +#: website/public/blog/reverse-engineering-models/index.html:566 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Reinforcement learning could train that decision-making process through the " +"feedback it receives. A candidate accepted by a defined check gives us a " +"concrete outcome, while the sequence of attempts lets us observe how much " +"work it took to reach it." +msgstr "" +"強化學習可以利用這些回饋,訓練模型的決策過程。候選原始碼透過明確定義的檢查,就給出了一個具體成果;而嘗試的過程,讓我們可以看到實現它花了多少功夫。" + +#. {ph0}: <a href="https://aclanthology.org/2024.emnlp-main.203/" > +#. {ph1}: </a > +#. {ph2}: <a href="https://arxiv.org/html/2606.16162v1"> +#. {ph3}: </a> +#: website/public/blog/reverse-engineering-models/index.html:572 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"There is already research supporting this direction. {ph0}LLM4Decompile{ph1}" +" studies models specialized for decompilation. {ph2}AutoDecompiler{ph3} " +"trains multi-turn refinement using compiler and execution feedback. Their " +"studies focus on functional recovery. For this work, I would use them as a " +"starting point for the related task of finding source that matches a " +"historical compiler's output." +msgstr "" +"已有研究支援這個方向。{ph0}LLM4Decompile{ph1}研究專門用於反編譯的模型。{ph2}AutoDecompiler{ph3}利用編譯和執行回饋,訓練多輪改進能力。這些研究關注的是功能還原。對於我們的工作,我會以它們為起點,研究一個相關任務:找到能復現歷史編譯器輸出的原始碼。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:584 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To reach such a well-defined task, though, we may first need to establish " +"what a function owns or devise a new runtime measurement. In TH08, for " +"example, a {ph0}collision difference led back to how the original program " +"handled floating-point calculations{ph1}. Before the agent could test a " +"useful correction, it had to work out what to measure." +msgstr "" +"不過,要得到這樣一個定義明確的任務,有時得先確定函式負責哪些資源,或者設計新的方法觀察程式執行時的行為。在 TH08 " +"中,{ph0}一次碰撞差異最終追溯到原版處理浮點計算的方式{ph1}。agent 必須先弄清楚該測量什麼,才能驗證有價值的修正。" + +#: website/public/blog/reverse-engineering-models/index.html:595 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This suggests another role for a broadly capable model: helping make the " +"problem checkable in the first place. Once that check exists, we can " +"investigate how far a learned search policy can get with it." +msgstr "這提示了能力全面的模型的另一個作用:先把問題變得可驗證。驗證手段建立起來後,我們才可以研究,學出來的搜尋策略能走多遠。" + +#: website/public/blog/reverse-engineering-models/index.html:603 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "When the oracle is wrong" +msgstr "當驗證器出錯時" + +#: website/public/blog/reverse-engineering-models/index.html:604 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Once we train against that check, its coverage becomes part of what the " +"model learns. I call the reference or checker an oracle. Even if it gives a " +"repeatable answer, we still need to understand what that answer covers." +msgstr "" +"一旦用某項檢查來訓練模型,它的覆蓋範圍就會成為學習環境的一部分。我把這種參考標準或驗證器稱為 " +"oracle。即使它能給出可重複的答案,我們也必須知道,這個答案覆蓋了什麼。" + +#: website/public/blog/reverse-engineering-models/index.html:610 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"TH08 showed how much can hide outside that coverage. Some reconstructed " +"functions passed their exact comparisons with wrong floating constants. The " +"comparator adjusted relocated addresses before checking instructions, but it" +" checked the values behind those addresses only when they had been " +"explicitly recorded for verification. Other literal references could pass " +"without their values being examined." +msgstr "" +"TH08 " +"展示了檢查範圍之外可能藏著多少問題。一些重建函式使用了錯誤的浮點常量,卻仍然透過了精確比較。比較器會先調整重定位地址,再檢查指令;但只有明確登記過的常量,才會進一步檢查地址指向的值。其他常量引用,即使值沒被檢查,也可能透過。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph1}: </a > +#. {ph2}: <code>1.0f</code> +#. {ph3}: <code>32.0f</code> +#: website/public/blog/reverse-engineering-models/index.html:619 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To close that gap, a {ph0}wider audit{ph1} found incorrect constants in " +"functions that had already been accepted. In one calculation, the " +"reconstructed source added {ph2} where the original added {ph3}." +msgstr "" +"為了補上這個漏洞,{ph0}一次更全面的審計{ph1}在已經透過檢查的函式中找到了錯誤常量。有一個計算中,重建原始碼加的是 {ph2},而原版加的是 " +"{ph3}。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:629 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}A learner rewarded by the old check could learn to produce the wrong " +"reconstruction.{ph1} We had not trained an RL model against this oracle; the" +" observed failure was in the check itself. But using that check as a reward " +"would have made the same blind spot part of the learning environment." +msgstr "" +"{ph0}如果用舊檢查的結果作為獎勵,模型可能學會生成錯誤的重建原始碼。{ph1} 我們沒有用這個驗證器訓練 RL " +"模型;實際觀察到的是檢查本身的漏洞。但如果把它用作獎勵,同一個盲點也會進入學習環境。" + +#. {ph0}: <a href="https://arxiv.org/html/2609.05370v1" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:639 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"A functional test can have a similar blind spot. {ph0}Differential-fuzzing " +"research on LLM decompilers{ph1} has found behavior differences beyond the " +"supplied tests. Passing those tests therefore needs to be read in terms of " +"the cases they exercise, just as an instruction match needs to be read in " +"terms of the bytes and data it checks." +msgstr "" +"功能測試也可能存在類似盲點。{ph0}針對 LLM " +"反編譯器的差分模糊測試研究{ph1}發現,在已有測試之外,程式行為仍可能不同。因此,理解“測試透過”時,必須看它實際覆蓋了哪些情況;理解“指令匹配”時,也必須看它檢查了哪些位元組和資料。" + +#: website/public/blog/reverse-engineering-models/index.html:649 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Before using either kind of check as a reward, I would test it with " +"deliberate failures. I would also keep final acceptance outside the " +"candidate's editable source, so the model has to satisfy the check through " +"its reconstruction. Otherwise, something like a byte array copied from the " +"target could satisfy a naive score without recovering useful source." +msgstr "" +"在把任何一種檢查用作獎勵之前,我都會用刻意構造的錯誤來測試它。我還會把最終驗收機制放在候選原始碼可修改的範圍之外,讓模型透過正確重建來滿足檢查。否則,直接複製目標程式的位元組陣列,也可能騙過簡單的評分,卻沒有還原出有用的原始碼。" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:657 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Improving the learner and improving its oracle belong to the same " +"research problem.{ph1} As the learner gets better at optimizing the feedback" +" we give it, understanding that feedback becomes more important too." +msgstr "{ph0}改進模型和改進它的驗證器,屬於同一個研究問題。{ph1} 模型越擅長最佳化我們給它的回饋,我們就越需要理解回饋本身。" + +#: website/public/blog/reverse-engineering-models/index.html:667 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "A comparison worth running" +msgstr "值得做的對照實驗" + +#: website/public/blog/reverse-engineering-models/index.html:668 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"With those checks in place, I would start the comparison on a fixed VC7.1 " +"task family. First, I would establish baselines for a strong general model " +"and a smaller one. Adding repository knowledge to the smaller model would " +"show what retrieval changes. From there, supervised specialization and an " +"RL-trained version would let us examine what training adds." +msgstr "" +"具備這些檢查之後,我會從一組固定的 VC7.1 " +"任務開始比較。先為強通用模型和小型通用模型建立基線,再給小模型加入倉庫知識,觀察檢索帶來的變化。接著比較監督訓練的專用模型,以及在此基礎上進行 RL " +"訓練的版本,看看訓練增加了什麼。" + +#: website/public/blog/reverse-engineering-models/index.html:676 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"To make those comparisons informative, each model would receive the same " +"target evidence and tools. For the training-specific comparisons, I would " +"keep the base model and available knowledge fixed as well. Repeated trials " +"would help distinguish a reliable search strategy from a lucky candidate." +msgstr "" +"為了讓比較有意義,每個模型都應獲得相同的目標證據和工具。專門比較訓練效果時,還要固定基礎模型和可用知識。重複實驗有助於區分可靠的搜尋策略與偶然成功的候選方案。" + +#: website/public/blog/reverse-engineering-models/index.html:683 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would then separate two starting conditions: reconstructing a function " +"from its instructions, and closing the last few differences in maintained " +"source. A specialist might be excellent at the second task while a general " +"model does much of the work needed to reach it. Measuring them separately " +"would reveal that division of work." +msgstr "" +"我還會區分兩種起點:從指令開始重建函式,以及在已有原始碼中消除最後幾處差異。專用模型可能很擅長後者,而通用模型承擔了到達這個階段的大部分工作。分別評估,才能看清這種分工。" + +#: website/public/blog/reverse-engineering-models/index.html:691 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both tasks need genuinely held-out examples. Because related Touhou games " +"share engine code, holding out a game's name would still allow nearly " +"identical functions to appear in training. I would instead hold out source " +"families and keep their accepted answers out of both training and retrieval." +msgstr "" +"兩類任務都需要真正未見過的測試案例。東方系列的相關遊戲會共享引擎程式碼,只留出某個遊戲,仍可能讓幾乎相同的函式進入訓練集。我會改為按相關原始碼家族留出測試集,並把它們透過驗證的答案同時排除在訓練資料和檢索庫之外。" + +#: website/public/blog/reverse-engineering-models/index.html:698 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"On those examples, the outcome would be complete, independently validated " +"matches. Giving each model the same candidate or compile budget would help " +"compare search quality. Measuring elapsed time and total cost, including " +"compilation, would tell us whether that quality produces an efficient " +"workflow. Training costs would need their own accounting too." +msgstr "" +"在這些案例上,要統計的是完整、獨立驗證過的匹配成果。給每個模型相同的候選數量或編譯次數預算,可以比較搜尋品質。記錄總耗時和總成本,包括編譯,才能知道這種品質是否轉化成了高效的工作流程。訓練成本也要單獨計算。" + +#: website/public/blog/reverse-engineering-models/index.html:706 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Both views matter because a cheaper proposal can become an expensive " +"workflow if it causes more uninformative compiles. Conversely, a slower " +"model may pay for itself by finding a useful experiment sooner. The " +"comparison should capture those costs." +msgstr "" +"兩種角度都重要。一個便宜的提議,如果導致大量無效編譯,整個工作流程仍可能很貴。反過來,較慢的模型如果更早找到有價值的實驗,也可能更划算。對照實驗應當反映這些成本。" + +#. {ph0}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:712 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"Counting accepted results also keeps intermediate progress in perspective. " +"One TH09 {ph0}replay-save candidate{ph1} looked promising because the " +"compiled function had the expected size, but a full comparison still found " +"substantial differences. Changes in how the compiler arranges instructions " +"can also make a candidate look closer without resolving the underlying " +"problem. Such diagnostics can guide the next experiment, but I would " +"validate any reward for \"getting closer\" against the full acceptance " +"check." +msgstr "" +"只統計透過驗收的結果,也能幫助我們合理看待中間進展。TH09 " +"的一個{ph0}錄影儲存候選方案{ph1}看起來很有希望,因為編譯後函式的大小符合預期,但完整比較仍發現大量差異。編譯器改變指令排列,也可能讓候選原始碼看起來更接近,卻沒有解決根本問題。這些診斷可以指導下一步,但若要獎勵“變得更接近”,我會先對照完整驗收檢查,確認這種獎勵有效。" + +#: website/public/blog/reverse-engineering-models/index.html:727 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"I would be interested in the pattern across these results. If a specialist " +"does well within a familiar compiler family, does that advantage survive a " +"toolchain change? And once both models have good retrieval, how much does " +"training still add? The answers would help us decide where each kind of " +"model is most useful." +msgstr "" +"我想看這些結果呈現出什麼規律。如果專用模型在熟悉的編譯器上表現很好,換了工具鏈後,這種優勢還在嗎?當雙方都擁有良好的檢索能力時,訓練還能增加多少價值?這些答案能幫助我們決定,每類模型最適合用在哪裡。" + +#: website/public/blog/reverse-engineering-models/index.html:736 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "What kind of agent does this suggest?" +msgstr "這意味著怎樣的 agent?" + +#: website/public/blog/reverse-engineering-models/index.html:737 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"If the models turn out to help at different stages, a useful arrangement " +"might be a broad agent with access to a specialist. Once a task becomes a " +"familiar compiler search, it could ask the specialist for candidates. If the" +" results stop making sense, the broader agent could return to the target " +"evidence or investigate the measurement itself." +msgstr "" +"如果不同模型在不同階段各有所長,一種有價值的安排可能是:讓能力全面的 agent " +"可以呼叫專用模型。當任務變成一種熟悉的編譯器搜尋時,它可以請專用模型提出候選方案。如果結果開始說不通,通用 agent " +"可以回頭檢查目標證據,或者調查測量本身。" + +#: website/public/blog/reverse-engineering-models/index.html:745 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"In that arrangement, specialization becomes a tool the agent can choose as " +"the investigation develops. The agent keeps the freedom to change direction " +"that made the earlier breakthroughs possible." +msgstr "" +"在這樣的安排中,專用模型成為 agent 隨著調查進展可以選擇的工具。agent 仍然擁有改變方向的自由,而這正是前面那些突破發生的重要條件。" + +#: website/public/blog/reverse-engineering-models/index.html:750 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"This follows naturally from the industrial shift I described in the previous" +" essay. Being able to run many more experiments changes how we organize the " +"work. It also gives us a reason to ask which decisions need broad judgment " +"and which improve through repeated experience with a particular craft." +msgstr "" +"這自然延續了上一篇文章中談到的工業化轉變。能夠開展更多實驗,會改變我們組織工作的方式,也讓我們有理由追問:哪些決策需要全面的判斷,哪些可以透過反覆積累某項具體技藝來改善?" + +#: website/public/blog/reverse-engineering-models/index.html:757 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"For now, the strongest general model has earned its place in my workflow by " +"opening problems I had left unresolved. Those successes are what make me " +"want to examine the work more closely: how much depended on the model's " +"breadth, and how much could be handled by a model trained in this particular" +" kind of reconstruction?" +msgstr "" +"目前,最強的通用模型解決了我過去沒能解決的問題,因此在我的工作流程中佔據了一席之地。正是這些成功,讓我想更仔細地研究過程:有多少依賴模型能力的廣度?又有多少可以交給專門學習這類重建的模型?" + +#. {ph0}: <strong > +#. {ph1}: </strong > +#: website/public/blog/reverse-engineering-models/index.html:765 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}The repositories give us a way to test the question.{ph1} I would like " +"to use that record to build the comparison and see what we learn." +msgstr "{ph0}這些程式碼倉庫讓我們有機會驗證這個問題。{ph1} 我想利用這些記錄建立對照實驗,看看我們能學到什麼。" + +#: website/public/blog/reverse-engineering-models/index.html:775 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Evidence and model attribution" +msgstr "證據與模型歸屬" + +#: website/public/blog/reverse-engineering-models/index.html:783 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The examples describe historical function-level comparisons recorded in the " +"linked commits. Whole-game runtime checks are separate milestones. Source " +"and matching records were reviewed on 13 October 2026." +msgstr "" +"這些例子來自連結中的提交中記錄的歷史函式級比較。整款遊戲的執行時檢查屬於另一個里程碑。相關原始碼與匹配記錄核查於 2026 年 10 月 13 日。" + +#. {ph0}: <code>gpt-dots</code> +#. {ph1}: <code>gpt-web</code> +#: website/public/blog/reverse-engineering-models/index.html:789 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The TH09 label {ph0} identifies GPT-6-Astra. {ph1} changed with the model " +"used at the time, so that label alone does not identify an individual run. " +"Explicit model names in the other cited commits establish their recorded " +"attribution; the histories do not contain uniform per-run cost or effort " +"measurements." +msgstr "" +"TH09 中的標籤 {ph0} 對應 GPT-6-Astra。{ph1} " +"會隨當時使用的模型變化,因此僅憑這個標籤無法確定某次執行的具體模型。其他引用提交中的明確模型名,提供了對應的歸屬記錄;這些歷史記錄並沒有統一的單次執行成本或投入統計。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/52929ed7c299f1a5f29cc13964e22510145fd616" +#. > +#. {ph5}: </a > +#: website/public/blog/reverse-engineering-models/index.html:798 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 temporary lifetimes:{ph1} the {ph2}earlier context review{ph3} and" +" {ph4}complete cold reconstruction{ph5}." +msgstr "{ph0}TH09 臨時值生命週期:{ph1}{ph2}早期上下文檢查{ph3}與{ph4}完整的乾淨重建{ph5}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/f8d12d72aaf02212ee1b585a8f3f86d7ed000269" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/da33a646221198ceb7f3df2b96e2ca0e9b2f705f" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/5f825b28a862f8e1a6d4aea2f78a42f04c09a1c0" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:810 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}TH09 Front callback:{ph1} {ph2}non-exact diagnostic regions{ph3}, " +"{ph4}Astra's new graph{ph5} and its {ph6}accepted recompile replay{ph7}." +msgstr "" +"{ph0}TH09 Front 回呼:{ph1}{ph2}未匹配的診斷區域{ph3}、{ph4}Astra " +"提出的新控制流圖{ph5}與{ph6}透過驗收的重新編譯檢查{ph7}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th095/commit/26bb64bdb093a13f73abd0ee8ae7ce199ee4658f" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th04/commit/6dce0a79d5b931f0e2a08475b90e0c33d2321b98" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/1eb843383941d00065622a9e353146c4bb96979e" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:826 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Compiler knowledge:{ph1} {ph2}TH095 identifier-bucket reuse{ph3}, " +"{ph4}TH04 player source and linker order{ph5} and {ph6}Luna's TH09 enemy-" +"spawn closure{ph7}." +msgstr "" +"{ph0}編譯器知識:{ph1}{ph2}TH095 識別符號分桶規律的複用{ph3}、{ph4}TH04 " +"玩家原始碼與連結順序{ph5}、{ph6}Luna 完成的 TH09 敵人生成函式匹配{ph7}。" + +#. {ph0}: <strong> +#. {ph1}: </strong> +#. {ph2}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/a393f400786e4cc6cbb1000af0dad3276da12c78" +#. > +#. {ph3}: </a > +#. {ph4}: <a +#. href="https://github.com/N0zoM1z0/th08/commit/af9cb1d3e839b15a78b47ac1701506083cc82847" +#. > +#. {ph5}: </a > +#. {ph6}: <a +#. href="https://github.com/N0zoM1z0/th09/commit/ab72fd77728293fc0beacfc656ca701b0e266016" +#. > +#. {ph7}: </a > +#: website/public/blog/reverse-engineering-models/index.html:842 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Checks and diagnostics:{ph1} {ph2}TH08 floating-literal audit{ph3}, " +"{ph4}TH08 numerical investigation{ph5} and {ph6}TH09 replay-save " +"reconstruction{ph7}." +msgstr "" +"{ph0}檢查與診斷:{ph1}{ph2}TH08 浮點常量審計{ph3}、{ph4}TH08 數值問題調查{ph5}、{ph6}TH09 " +"錄影儲存重建{ph7}。" + +#: website/public/blog/reverse-engineering-models/index.html:859 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"The proposed specialist and RL comparisons are future experiments. The " +"project histories motivate them; no trained specialist was evaluated for " +"this essay." +msgstr "文中提出的專用模型與 RL 對照,屬於未來實驗。專案歷史為這些想法提供了依據;本文尚未評估經過訓練的專用模型。" + +#: website/public/blog/reverse-engineering-models/index.html:6 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Does reverse engineering need a bigger model? | REA" +msgstr "逆向工程需要更大的模型嗎? | REA" + +#: website/public/blog/reverse-engineering-models/index.html:7 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"What Touhou reconstruction taught me about general models, specialist models" +" and learning to propose better hypotheses from compiler feedback." +msgstr "東方重建讓我如何思考通用模型、專用模型,以及怎樣從編譯器回饋中學會提出更好的假設。" + +#: website/public/blog/reverse-engineering-models/index.html:240 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "On this page" +msgstr "在本頁" + +#: website/public/blog/reverse-engineering-models/index.html:253 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Models and reverse engineering essay" +msgstr "模型與逆向工程隨筆" + +#: website/public/blog/reverse-engineering-models/index.html:491 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Selected reconstruction experiments" +msgstr "重建實驗選例" + +#: website/public/blog/reverse-engineering-models/index.html:883 +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "Back to top" +msgstr "回到頂部" + +#. {ph0}: <a +#. href="https://github.com/morluto/rea/blob/main/website/evidence/reverse- +#. engineering-models.md" > +#. {ph1}: </a > +#: website/public/blog/reverse-engineering-models/index.html:776 +#, python-brace-format +msgctxt "page:blog/reverse-engineering-models/index.html" +msgid "" +"{ph0}Detailed evidence notes{ph1} include the recorded comparisons and " +"experiment context." +msgstr "{ph0}詳細證據記錄{ph1}包含歷史比較結果與實驗背景。" + +#~ msgctxt "page:blog/index.html" +#~ msgid "By N0zoM1z0 · 13 October 2026 · Draft for review" +#~ msgstr "作者 N0zoM1z0 · 2026 年 10 月 13 日 · 待審草稿" + #~ msgctxt "page:index.html" #~ msgid "Setup guide" #~ msgstr "安裝指南" diff --git a/website/public/assets/dino-demo.js b/website/public/assets/dino-demo.js index ccae1598a..2421ec32b 100644 --- a/website/public/assets/dino-demo.js +++ b/website/public/assets/dino-demo.js @@ -224,9 +224,7 @@ function initializeDinoDemo(demo) { stop(t("Paused. Press Play to continue.")); }).observe(demo); } - window - .matchMedia("(prefers-color-scheme: dark)") - .addEventListener("change", draw); + window.addEventListener("website-theme-change", draw); demo.querySelector(".dino-fallback").setAttribute("hidden", ""); demo.querySelector(".dino-controls").hidden = false; canvas.hidden = false; diff --git a/website/public/assets/styles.css b/website/public/assets/styles.css index aa514ed6f..e6ed24b46 100644 --- a/website/public/assets/styles.css +++ b/website/public/assets/styles.css @@ -284,6 +284,31 @@ section[id] { align-items: center; gap: 8px; } +.theme-toggle { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 44px; + height: 44px; + padding: 0; + border: 1px solid var(--line); + border-radius: 5px; + background: var(--page); + color: var(--muted); +} +.theme-toggle:hover { + background: var(--soft); + color: var(--ink); +} +.theme-toggle[hidden], +.theme-toggle .theme-sun, +:root[data-theme="dark"] .theme-toggle .theme-moon { + display: none; +} +:root[data-theme="dark"] .theme-toggle .theme-sun { + display: block; +} .nav-github, .nav-discord, .nav-x { @@ -394,7 +419,7 @@ section[id] { font-weight: 600; } .button.home-setup-link:hover { - background: #eef3fa; + background: var(--soft); } html[dir="rtl"] .home-setup-link .button-arrow { transform: scaleX(-1); @@ -2606,96 +2631,94 @@ pre code { } } -@media (prefers-color-scheme: dark) { - :root { - color-scheme: dark; - --ink: #cdd6f4; - --muted: #a6adc8; - --line: #45475a; - --soft: #181825; - --accent: #89b4fa; - --page: #1e1e2e; - } - ::selection { - background: #45475a; - } - .dino-stage { - --dino-ground: #45475a; - --dino-ink: #a6adc8; - --dino-player: #89b4fa; - --dino-crash: #f38ba8; - --dino-eye: #181825; - } - .reconstruction-flywheel [stroke="#294f82"] { - stroke: var(--accent); - } - .reconstruction-flywheel [stroke="#5b6570"] { - stroke: var(--muted); - } - .skip-link, - .button, - .dino-buttons .button { - color: var(--page); - } - .button { - border-color: #bac2de; - background: #bac2de; - } - .button:hover { - border-color: #a6adc8; - background: #a6adc8; - } - .code-key, - .notion-channel, - .prose-highlight, - .step-selector button[aria-pressed="true"], - .percent-operation button[aria-pressed="true"], - .flow-result, - .home-nav-links a[aria-current="location"] { - background: #313244; - } - .copy-button:hover { - background: #313244; - } - .step-comparison .is-active { - background: #313244; - color: #b4befe; - } - .article p, - .article li, - .guide-route span { - color: #bac2de; - } - .prompt { - border-left-color: #585b70; - } - .agent-terminal { - border-color: var(--line); - background: #181825; - } - .terminal-header { - border-bottom-color: #313244; - } - .agent-terminal .copy-button:hover { - background: #313244; - } - .agent-one-prompt { - color: var(--ink); - } - .workflow-figure { - background: var(--soft); - } - .flow-node { - background: #313244; - border-color: #585b70; - } - .flow-steps li:not(:last-child)::after, - .notion-mini-flow li:not(:last-child)::after { - color: #9399b2; - } - .percent-controls .percent-key { - border-color: #585b70; - } +:root[data-theme="dark"] { + color-scheme: dark; + --ink: #cdd6f4; + --muted: #a6adc8; + --line: #45475a; + --soft: #181825; + --accent: #89b4fa; + --page: #1e1e2e; +} +:where(:root[data-theme="dark"]) ::selection { + background: #45475a; +} +:where(:root[data-theme="dark"]) .dino-stage { + --dino-ground: #45475a; + --dino-ink: #a6adc8; + --dino-player: #89b4fa; + --dino-crash: #f38ba8; + --dino-eye: #181825; +} +:where(:root[data-theme="dark"]) .reconstruction-flywheel [stroke="#294f82"] { + stroke: var(--accent); +} +:where(:root[data-theme="dark"]) .reconstruction-flywheel [stroke="#5b6570"] { + stroke: var(--muted); +} +:where(:root[data-theme="dark"]) .skip-link, +:where(:root[data-theme="dark"]) .button, +:where(:root[data-theme="dark"]) .dino-buttons .button { + color: var(--page); +} +:where(:root[data-theme="dark"]) .button { + border-color: #bac2de; + background: #bac2de; +} +:where(:root[data-theme="dark"]) .button:hover { + border-color: #a6adc8; + background: #a6adc8; +} +:where(:root[data-theme="dark"]) .code-key, +:where(:root[data-theme="dark"]) .notion-channel, +:where(:root[data-theme="dark"]) .prose-highlight, +:where(:root[data-theme="dark"]) .step-selector button[aria-pressed="true"], +:where(:root[data-theme="dark"]) .percent-operation button[aria-pressed="true"], +:where(:root[data-theme="dark"]) .flow-result, +:where(:root[data-theme="dark"]) .home-nav-links a[aria-current="location"] { + background: #313244; +} +:where(:root[data-theme="dark"]) .copy-button:hover { + background: #313244; +} +:where(:root[data-theme="dark"]) .step-comparison .is-active { + background: #313244; + color: #b4befe; +} +:where(:root[data-theme="dark"]) .article p, +:where(:root[data-theme="dark"]) .article li, +:where(:root[data-theme="dark"]) .guide-route span { + color: #bac2de; +} +:where(:root[data-theme="dark"]) .prompt { + border-left-color: #585b70; +} +:where(:root[data-theme="dark"]) .agent-terminal { + border-color: var(--line); + background: #181825; +} +:where(:root[data-theme="dark"]) .terminal-header { + border-bottom-color: #313244; +} +:where(:root[data-theme="dark"]) .agent-terminal .copy-button:hover { + background: #313244; +} +:where(:root[data-theme="dark"]) .agent-one-prompt { + color: var(--ink); +} +:where(:root[data-theme="dark"]) .workflow-figure { + background: var(--soft); +} +:where(:root[data-theme="dark"]) .flow-node { + background: #313244; + border-color: #585b70; +} +:where(:root[data-theme="dark"]) .flow-steps li:not(:last-child)::after, +:where(:root[data-theme="dark"]) .notion-mini-flow li:not(:last-child)::after { + color: #9399b2; +} +:where(:root[data-theme="dark"]) .percent-controls .percent-key { + border-color: #585b70; } @media (max-width: 360px) { diff --git a/website/public/assets/theme.js b/website/public/assets/theme.js new file mode 100644 index 000000000..77f51417d --- /dev/null +++ b/website/public/assets/theme.js @@ -0,0 +1,70 @@ +// This small, blocking head script applies the theme before the first paint. +(() => { + const root = document.documentElement; + const system = window.matchMedia("(prefers-color-scheme: dark)"); + const storageKey = "rea-theme"; + const parseChoice = (value) => + value === "light" || value === "dark" ? value : null; + let choice = null; + let storage = null; + try { + storage = window.localStorage; + choice = parseChoice(storage.getItem(storageKey)); + } catch { + // The switch still works when browser storage is unavailable. + } + + const applyTheme = () => { + const theme = choice ?? (system.matches ? "dark" : "light"); + root.dataset.theme = theme; + document.querySelector('meta[name="theme-color"]').content = + theme === "dark" ? "#1e1e2e" : "#ffffff"; + window.dispatchEvent(new Event("website-theme-change")); + }; + + applyTheme(); + system.addEventListener("change", () => { + if (choice === null) applyTheme(); + }); + window.addEventListener("storage", (event) => { + if ( + storage !== null && + event.storageArea === storage && + (event.key === storageKey || event.key === null) + ) { + try { + // Another tab may have written a newer choice while this event waited. + choice = parseChoice(storage.getItem(storageKey)); + } catch { + return; + } + applyTheme(); + } + }); + + document.addEventListener("DOMContentLoaded", async () => { + const button = document.querySelector("[data-theme-toggle]"); + if (button === null) return; + const { t } = await import("./i18n.js"); + const updateLabel = () => { + const label = + root.dataset.theme === "dark" + ? t("Switch to light mode") + : t("Switch to dark mode"); + button.setAttribute("aria-label", label); + button.title = label; + }; + window.addEventListener("website-theme-change", updateLabel); + button.addEventListener("click", () => { + choice = root.dataset.theme === "dark" ? "light" : "dark"; + try { + storage?.setItem(storageKey, choice); + } catch { + // Retain the choice for this page even if it cannot be saved. + } + applyTheme(); + }); + updateLabel(); + button.hidden = false; + }); +})(); diff --git a/website/public/blog/index.html b/website/public/blog/index.html index 509d85ba6..a89e27807 100644 --- a/website/public/blog/index.html +++ b/website/public/blog/index.html @@ -90,16 +90,11 @@ content="REA — Find out how software works. Reverse engineering with your coding agent." /> <!-- website:sharing:end --> - <meta - name="theme-color" - content="#ffffff" - media="(prefers-color-scheme: light)" - /> - <meta - name="theme-color" - content="#1e1e2e" - media="(prefers-color-scheme: dark)" - /> + <!-- website:theme:start --> + <meta name="theme-color" content="#ffffff" /> + <!-- Apply the saved theme before styles load, to avoid a flash on navigation. --> + <script src="../assets/theme.js"></script> + <!-- website:theme:end --> <link rel="icon" href="../assets/favicon.svg" type="image/svg+xml" /> <link rel="stylesheet" href="../assets/styles.css" /> <script src="../assets/main.js" defer></script> @@ -123,6 +118,15 @@ </nav> <div class="header-social"> <details class="language-picker" data-i18n-skip><summary><span aria-hidden="true">文 / A</span> <span>English</span></summary><nav aria-label="English"><a href="../blog/" lang="en" dir="ltr" data-language="en" aria-current="true">English</a><a href="../zh-CN/blog/" lang="zh-CN" dir="ltr" data-language="zh-CN">简体中文</a><a href="../zh-TW/blog/" lang="zh-TW" dir="ltr" data-language="zh-TW">繁體中文</a><a href="../ja/blog/" lang="ja" dir="ltr" data-language="ja">日本語</a><a href="../ko/blog/" lang="ko" dir="ltr" data-language="ko">한국어</a><a href="../tr/blog/" lang="tr" dir="ltr" data-language="tr">Türkçe</a><a href="../ru/blog/" lang="ru" dir="ltr" data-language="ru">Русский</a><a href="../vi/blog/" lang="vi" dir="ltr" data-language="vi">Tiếng Việt</a><a href="../th/blog/" lang="th" dir="ltr" data-language="th">ไทย</a><a href="../de/blog/" lang="de" dir="ltr" data-language="de">Deutsch</a><a href="../es/blog/" lang="es" dir="ltr" data-language="es">Español</a><a href="../fr/blog/" lang="fr" dir="ltr" data-language="fr">Français</a><a href="../uk/blog/" lang="uk" dir="ltr" data-language="uk">Українська</a><a href="../pl/blog/" lang="pl" dir="ltr" data-language="pl">Polski</a><a href="../pt-BR/blog/" lang="pt-BR" dir="ltr" data-language="pt-BR">Português (Brasil)</a><a href="../ar/blog/" lang="ar" dir="rtl" data-language="ar">العربية</a><a href="../fa/blog/" lang="fa" dir="rtl" data-language="fa">فارسی</a><a href="../id/blog/" lang="id" dir="ltr" data-language="id">Bahasa Indonesia</a><a href="../it/blog/" lang="it" dir="ltr" data-language="it">Italiano</a></nav></details> + <button class="theme-toggle" type="button" data-theme-toggle hidden> + <svg class="theme-moon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> + <path d="M20.9 13a9 9 0 0 1-9.9-9.9A9 9 0 1 0 20.9 13Z" /> + </svg> + <svg class="theme-sun" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true" focusable="false"> + <circle cx="12" cy="12" r="4" /> + <path d="M12 2v2m0 16v2M2 12h2m16 0h2M4.93 4.93l1.42 1.42m11.3 11.3 1.42 1.42M4.93 19.07l1.42-1.42m11.3-11.3 1.42-1.42" /> + </svg> + </button> <a class="nav-github" href="https://github.com/morluto/rea" @@ -192,6 +196,20 @@ <p class="lede">Thoughts on reverse engineering.</p> </div> <div class="guide-index"> + <section class="guide-entry"> + <p class="eyebrow">Model specialization<br />Essay</p> + <div> + <h2>Does reverse engineering need a bigger model?</h2> + <p> + What Touhou reconstruction suggests about general models, + specialist models and learning from compiler feedback. + </p> + <a class="text-link" href="reverse-engineering-models/" + >Read the article</a + > + <p class="page-meta">By N0zoM1z0 · 13 October 2026</p> + </div> + </section> <section class="guide-entry"> <p class="eyebrow">Game reconstruction<br />Essay</p> <div> diff --git a/website/public/blog/reverse-engineering-models/index.html b/website/public/blog/reverse-engineering-models/index.html new file mode 100644 index 000000000..a92f9f84f --- /dev/null +++ b/website/public/blog/reverse-engineering-models/index.html @@ -0,0 +1,888 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <title>Does reverse engineering need a bigger model? | REA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +

Essay

+

Does reverse engineering need a bigger model?

+

By N0zoM1z0 · 13 October 2026

+
+

Takeaway

+
    +
  • + Model capability changes the hypotheses an agent can + find. + Later sessions have solved problems that earlier work left + unresolved. +
  • +
  • + A familiar compiler gives specialization something concrete to + learn. + Some exact matches depend on narrow, reusable source patterns. +
  • +
  • + Give repository knowledge a fair comparison. + A smaller model with good retrieval may already know enough to + make progress. +
  • +
  • + Train the next useful experiment, and test its oracle. + The value of feedback depends on what the checker actually + verifies. +
  • +
  • + Measure accepted reconstruction against time and cost. + That is the result I want from the whole agent. +
  • +
+
+
+
+ +
+
+

What better models changed

+

+ Since August 2026, I have been exploring how much reverse + engineering an agent can carry out with access to a program and a + way to check its work. Most of my experience comes from + reconstructing games, especially Touhou. As I have changed models, + the repositories have kept a record of what each session managed + to recover. +

+

+ Much of that work aims at exact reconstruction: we compile the + maintained source under a pinned historical toolchain and check + whether it reproduces the target function. When a later model + succeeds where earlier work stalled, the source changes show what + made that progress possible. +

+

The temporary values had to stay alive together

+

+ Much of a TH09 attack function's logic had already been + reconstructed, but the compiler still stored temporary results + differently from the original. The remaining problem was how long + those results needed to stay alive and when their storage could be + reused. +

+

+ A + GPT-6-Sol checkpoint + recorded this mismatch after testing several ordinary source + arrangements. When + GPT-6.1-Sol returned to the problem, it found a useful hypothesis about how long those temporary + values needed to stay alive. +

+

+ The function produced temporary results and copied them into + animation positions. In C++, a temporary result stays alive until + the expression using it finishes. Grouping the real operations + into one expression kept those results alive together, so the + compiler could no longer reuse the same storage for all of them. +

+

+ One result still shared storage with a value used later for + collision checks. Giving that value its own lifetime resolved the + remaining overlap. After several targeted experiments, + a clean rebuild confirmed that the full function + matched. +

+

+ What interests me is how the discovery and the tests worked + together. The lifetime hypothesis gave the agent a new direction; + compiler feedback helped it refine that hypothesis into a source + arrangement that matched. +

+

A different control-flow graph

+

+ A second TH09 function shows why that new direction can matter. + Here, the obstacle was how several branches shared their final + work. + GPT-6.1-Sol's earlier work + got parts of the function to match, but the branches still joined + up differently from the original. +

+

+ GPT-6-Astra changed the surrounding control-flow graph. The main paths now led to a shared final update and return. In + that source structure, the compiler combined the branches in the + same way as the original. The complete function matched, and a + separate rebuild check confirmed it. +

+

+ Changing the representation opened a more productive search + space. + Both cases give me a reason to take general model capability + seriously: an agent can keep trying local variations for a long + time before finding a better way to express the surrounding work. +

+

+ At the same time, the later sessions started with earlier source + and recorded failures. That accumulated work was part of their + advantage. The history lets us inspect the discoveries and their + checks; a controlled comparison would help separate the effect of + the model from the experience it inherited. +

+

+ This is where the question becomes interesting to me. Some of the + progress came from finding a new representation, while much of the + remaining work involved testing source forms against a familiar + compiler. How much needs broad reasoning ability, and how much + could a model learn through repeated experience with that compiler + and code? +

+
+
+

Why might a specialist do well?

+

+ Touhou gives us a concrete reason to expect that experience to + help. Much of the game code comes from the same author, ZUN, so + recurring habits are a reasonable starting assumption. The + repositories back that up with useful examples: related loops and + helper arrangements have supplied hypotheses across games. +

+

+ Those source patterns become more specific when we include the + compiler. Under a particular version and set of options, small + changes in source can produce repeatable differences in machine + code. Some of those differences are surprisingly obscure. +

+

+ In TH095, for example, + even the name used for a local variable could change where + VC7.1 stored it. Moving the declaration alone did not solve the layout, but an + earlier background function had revealed a naming pattern that + affected the compiler's choice. That gave us a more promising + hypothesis for + the reconstruction of Supervisor::LoadDat. +

+

+ Reusing that pattern for the file-size variable produced the + required layout without adding storage. The full function then + matched. +

+

+ This is the sort of narrow detail a general model may not know + when it arrives. A specialist trained on this compiler could + encounter many such cases and learn which source variations are + worth testing first. +

+

+ The opportunity is especially clear in final matching problems + where we already understand the behavior. We are then asking which + ordinary source form this compiler turns into the observed + instructions. Specialization could help the model propose those + forms more efficiently, while the target still determines which + hypotheses survive. +

+

+ The useful patterns would have to retain their context, though. + TH08 uses an earlier Visual C++ version than TH095 and TH09. TH04 + uses a different DOS-era compiler, and its + player reconstruction + needed different hypotheses about source patterns and how the + compiled code was combined into an executable. Shared authorship + gives us a prior, but each target tells us whether it applies. + Distinguishing those contexts is part of what a specialist would + need to learn. +

+
+
+

Where should that experience live?

+

+ Before deciding to teach those patterns through model training, I + would look at the knowledge we already keep in the repository. In + the + previous essay, I wrote + about it becoming the project's working memory. That memory + includes compiler lessons, along with the source and failed + experiments that made them useful. +

+

+ By retrieving that record, an agent can start with a known result + and inspect how we reached it. It can also avoid alternatives that + have already failed in the same context. The starting point + improves without changing the model's weights. +

+

+ When reconstructing TH09's enemy-spawn function, a + GPT-6-Luna-max session + drew a hypothesis from TH08's corresponding source family. That + earlier source suggested how to structure the loop and handle + failures within it. TH09's own evidence supplied the game-specific + details, and clean rebuilds confirmed the complete match. +

+

+ "The model did not know that compiler quirk" and "the model + could not use it" are different problems. + Retrieval may solve the first, but turning that fact into a useful + candidate still takes work. And if the candidate fails, the model + must decide what the result means for its next attempt. Knowing + the relevant pattern is only the beginning of that process. +

+

+ For that reason, I would include a smaller general model with good + retrieval in any comparison. Giving it the same library of + experience would help us identify what training adds: better + candidate generation, better decisions after feedback, or both. +

+
+
+

Learning the next useful experiment

+

+ Those decisions after feedback are what I would most like to + study. In agentic reconstruction, the model proposes an + explanation and tests it against the program. Even when the + candidate fails, the result can narrow the remaining possibilities + and suggest a more useful next experiment. +

+

+ Consider the temporary-results example again. Its final source + shows the arrangement that worked, but the route to that source + contains more information. Each of the following experiments + helped identify what still needed to change. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ExperimentWhat its result taught us
Try a different way to copy the results + The copy code changes, but the function still differs. +
Use the returned values directly + Copying follows the original pattern, but temporary + storage still differs. +
Keep the temporary results alive together + They get separate storage, but one still overlaps a value + used later for collision checks. +
Keep the collision-check value separateA clean rebuild confirms the complete match.
+
+

+ Selected experiments from the attack-function reconstruction + above, grouped by what they taught us. +

+

+ A training record that keeps this sequence can teach more than the + final source alone. It connects each proposed change to an + observed result and the next decision. Keeping ineffective + variations matters too: they tell a later agent which hypotheses + have already been tested in that context. +

+

+ I would want the model to learn how to use feedback. + A neutral result is a reason to reconsider the variation; a + changed mismatch may point to another cause. When local edits stop + being informative, the agent should be able to revisit the source + representation or inspect the evidence again. +

+

+ Learning to make those choices requires autonomy. Sometimes the + useful next step is inspecting another caller rather than + compiling another edit. A rigid sequence of required rewrites + would remove that choice, along with part of the behavior we want + the model to learn. +

+
+
+

Why RE is interesting for reinforcement learning

+

+ Bounded reconstruction gives us a practical environment for + studying these choices. Once the target and compiler are pinned, + many source experiments produce quick, repeatable feedback. The + agent can compile a candidate, inspect the mismatch and use that + observation to choose its next step. +

+

+ Reinforcement learning could train that decision-making process + through the feedback it receives. A candidate accepted by a + defined check gives us a concrete outcome, while the sequence of + attempts lets us observe how much work it took to reach it. +

+

+ There is already research supporting this direction. + LLM4Decompile + studies models specialized for decompilation. + AutoDecompiler + trains multi-turn refinement using compiler and execution + feedback. Their studies focus on functional recovery. For this + work, I would use them as a starting point for the related task of + finding source that matches a historical compiler's output. +

+

+ To reach such a well-defined task, though, we may first need to + establish what a function owns or devise a new runtime + measurement. In TH08, for example, a + collision difference led back to how the original program + handled floating-point calculations. Before the agent could test a useful correction, it had to work + out what to measure. +

+

+ This suggests another role for a broadly capable model: helping + make the problem checkable in the first place. Once that check + exists, we can investigate how far a learned search policy can get + with it. +

+
+
+

When the oracle is wrong

+

+ Once we train against that check, its coverage becomes part of + what the model learns. I call the reference or checker an oracle. + Even if it gives a repeatable answer, we still need to understand + what that answer covers. +

+

+ TH08 showed how much can hide outside that coverage. Some + reconstructed functions passed their exact comparisons with wrong + floating constants. The comparator adjusted relocated addresses + before checking instructions, but it checked the values behind + those addresses only when they had been explicitly recorded for + verification. Other literal references could pass without their + values being examined. +

+

+ To close that gap, a + wider audit + found incorrect constants in functions that had already been + accepted. In one calculation, the reconstructed source added + 1.0f where the original added 32.0f. +

+

+ A learner rewarded by the old check could learn to produce the + wrong reconstruction. + We had not trained an RL model against this oracle; the observed + failure was in the check itself. But using that check as a reward + would have made the same blind spot part of the learning + environment. +

+

+ A functional test can have a similar blind spot. + Differential-fuzzing research on LLM decompilers + has found behavior differences beyond the supplied tests. Passing + those tests therefore needs to be read in terms of the cases they + exercise, just as an instruction match needs to be read in terms + of the bytes and data it checks. +

+

+ Before using either kind of check as a reward, I would test it + with deliberate failures. I would also keep final acceptance + outside the candidate's editable source, so the model has to + satisfy the check through its reconstruction. Otherwise, something + like a byte array copied from the target could satisfy a naive + score without recovering useful source. +

+

+ Improving the learner and improving its oracle belong to the + same research problem. + As the learner gets better at optimizing the feedback we give it, + understanding that feedback becomes more important too. +

+
+
+

A comparison worth running

+

+ With those checks in place, I would start the comparison on a + fixed VC7.1 task family. First, I would establish baselines for a + strong general model and a smaller one. Adding repository + knowledge to the smaller model would show what retrieval changes. + From there, supervised specialization and an RL-trained version + would let us examine what training adds. +

+

+ To make those comparisons informative, each model would receive + the same target evidence and tools. For the training-specific + comparisons, I would keep the base model and available knowledge + fixed as well. Repeated trials would help distinguish a reliable + search strategy from a lucky candidate. +

+

+ I would then separate two starting conditions: reconstructing a + function from its instructions, and closing the last few + differences in maintained source. A specialist might be excellent + at the second task while a general model does much of the work + needed to reach it. Measuring them separately would reveal that + division of work. +

+

+ Both tasks need genuinely held-out examples. Because related + Touhou games share engine code, holding out a game's name would + still allow nearly identical functions to appear in training. I + would instead hold out source families and keep their accepted + answers out of both training and retrieval. +

+

+ On those examples, the outcome would be complete, independently + validated matches. Giving each model the same candidate or compile + budget would help compare search quality. Measuring elapsed time + and total cost, including compilation, would tell us whether that + quality produces an efficient workflow. Training costs would need + their own accounting too. +

+

+ Both views matter because a cheaper proposal can become an + expensive workflow if it causes more uninformative compiles. + Conversely, a slower model may pay for itself by finding a useful + experiment sooner. The comparison should capture those costs. +

+

+ Counting accepted results also keeps intermediate progress in + perspective. One TH09 + replay-save candidate + looked promising because the compiled function had the expected + size, but a full comparison still found substantial differences. + Changes in how the compiler arranges instructions can also make a + candidate look closer without resolving the underlying problem. + Such diagnostics can guide the next experiment, but I would + validate any reward for "getting closer" against the full + acceptance check. +

+

+ I would be interested in the pattern across these results. If a + specialist does well within a familiar compiler family, does that + advantage survive a toolchain change? And once both models have + good retrieval, how much does training still add? The answers + would help us decide where each kind of model is most useful. +

+
+
+

What kind of agent does this suggest?

+

+ If the models turn out to help at different stages, a useful + arrangement might be a broad agent with access to a specialist. + Once a task becomes a familiar compiler search, it could ask the + specialist for candidates. If the results stop making sense, the + broader agent could return to the target evidence or investigate + the measurement itself. +

+

+ In that arrangement, specialization becomes a tool the agent can + choose as the investigation develops. The agent keeps the freedom + to change direction that made the earlier breakthroughs possible. +

+

+ This follows naturally from the industrial shift I described in + the previous essay. Being able to run many more experiments + changes how we organize the work. It also gives us a reason to ask + which decisions need broad judgment and which improve through + repeated experience with a particular craft. +

+

+ For now, the strongest general model has earned its place in my + workflow by opening problems I had left unresolved. Those + successes are what make me want to examine the work more closely: + how much depended on the model's breadth, and how much could be + handled by a model trained in this particular kind of + reconstruction? +

+

+ The repositories give us a way to test the question. + I would like to use that record to build the comparison and see + what we learn. +

+
+
+
+ Evidence and model attribution +

+ Detailed evidence notes + include the recorded comparisons and experiment context. +

+

+ The examples describe historical function-level comparisons + recorded in the linked commits. Whole-game runtime checks are + separate milestones. Source and matching records were reviewed + on 13 October 2026. +

+

+ The TH09 label gpt-dots identifies GPT-6-Astra. + gpt-web changed with the model used at the time, so + that label alone does not identify an individual run. Explicit + model names in the other cited commits establish their recorded + attribution; the histories do not contain uniform per-run cost + or effort measurements. +

+ +

+ The proposed specialist and RL comparisons are future + experiments. The project histories motivate them; no trained + specialist was evaluated for this essay. +

+
+
+
+
+
+ + + +

+ + Top + + + + diff --git a/website/public/blog/touhou-reconstruction/index.html b/website/public/blog/touhou-reconstruction/index.html index 9e2051c6b..93de87e90 100644 --- a/website/public/blog/touhou-reconstruction/index.html +++ b/website/public/blog/touhou-reconstruction/index.html @@ -90,16 +90,11 @@ content="REA — Find out how software works. Reverse engineering with your coding agent." /> - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -124,6 +119,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ application workflow to follow files and process boundaries.

+

+ For HTTP request and response bodies, use + Fiddler Everywhere: SAZ captures, MCP and public skills. Export SAZ or HAR 1.2 for offline REA capture Evidence, or + connect Everywhere's MCP server to inspect captured traffic with + your agent. +

diff --git a/website/public/guides/index.html b/website/public/guides/index.html index ebf5581bf..5c0ee4052 100644 --- a/website/public/guides/index.html +++ b/website/public/guides/index.html @@ -90,16 +90,11 @@ content="REA — Find out how software works. Reverse engineering with your coding agent." /> - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -125,6 +120,15 @@
English
+ - - + + + + + @@ -124,6 +119,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@
English
+ - - + + + + + @@ -123,6 +118,15 @@